summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/device-drivers.tmpl12
-rw-r--r--Documentation/devicetree/bindings/sound/alc5632.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audmux.txt13
-rw-r--r--Documentation/devicetree/bindings/sound/sgtl5000.txt (renamed from Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt)0
-rw-r--r--Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt59
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/driver-model/devres.txt3
-rw-r--r--Documentation/input/event-codes.txt72
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt8
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt79
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt7
-rw-r--r--Documentation/sysctl/kernel.txt2
-rw-r--r--MAINTAINERS56
-rw-r--r--Makefile2
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi1
-rw-r--r--arch/arm/boot/dts/tegra-paz00.dts6
-rw-r--r--arch/arm/include/asm/tlb.h10
-rw-r--r--arch/arm/kernel/entry-armv.S2
-rw-r--r--arch/arm/kernel/perf_event_v7.c28
-rw-r--r--arch/arm/kernel/ptrace.c8
-rw-r--r--arch/arm/kernel/signal.c5
-rw-r--r--arch/arm/kernel/traps.c5
-rw-r--r--arch/arm/kernel/vmlinux.lds.S1
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c9
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c8
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9_smc.h29
-rw-r--r--arch/arm/mach-at91/sam9_smc.c76
-rw-r--r--arch/arm/mach-at91/sam9_smc.h23
-rw-r--r--arch/arm/mach-bcmring/arch.c2
-rw-r--r--arch/arm/mach-bcmring/dma.c812
-rw-r--r--arch/arm/mach-bcmring/include/mach/dma.h196
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-neuros-osd2.c2
-rw-r--r--arch/arm/mach-davinci/board-omapl138-hawk.c2
-rw-r--r--arch/arm/mach-davinci/board-sffsdr.c2
-rw-r--r--arch/arm/mach-davinci/da850.c32
-rw-r--r--arch/arm/mach-dove/common.c3
-rw-r--r--arch/arm/mach-ep93xx/core.c19
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h2
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c4
-rw-r--r--arch/arm/mach-exynos/clock-exynos4210.c2
-rw-r--r--arch/arm/mach-exynos/clock-exynos4212.c2
-rw-r--r--arch/arm/mach-exynos/clock.c2
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c8
-rw-r--r--arch/arm/mach-exynos/mach-nuri.c8
-rw-r--r--arch/arm/mach-exynos/mach-universal_c210.c2
-rw-r--r--arch/arm/mach-exynos/pm.c4
-rw-r--r--arch/arm/mach-imx/Kconfig6
-rw-r--r--arch/arm/mach-imx/eukrea_mbimx27-baseboard.c20
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c1
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c17
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c17
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c1
-rw-r--r--arch/arm/mach-imx/mach-pca100.c13
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c13
-rw-r--r--arch/arm/mach-imx/mm-imx21.c6
-rw-r--r--arch/arm/mach-imx/mm-imx25.c7
-rw-r--r--arch/arm/mach-imx/mm-imx27.c7
-rw-r--r--arch/arm/mach-imx/mm-imx3.c13
-rw-r--r--arch/arm/mach-imx/mm-imx5.c22
-rw-r--r--arch/arm/mach-kirkwood/common.c3
-rw-r--r--arch/arm/mach-kirkwood/mpp.h320
-rw-r--r--arch/arm/mach-kirkwood/openrd-setup.c6
-rw-r--r--arch/arm/mach-kirkwood/t5325-setup.c6
-rw-r--r--arch/arm/mach-mv78xx0/common.c3
-rw-r--r--arch/arm/mach-mv78xx0/mpp.h226
-rw-r--r--arch/arm/mach-omap1/Kconfig3
-rw-r--r--arch/arm/mach-omap1/Makefile4
-rw-r--r--arch/arm/mach-omap1/devices.c9
-rw-r--r--arch/arm/mach-omap1/mcbsp.c14
-rw-r--r--arch/arm/mach-omap2/Kconfig11
-rw-r--r--arch/arm/mach-omap2/Makefile8
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c64
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c2
-rw-r--r--arch/arm/mach-omap2/board-generic.c4
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c23
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c84
-rw-r--r--arch/arm/mach-omap2/board-zoom-peripherals.c6
-rw-r--r--arch/arm/mach-omap2/devices.c23
-rw-r--r--arch/arm/mach-omap2/display.c4
-rw-r--r--arch/arm/mach-omap2/gpmc.c6
-rw-r--r--arch/arm/mach-omap2/hsmmc.c24
-rw-r--r--arch/arm/mach-omap2/io.c4
-rw-r--r--arch/arm/mach-omap2/mcbsp.c54
-rw-r--r--arch/arm/mach-omap2/mux.c22
-rw-r--r--arch/arm/mach-omap2/omap-headsmp.S1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c16
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c21
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c22
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c54
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c2
-rw-r--r--arch/arm/mach-omap2/pm24xx.c8
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c1
-rw-r--r--arch/arm/mach-omap2/prm44xx.c1
-rw-r--r--arch/arm/mach-omap2/serial.c8
-rw-r--r--arch/arm/mach-omap2/smartreflex.c2
-rw-r--r--arch/arm/mach-omap2/timer.c2
-rw-r--r--arch/arm/mach-omap2/vc.c10
-rw-r--r--arch/arm/mach-omap2/vp.c5
-rw-r--r--arch/arm/mach-orion5x/common.c4
-rw-r--r--arch/arm/mach-s3c2410/cpu-freq.c8
-rw-r--r--arch/arm/mach-s3c2410/dma.c5
-rw-r--r--arch/arm/mach-s3c2410/pll.c2
-rw-r--r--arch/arm/mach-s3c2410/pm.c2
-rw-r--r--arch/arm/mach-s3c2412/cpu-freq.c3
-rw-r--r--arch/arm/mach-s3c2412/dma.c3
-rw-r--r--arch/arm/mach-s3c2412/irq.c2
-rw-r--r--arch/arm/mach-s3c2412/pm.c2
-rw-r--r--arch/arm/mach-s3c2416/irq.c3
-rw-r--r--arch/arm/mach-s3c2416/pm.c2
-rw-r--r--arch/arm/mach-s3c2440/clock.c2
-rw-r--r--arch/arm/mach-s3c2440/dma.c3
-rw-r--r--arch/arm/mach-s3c2440/irq.c2
-rw-r--r--arch/arm/mach-s3c2440/s3c2440-cpufreq.c3
-rw-r--r--arch/arm/mach-s3c2440/s3c2440-pll-12000000.c2
-rw-r--r--arch/arm/mach-s3c2440/s3c2440-pll-16934400.c3
-rw-r--r--arch/arm/mach-s3c2440/s3c2442.c2
-rw-r--r--arch/arm/mach-s3c2440/s3c244x-clock.c2
-rw-r--r--arch/arm/mach-s3c2440/s3c244x-irq.c2
-rw-r--r--arch/arm/mach-s3c2443/dma.c3
-rw-r--r--arch/arm/mach-s3c2443/irq.c3
-rw-r--r--arch/arm/mach-s3c64xx/clock.c5
-rw-r--r--arch/arm/mach-s3c64xx/common.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410-module.c1
-rw-r--r--arch/arm/mach-s5p64x0/pm.c2
-rw-r--r--arch/arm/mach-s5pv210/clock.c4
-rw-r--r--arch/arm/mach-s5pv210/pm.c2
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c30
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c18
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c2
-rw-r--r--arch/arm/mach-tegra/board-paz00.c8
-rw-r--r--arch/arm/mach-tegra/board-paz00.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/dma.h10
-rw-r--r--arch/arm/mm/cache-v7.S6
-rw-r--r--arch/arm/mm/ioremap.c3
-rw-r--r--arch/arm/plat-mxc/Kconfig6
-rw-r--r--arch/arm/plat-mxc/Makefile2
-rw-r--r--arch/arm/plat-mxc/audmux-v1.c64
-rw-r--r--arch/arm/plat-mxc/include/mach/audmux.h60
-rw-r--r--arch/arm/plat-omap/Kconfig8
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h333
-rw-r--r--arch/arm/plat-omap/include/plat/omap-secure.h2
-rw-r--r--arch/arm/plat-orion/common.c9
-rw-r--r--arch/arm/plat-orion/include/plat/common.h3
-rw-r--r--arch/arm/plat-orion/mpp.c3
-rw-r--r--arch/arm/plat-samsung/devs.c4
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/microblaze/kernel/setup.c21
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/jz4740/board-qi_lb60.c6
-rw-r--r--arch/mips/lib/iomap-pci.c4
-rw-r--r--arch/powerpc/configs/ppc64_defconfig5
-rw-r--r--arch/powerpc/include/asm/ppc-pci.h5
-rw-r--r--arch/powerpc/include/asm/ptrace.h20
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S2
-rw-r--r--arch/powerpc/kernel/irq.c6
-rw-r--r--arch/powerpc/kernel/perf_event.c8
-rw-r--r--arch/powerpc/kernel/process.c6
-rw-r--r--arch/powerpc/kernel/rtas.c5
-rw-r--r--arch/powerpc/platforms/powernv/pci.c22
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c4
-rw-r--r--arch/powerpc/platforms/pseries/suspend.c6
-rw-r--r--arch/powerpc/platforms/wsp/ics.c2
-rw-r--r--arch/powerpc/platforms/wsp/wsp_pci.c8
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c48
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c4
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c4
-rw-r--r--arch/sh/drivers/pci/pci.c4
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/lib/divdi3.S16
-rw-r--r--arch/x86/include/asm/cmpxchg.h6
-rw-r--r--arch/x86/include/asm/i387.h284
-rw-r--r--arch/x86/include/asm/kvm_emulate.h16
-rw-r--r--arch/x86/include/asm/processor.h1
-rw-r--r--arch/x86/include/asm/thread_info.h2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c1
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c2
-rw-r--r--arch/x86/kernel/dumpstack.c3
-rw-r--r--arch/x86/kernel/dumpstack_64.c8
-rw-r--r--arch/x86/kernel/process_32.c25
-rw-r--r--arch/x86/kernel/process_64.c29
-rw-r--r--arch/x86/kernel/reboot.c36
-rw-r--r--arch/x86/kernel/traps.c41
-rw-r--r--arch/x86/kernel/xsave.c12
-rw-r--r--arch/x86/kvm/emulate.c51
-rw-r--r--arch/x86/kvm/vmx.c2
-rw-r--r--arch/x86/kvm/x86.c45
-rw-r--r--arch/x86/mm/fault.c4
-rw-r--r--arch/x86/pci/xen.c2
-rw-r--r--arch/x86/xen/smp.c7
-rw-r--r--arch/xtensa/include/asm/string.h3
-rw-r--r--block/blk-cgroup.c2
-rw-r--r--block/blk-core.c33
-rw-r--r--block/blk-ioc.c111
-rw-r--r--block/blk-merge.c37
-rw-r--r--block/blk.h2
-rw-r--r--block/bsg.c3
-rw-r--r--block/cfq-iosched.c24
-rw-r--r--block/elevator.c55
-rw-r--r--crypto/sha512_generic.c83
-rw-r--r--drivers/acpi/processor_driver.c7
-rw-r--r--drivers/ata/pata_at91.c48
-rw-r--r--drivers/base/cpu.c21
-rw-r--r--drivers/base/memory.c31
-rw-r--r--drivers/base/node.c8
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regcache.c15
-rw-r--r--drivers/base/regmap/regmap.c73
-rw-r--r--drivers/bcma/main.c4
-rw-r--r--drivers/bcma/scan.c19
-rw-r--r--drivers/block/floppy.c17
-rw-r--r--drivers/block/loop.c24
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c11
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h5
-rw-r--r--drivers/block/rbd.c7
-rw-r--r--drivers/cdrom/cdrom.c20
-rw-r--r--drivers/dma/at_hdmac.c4
-rw-r--r--drivers/dma/at_hdmac_regs.h17
-rw-r--r--drivers/dma/dmatest.c2
-rw-r--r--drivers/dma/imx-sdma.c6
-rw-r--r--drivers/dma/shdma.c3
-rw-r--r--drivers/firewire/ohci.c6
-rw-r--r--drivers/gpio/gpio-lpc32xx.c2
-rw-r--r--drivers/gpio/gpio-ml-ioh.c1
-rw-r--r--drivers/gpio/gpio-pch.c1
-rw-r--r--drivers/gpio/gpio-samsung.c23
-rw-r--r--drivers/gpu/drm/drm_ioc32.c3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c8
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c20
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mxm.c9
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c4
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c4
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c18
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c1
-rw-r--r--drivers/gpu/drm/radeon/r100.c4
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_kms.c35
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c17
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c1
-rw-r--r--drivers/gpu/drm/radeon/rs600.c4
-rw-r--r--drivers/hid/hid-hyperv.c1
-rw-r--r--drivers/hid/hid-wacom.c7
-rw-r--r--drivers/hid/hid-wiimote-core.c4
-rw-r--r--drivers/hid/usbhid/hiddev.c4
-rw-r--r--drivers/hwmon/f75375s.c11
-rw-r--r--drivers/hwmon/w83627ehf.c28
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/ide/Makefile1
-rw-r--r--drivers/ide/at91_ide.c366
-rw-r--r--drivers/infiniband/core/ucma.c5
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c1
-rw-r--r--drivers/infiniband/core/verbs.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c2
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c7
-rw-r--r--drivers/infiniband/hw/nes/nes.c2
-rw-r--r--drivers/infiniband/hw/nes/nes.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c10
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_context.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_user.h2
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c6
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h2
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_pcie.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c55
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c10
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c17
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.h1
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/keyboard/twl4030_keypad.c4
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/serio/serio_raw.c15
-rw-r--r--drivers/iommu/amd_iommu.c3
-rw-r--r--drivers/iommu/msm_iommu.c7
-rw-r--r--drivers/isdn/i4l/isdn_net.c2
-rw-r--r--drivers/leds/leds-lm3530.c4
-rw-r--r--drivers/macintosh/adb.c4
-rw-r--r--drivers/md/dm-raid.c12
-rw-r--r--drivers/md/md.c5
-rw-r--r--drivers/mfd/Kconfig2
-rw-r--r--drivers/mfd/twl-core.c6
-rw-r--r--drivers/mfd/twl4030-power.c20
-rw-r--r--drivers/mfd/twl6040-core.c128
-rw-r--r--drivers/misc/Kconfig17
-rw-r--r--drivers/misc/c2port/c2port-duramar2150.c1
-rw-r--r--drivers/misc/cb710/core.c1
-rw-r--r--drivers/misc/cs5535-mfgpt.c2
-rw-r--r--drivers/misc/lkdtm.c6
-rw-r--r--drivers/misc/vmw_balloon.c14
-rw-r--r--drivers/mmc/card/block.c1
-rw-r--r--drivers/mmc/core/core.c49
-rw-r--r--drivers/mmc/core/host.h21
-rw-r--r--drivers/mmc/core/mmc.c26
-rw-r--r--drivers/mmc/core/sd.c22
-rw-r--r--drivers/mmc/core/sdio.c7
-rw-r--r--drivers/mmc/core/sdio_irq.c10
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/atmel-mci.c3
-rw-r--r--drivers/mmc/host/dw_mmc.c144
-rw-r--r--drivers/mmc/host/of_mmc_spi.c4
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c32
-rw-r--r--drivers/mmc/host/sdhci-pci.c2
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c10
-rw-r--r--drivers/mmc/host/sh_mmcif.c16
-rw-r--r--drivers/mmc/host/tmio_mmc.h7
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c12
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c6
-rw-r--r--drivers/mtd/mtdcore.c2
-rw-r--r--drivers/mtd/nand/atmel_nand.c45
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c18
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--drivers/net/can/cc770/cc770.c4
-rw-r--r--drivers/net/can/cc770/cc770_isa.c16
-rw-r--r--drivers/net/can/flexcan.c7
-rw-r--r--drivers/net/can/pch_can.c3
-rw-r--r--drivers/net/can/sja1000/peak_pci.c23
-rw-r--r--drivers/net/can/ti_hecc.c3
-rw-r--r--drivers/net/can/usb/ems_usb.c9
-rw-r--r--drivers/net/ethernet/3com/3c59x.c2
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c17
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c8
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c10
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c6
-rw-r--r--drivers/net/ethernet/freescale/fec.c4
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c10
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c3
-rw-r--r--drivers/net/ethernet/intel/igbvf/Makefile2
-rw-r--r--drivers/net/ethernet/intel/igbvf/defines.h2
-rw-r--r--drivers/net/ethernet/intel/igbvf/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h2
-rw-r--r--drivers/net/ethernet/intel/igbvf/mbx.c2
-rw-r--r--drivers/net/ethernet/intel/igbvf/mbx.h2
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c4
-rw-r--r--drivers/net/ethernet/intel/igbvf/regs.h2
-rw-r--r--drivers/net/ethernet/intel/igbvf/vf.c2
-rw-r--r--drivers/net/ethernet/intel/igbvf/vf.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/Makefile2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c13
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c92
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c22
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/Makefile2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/defines.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c12
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/regs.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c21
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h2
-rw-r--r--drivers/net/ethernet/marvell/skge.c71
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c21
-rw-r--r--drivers/net/ethernet/micrel/Kconfig1
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c14
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c4
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c4
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c205
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c23
-rw-r--r--drivers/net/ethernet/ti/cpmac.c4
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c3
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c2
-rw-r--r--drivers/net/ethernet/toshiba/Kconfig2
-rw-r--r--drivers/net/ethernet/via/via-velocity.c3
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c3
-rw-r--r--drivers/net/hyperv/netvsc_drv.c18
-rw-r--r--drivers/net/hyperv/rndis_filter.c32
-rw-r--r--drivers/net/tokenring/Kconfig5
-rw-r--r--drivers/net/usb/ipheth.c5
-rw-r--r--drivers/net/veth.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c1
-rw-r--r--drivers/net/wireless/mwifiex/init.c3
-rw-r--r--drivers/net/wireless/mwifiex/main.c12
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c8
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c8
-rw-r--r--drivers/pci/iov.c3
-rw-r--r--drivers/pci/probe.c5
-rw-r--r--drivers/pci/remove.c28
-rw-r--r--drivers/pci/xen-pcifront.c10
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pinctrl/core.c2
-rw-r--r--drivers/power/bq27x00_battery.c15
-rw-r--r--drivers/power/charger-manager.c4
-rw-r--r--drivers/power/lp8727_charger.c1
-rw-r--r--drivers/regulator/core.c108
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c2
-rw-r--r--drivers/rtc/rtc-at91sam9.c13
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-topcliff-pch.c6
-rw-r--r--drivers/ssb/driver_pcicore.c2
-rw-r--r--drivers/staging/Kconfig4
-rw-r--r--drivers/staging/Makefile2
-rw-r--r--drivers/staging/android/Kconfig5
-rw-r--r--drivers/staging/android/Makefile1
-rw-r--r--drivers/staging/android/android_pmem.h93
-rw-r--r--drivers/staging/android/binder.c13
-rw-r--r--drivers/staging/android/lowmemorykiller.c5
-rw-r--r--drivers/staging/android/pmem.c1345
-rw-r--r--drivers/staging/asus_oled/asus_oled.c13
-rw-r--r--drivers/staging/gma500/Kconfig33
-rw-r--r--drivers/staging/gma500/Makefile52
-rw-r--r--drivers/staging/gma500/TODO15
-rw-r--r--drivers/staging/gma500/accel_2d.c414
-rw-r--r--drivers/staging/gma500/backlight.c49
-rw-r--r--drivers/staging/gma500/cdv_device.c350
-rw-r--r--drivers/staging/gma500/cdv_device.h36
-rw-r--r--drivers/staging/gma500/cdv_intel_crt.c326
-rw-r--r--drivers/staging/gma500/cdv_intel_display.c1508
-rw-r--r--drivers/staging/gma500/cdv_intel_hdmi.c376
-rw-r--r--drivers/staging/gma500/cdv_intel_lvds.c721
-rw-r--r--drivers/staging/gma500/displays/hdmi.h33
-rw-r--r--drivers/staging/gma500/displays/pyr_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/pyr_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tpo_cmd.h35
-rw-r--r--drivers/staging/gma500/displays/tpo_vid.h33
-rw-r--r--drivers/staging/gma500/framebuffer.c856
-rw-r--r--drivers/staging/gma500/framebuffer.h48
-rw-r--r--drivers/staging/gma500/gem.c292
-rw-r--r--drivers/staging/gma500/gem_glue.c89
-rw-r--r--drivers/staging/gma500/gem_glue.h2
-rw-r--r--drivers/staging/gma500/gtt.c553
-rw-r--r--drivers/staging/gma500/gtt.h64
-rw-r--r--drivers/staging/gma500/intel_bios.c303
-rw-r--r--drivers/staging/gma500/intel_bios.h430
-rw-r--r--drivers/staging/gma500/intel_i2c.c170
-rw-r--r--drivers/staging/gma500/intel_opregion.c81
-rw-r--r--drivers/staging/gma500/mdfld_device.c714
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.c761
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.h173
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.c778
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.h154
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.c805
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.h78
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.c1014
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.h138
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.c1484
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.h184
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c1404
-rw-r--r--drivers/staging/gma500/mdfld_msic.h31
-rw-r--r--drivers/staging/gma500/mdfld_output.c171
-rw-r--r--drivers/staging/gma500/mdfld_output.h41
-rw-r--r--drivers/staging/gma500/mdfld_pyr_cmd.c558
-rw-r--r--drivers/staging/gma500/mdfld_tmd_vid.c206
-rw-r--r--drivers/staging/gma500/mdfld_tpo_cmd.c509
-rw-r--r--drivers/staging/gma500/mdfld_tpo_vid.c140
-rw-r--r--drivers/staging/gma500/medfield.h268
-rw-r--r--drivers/staging/gma500/mid_bios.c270
-rw-r--r--drivers/staging/gma500/mid_bios.h21
-rw-r--r--drivers/staging/gma500/mmu.c858
-rw-r--r--drivers/staging/gma500/mrst.h252
-rw-r--r--drivers/staging/gma500/mrst_crtc.c604
-rw-r--r--drivers/staging/gma500/mrst_device.c634
-rw-r--r--drivers/staging/gma500/mrst_hdmi.c852
-rw-r--r--drivers/staging/gma500/mrst_hdmi_i2c.c328
-rw-r--r--drivers/staging/gma500/mrst_lvds.c407
-rw-r--r--drivers/staging/gma500/power.c318
-rw-r--r--drivers/staging/gma500/power.h67
-rw-r--r--drivers/staging/gma500/psb_device.c321
-rw-r--r--drivers/staging/gma500/psb_drm.h219
-rw-r--r--drivers/staging/gma500/psb_drv.c1230
-rw-r--r--drivers/staging/gma500/psb_drv.h952
-rw-r--r--drivers/staging/gma500/psb_intel_display.c1429
-rw-r--r--drivers/staging/gma500/psb_intel_display.h28
-rw-r--r--drivers/staging/gma500/psb_intel_drv.h230
-rw-r--r--drivers/staging/gma500/psb_intel_lvds.c854
-rw-r--r--drivers/staging/gma500/psb_intel_modes.c77
-rw-r--r--drivers/staging/gma500/psb_intel_reg.h1235
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo.c1293
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo_regs.h338
-rw-r--r--drivers/staging/gma500/psb_irq.c627
-rw-r--r--drivers/staging/gma500/psb_irq.h45
-rw-r--r--drivers/staging/gma500/psb_lid.c88
-rw-r--r--drivers/staging/gma500/psb_reg.h582
-rw-r--r--drivers/staging/media/go7007/go7007-usb.c1
-rw-r--r--drivers/staging/omapdrm/Makefile1
-rw-r--r--drivers/staging/omapdrm/omap_crtc.c191
-rw-r--r--drivers/staging/omapdrm/omap_drv.c81
-rw-r--r--drivers/staging/omapdrm/omap_drv.h52
-rw-r--r--drivers/staging/omapdrm/omap_fb.c224
-rw-r--r--drivers/staging/omapdrm/omap_fbdev.c59
-rw-r--r--drivers/staging/omapdrm/omap_gem.c23
-rw-r--r--drivers/staging/omapdrm/omap_plane.c344
-rw-r--r--drivers/staging/omapdrm/omap_priv.h12
-rw-r--r--drivers/staging/pohmelfs/Kconfig20
-rw-r--r--drivers/staging/pohmelfs/Makefile3
-rw-r--r--drivers/staging/pohmelfs/config.c611
-rw-r--r--drivers/staging/pohmelfs/crypto.c878
-rw-r--r--drivers/staging/pohmelfs/dir.c1102
-rw-r--r--drivers/staging/pohmelfs/inode.c2055
-rw-r--r--drivers/staging/pohmelfs/lock.c182
-rw-r--r--drivers/staging/pohmelfs/mcache.c171
-rw-r--r--drivers/staging/pohmelfs/net.c1209
-rw-r--r--drivers/staging/pohmelfs/netfs.h919
-rw-r--r--drivers/staging/pohmelfs/path_entry.c120
-rw-r--r--drivers/staging/pohmelfs/trans.c706
-rw-r--r--drivers/staging/rtl8712/drv_types.h7
-rw-r--r--drivers/staging/rtl8712/hal_init.c62
-rw-r--r--drivers/staging/rtl8712/os_intfs.c14
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h1
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c1
-rw-r--r--drivers/staging/rtl8712/usb_intf.c10
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430.c2
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c58
-rw-r--r--drivers/staging/usbip/stub_main.c4
-rw-r--r--drivers/staging/zcache/zcache-main.c25
-rw-r--r--drivers/target/iscsi/iscsi_target.c39
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h6
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c39
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c11
-rw-r--r--drivers/target/target_core_alua.c8
-rw-r--r--drivers/target/target_core_cdb.c51
-rw-r--r--drivers/target/target_core_configfs.c12
-rw-r--r--drivers/target/target_core_device.c28
-rw-r--r--drivers/target/target_core_fabric_configfs.c4
-rw-r--r--drivers/target/target_core_iblock.c11
-rw-r--r--drivers/target/target_core_internal.h2
-rw-r--r--drivers/target/target_core_pr.c43
-rw-r--r--drivers/target/target_core_pscsi.c4
-rw-r--r--drivers/target/target_core_tpg.c3
-rw-r--r--drivers/target/target_core_transport.c124
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c9
-rw-r--r--drivers/tty/serial/8250/8250.c2
-rw-r--r--drivers/tty/serial/m32r_sio.c (renamed from drivers/tty/serial/8250/m32r_sio.c)0
-rw-r--r--drivers/tty/serial/m32r_sio.h (renamed from drivers/tty/serial/8250/m32r_sio.h)0
-rw-r--r--drivers/tty/serial/m32r_sio_reg.h (renamed from drivers/tty/serial/8250/m32r_sio_reg.h)0
-rw-r--r--drivers/tty/serial/omap-serial.c30
-rw-r--r--drivers/tty/serial/samsung.c3
-rw-r--r--drivers/tty/vt/vt_ioctl.c1
-rw-r--r--drivers/usb/gadget/f_loopback.c2
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/ehci-fsl.c11
-rw-r--r--drivers/usb/host/ehci-fsl.h1
-rw-r--r--drivers/usb/host/pci-quirks.c6
-rw-r--r--drivers/usb/musb/musb_io.h3
-rw-r--r--drivers/usb/otg/Kconfig2
-rw-r--r--drivers/usb/serial/ftdi_sio.c1
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h7
-rw-r--r--drivers/usb/serial/option.c129
-rw-r--r--drivers/usb/serial/qcserial.c16
-rw-r--r--drivers/video/atmel_lcdfb.c2
-rw-r--r--drivers/video/fsl-diu-fb.c4
-rw-r--r--drivers/video/intelfb/intelfbdrv.c1
-rw-r--r--drivers/video/omap2/dss/dispc.c2
-rw-r--r--drivers/video/omap2/dss/dpi.c5
-rw-r--r--drivers/video/omap2/dss/dsi.c2
-rw-r--r--drivers/video/omap2/dss/dss.c2
-rw-r--r--drivers/video/omap2/dss/hdmi.c5
-rw-r--r--drivers/video/omap2/dss/rfbi.c2
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h4
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c68
-rw-r--r--drivers/video/omap2/dss/venc.c2
-rw-r--r--drivers/xen/cpu_hotplug.c3
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c8
-rw-r--r--drivers/xen/xen-pciback/xenbus.c5
-rw-r--r--drivers/xen/xenbus/xenbus_dev_frontend.c4
-rw-r--r--fs/bio.c10
-rw-r--r--fs/ceph/caps.c4
-rw-r--r--fs/ceph/dir.c4
-rw-r--r--fs/ceph/mds_client.c10
-rw-r--r--fs/ceph/mds_client.h7
-rw-r--r--fs/ceph/xattr.c4
-rw-r--r--fs/cifs/Kconfig4
-rw-r--r--fs/cifs/connect.c23
-rw-r--r--fs/cifs/dir.c2
-rw-r--r--fs/cifs/sess.c11
-rw-r--r--fs/ecryptfs/crypto.c68
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h6
-rw-r--r--fs/ecryptfs/inode.c2
-rw-r--r--fs/ecryptfs/keystore.c9
-rw-r--r--fs/ecryptfs/mmap.c4
-rw-r--r--fs/ecryptfs/read_write.c4
-rw-r--r--fs/ecryptfs/super.c14
-rw-r--r--fs/exec.c33
-rw-r--r--fs/fs-writeback.c16
-rw-r--r--fs/ioprio.c2
-rw-r--r--fs/jffs2/erase.c2
-rw-r--r--fs/logfs/dev_mtd.c6
-rw-r--r--fs/nilfs2/ioctl.c2
-rw-r--r--fs/proc/base.c126
-rw-r--r--fs/xfs/kmem.h6
-rw-r--r--fs/xfs/xfs_dquot.c103
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_qm.c291
-rw-r--r--fs/xfs/xfs_qm.h14
-rw-r--r--fs/xfs/xfs_qm_stats.c4
-rw-r--r--fs/xfs/xfs_trace.h5
-rw-r--r--include/asm-generic/pci_iomap.h10
-rw-r--r--include/linux/binfmts.h3
-rw-r--r--include/linux/bitops.h20
-rw-r--r--include/linux/blkdev.h3
-rw-r--r--include/linux/cdrom.h3
-rw-r--r--include/linux/elevator.h9
-rw-r--r--include/linux/gpio_keys.h2
-rw-r--r--include/linux/hyperv.h2
-rw-r--r--include/linux/iocontext.h5
-rw-r--r--[-rwxr-xr-x]include/linux/lp8727.h0
-rw-r--r--include/linux/mfd/twl6040.h2
-rw-r--r--include/linux/mfd/wm8994/pdata.h3
-rw-r--r--include/linux/mmc/card.h4
-rw-r--r--include/linux/mmc/dw_mmc.h6
-rw-r--r--include/linux/mmc/host.h20
-rw-r--r--include/linux/mpi.h2
-rw-r--r--include/linux/mtd/mtd.h6
-rw-r--r--include/linux/perf_event.h1
-rw-r--r--include/linux/platform_data/omap-abe-twl6040.h49
-rw-r--r--include/linux/pm_qos.h14
-rw-r--r--include/linux/proportions.h4
-rw-r--r--include/linux/regmap.h4
-rw-r--r--include/linux/regulator/consumer.h12
-rw-r--r--include/linux/sched.h6
-rw-r--r--include/linux/sh_dma.h1
-rw-r--r--include/linux/usb/ch9.h2
-rw-r--r--include/net/flow.h10
-rw-r--r--include/net/netprio_cgroup.h48
-rw-r--r--include/net/route.h4
-rw-r--r--include/net/sch_generic.h9
-rw-r--r--include/net/tcp.h14
-rw-r--r--include/sound/control.h7
-rw-r--r--include/sound/core.h2
-rw-r--r--include/sound/dmaengine_pcm.h49
-rw-r--r--include/sound/max9768.h24
-rw-r--r--include/sound/pcm.h9
-rw-r--r--include/sound/sh_fsi.h12
-rw-r--r--include/sound/soc-dai.h11
-rw-r--r--include/sound/soc-dapm.h33
-rw-r--r--include/sound/soc.h45
-rw-r--r--include/sound/version.h2
-rw-r--r--include/sound/wm2200.h41
-rw-r--r--include/sound/wm8962.h6
-rw-r--r--include/sound/ymfpci.h2
-rw-r--r--include/target/target_core_backend.h4
-rw-r--r--include/target/target_core_base.h1
-rw-r--r--include/target/target_core_fabric.h2
-rw-r--r--include/trace/events/writeback.h7
-rw-r--r--include/video/omapdss.h5
-rw-r--r--kernel/events/core.c123
-rw-r--r--kernel/exit.c16
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/kprobes.c6
-rw-r--r--kernel/params.c3
-rw-r--r--kernel/power/power.h24
-rw-r--r--kernel/power/process.c7
-rw-r--r--kernel/power/user.c6
-rw-r--r--kernel/relay.c10
-rw-r--r--kernel/sched/core.c19
-rw-r--r--kernel/sched/fair.c34
-rw-r--r--kernel/sched/rt.c5
-rw-r--r--kernel/watchdog.c2
-rw-r--r--lib/Kconfig7
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bug.c2
-rw-r--r--lib/clz_tab.c18
-rw-r--r--lib/digsig.c52
-rw-r--r--lib/kstrtox.c18
-rw-r--r--lib/mpi/longlong.h44
-rw-r--r--lib/mpi/mpi-bit.c19
-rw-r--r--lib/mpi/mpi-div.c5
-rw-r--r--lib/mpi/mpi-pow.c2
-rw-r--r--lib/mpi/mpicoder.c91
-rw-r--r--lib/mpi/mpih-div.c4
-rw-r--r--lib/mpi/mpiutil.c5
-rw-r--r--lib/pci_iomap.c2
-rw-r--r--mm/backing-dev.c23
-rw-r--r--mm/compaction.c24
-rw-r--r--mm/filemap.c8
-rw-r--r--mm/filemap_xip.c7
-rw-r--r--mm/huge_memory.c4
-rw-r--r--mm/kmemleak.c3
-rw-r--r--mm/memcontrol.c3
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/process_vm_access.c23
-rw-r--r--mm/swap.c2
-rw-r--r--net/caif/caif_socket.c10
-rw-r--r--net/caif/cfmuxl.c12
-rw-r--r--net/ceph/ceph_common.c2
-rw-r--r--net/ceph/mon_client.c13
-rw-r--r--net/core/dev.c10
-rw-r--r--net/core/ethtool.c2
-rw-r--r--net/core/netpoll.c2
-rw-r--r--net/core/netprio_cgroup.c15
-rw-r--r--net/core/sock.c7
-rw-r--r--net/ipv4/Kconfig2
-rw-r--r--net/ipv4/arp.c3
-rw-r--r--net/ipv4/ip_options.c2
-rw-r--r--net/ipv4/sysctl_net_ipv4.c6
-rw-r--r--net/ipv4/tcp.c23
-rw-r--r--net/ipv4/tcp_input.c45
-rw-r--r--net/ipv4/tcp_ipv4.c5
-rw-r--r--net/ipv4/tcp_timer.c5
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/rxrpc/ar-key.c4
-rw-r--r--net/sched/sch_choke.c3
-rw-r--r--net/sched/sch_netem.c3
-rw-r--r--net/sched/sch_sfb.c3
-rw-r--r--net/sched/sch_sfq.c5
-rwxr-xr-xscripts/checkpatch.pl6
-rw-r--r--scripts/mod/file2alias.c2
-rw-r--r--sound/aoa/codecs/onyx.c13
-rw-r--r--sound/aoa/codecs/tas.c13
-rw-r--r--sound/core/control.c2
-rw-r--r--sound/core/init.c169
-rw-r--r--sound/core/misc.c2
-rw-r--r--sound/core/pcm.c99
-rw-r--r--sound/core/pcm_lib.c3
-rw-r--r--sound/core/pcm_native.c15
-rw-r--r--sound/core/vmaster.c46
-rw-r--r--sound/isa/sb/emu8000_patch.c1
-rw-r--r--sound/pci/au88x0/au88x0.h13
-rw-r--r--sound/pci/au88x0/au88x0_core.c20
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c127
-rw-r--r--sound/pci/azt3328.c3
-rw-r--r--sound/pci/ctxfi/ctvmem.c2
-rw-r--r--sound/pci/hda/alc260_quirks.c968
-rw-r--r--sound/pci/hda/alc880_quirks.c1707
-rw-r--r--sound/pci/hda/alc882_quirks.c866
-rw-r--r--sound/pci/hda/alc_quirks.c480
-rw-r--r--sound/pci/hda/hda_codec.c206
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_eld.c4
-rw-r--r--sound/pci/hda/hda_intel.c52
-rw-r--r--sound/pci/hda/hda_jack.c40
-rw-r--r--sound/pci/hda/hda_jack.h13
-rw-r--r--sound/pci/hda/hda_local.h30
-rw-r--r--sound/pci/hda/patch_analog.c72
-rw-r--r--sound/pci/hda/patch_ca0132.c33
-rw-r--r--sound/pci/hda/patch_cirrus.c10
-rw-r--r--sound/pci/hda/patch_conexant.c146
-rw-r--r--sound/pci/hda/patch_hdmi.c2
-rw-r--r--sound/pci/hda/patch_realtek.c1939
-rw-r--r--sound/pci/hda/patch_sigmatel.c205
-rw-r--r--sound/pci/hda/patch_via.c335
-rw-r--r--sound/pci/ice1712/ice1724.c23
-rw-r--r--sound/pci/intel8x0.c6
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c25
-rw-r--r--sound/pci/rme9652/hdspm.c1
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c9
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/atmel/atmel-pcm.c4
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c37
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c17
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c17
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c29
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c20
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1373.c13
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1701.c16
-rw-r--r--sound/soc/blackfin/bfin-eval-adav80x.c13
-rw-r--r--sound/soc/codecs/Kconfig8
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ad1836.c6
-rw-r--r--sound/soc/codecs/ad1980.c2
-rw-r--r--sound/soc/codecs/adau1373.c7
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/ak4104.c174
-rw-r--r--sound/soc/codecs/ak4535.c98
-rw-r--r--sound/soc/codecs/ak4535.h2
-rw-r--r--sound/soc/codecs/ak4642.c33
-rw-r--r--sound/soc/codecs/ak4671.c2
-rw-r--r--sound/soc/codecs/alc5623.c12
-rw-r--r--sound/soc/codecs/alc5632.c197
-rw-r--r--sound/soc/codecs/alc5632.h1
-rw-r--r--sound/soc/codecs/cq93vc.c4
-rw-r--r--sound/soc/codecs/cs4270.c4
-rw-r--r--sound/soc/codecs/cs4271.c2
-rw-r--r--sound/soc/codecs/cs42l73.c2
-rw-r--r--sound/soc/codecs/da7210.c146
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/max9768.c247
-rw-r--r--sound/soc/codecs/max98088.c4
-rw-r--r--sound/soc/codecs/max98095.c6
-rw-r--r--sound/soc/codecs/max9877.c2
-rw-r--r--sound/soc/codecs/sgtl5000.c19
-rw-r--r--sound/soc/codecs/sn95031.c5
-rw-r--r--sound/soc/codecs/ssm2602.c2
-rw-r--r--sound/soc/codecs/stac9766.c2
-rw-r--r--sound/soc/codecs/tlv320aic23.c2
-rw-r--r--sound/soc/codecs/tlv320aic26.c2
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c66
-rw-r--r--sound/soc/codecs/tlv320aic3x.h9
-rw-r--r--sound/soc/codecs/tlv320dac33.c10
-rw-r--r--sound/soc/codecs/tpa6130a2.c4
-rw-r--r--sound/soc/codecs/twl4030.c42
-rw-r--r--sound/soc/codecs/twl6040.c31
-rw-r--r--sound/soc/codecs/twl6040.h1
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/wl1273.c2
-rw-r--r--sound/soc/codecs/wm2200.c2286
-rw-r--r--sound/soc/codecs/wm2200.h3674
-rw-r--r--sound/soc/codecs/wm5100.c651
-rw-r--r--sound/soc/codecs/wm8731.c109
-rw-r--r--sound/soc/codecs/wm8737.c2
-rw-r--r--sound/soc/codecs/wm8753.c195
-rw-r--r--sound/soc/codecs/wm8770.c5
-rw-r--r--sound/soc/codecs/wm8776.c8
-rw-r--r--sound/soc/codecs/wm8804.c154
-rw-r--r--sound/soc/codecs/wm8904.c856
-rw-r--r--sound/soc/codecs/wm8904.h11
-rw-r--r--sound/soc/codecs/wm8940.c16
-rw-r--r--sound/soc/codecs/wm8955.c247
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c14
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c2151
-rw-r--r--sound/soc/codecs/wm8971.c37
-rw-r--r--sound/soc/codecs/wm8974.c45
-rw-r--r--sound/soc/codecs/wm8978.c185
-rw-r--r--sound/soc/codecs/wm8978.h2
-rw-r--r--sound/soc/codecs/wm8983.c5
-rw-r--r--sound/soc/codecs/wm8985.c315
-rw-r--r--sound/soc/codecs/wm8988.c171
-rw-r--r--sound/soc/codecs/wm8990.c2
-rw-r--r--sound/soc/codecs/wm8991.c2
-rw-r--r--sound/soc/codecs/wm8993.c649
-rw-r--r--sound/soc/codecs/wm8993.h9
-rw-r--r--sound/soc/codecs/wm8994.c374
-rw-r--r--sound/soc/codecs/wm8994.h6
-rw-r--r--sound/soc/codecs/wm8995.c4
-rw-r--r--sound/soc/codecs/wm8996.c236
-rw-r--r--sound/soc/codecs/wm9081.c80
-rw-r--r--sound/soc/codecs/wm9090.c272
-rw-r--r--sound/soc/codecs/wm9705.c2
-rw-r--r--sound/soc/codecs/wm9712.c16
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c166
-rw-r--r--sound/soc/codecs/wm_hubs.h12
-rw-r--r--sound/soc/davinci/davinci-pcm.c4
-rw-r--r--sound/soc/ep93xx/Kconfig1
-rw-r--r--sound/soc/ep93xx/edb93xx.c4
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c152
-rw-r--r--sound/soc/ep93xx/snappercl15.c4
-rw-r--r--sound/soc/fsl/fsl_dma.c10
-rw-r--r--sound/soc/fsl/fsl_ssi.c6
-rw-r--r--sound/soc/fsl/mpc5200_dma.c17
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c18
-rw-r--r--sound/soc/fsl/p1022_ds.c36
-rw-r--r--sound/soc/imx/Kconfig25
-rw-r--r--sound/soc/imx/Makefile15
-rw-r--r--sound/soc/imx/eukrea-tlv320.c40
-rw-r--r--sound/soc/imx/imx-audmux.c (renamed from arch/arm/plat-mxc/audmux-v2.c)185
-rw-r--r--sound/soc/imx/imx-audmux.h60
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c223
-rw-r--r--sound/soc/imx/imx-pcm.c105
-rw-r--r--sound/soc/imx/imx-pcm.h32
-rw-r--r--sound/soc/imx/imx-ssi.c120
-rw-r--r--sound/soc/imx/imx-ssi.h16
-rw-r--r--sound/soc/imx/mx27vis-aic32x4.c159
-rw-r--r--sound/soc/imx/phycore-ac97.c27
-rw-r--r--sound/soc/imx/wm1133-ev1.c25
-rw-r--r--sound/soc/jz4740/qi_lb60.c56
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c4
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c46
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c47
-rw-r--r--sound/soc/mid-x86/mfld_machine.c2
-rw-r--r--sound/soc/mxs/Kconfig2
-rw-r--r--sound/soc/mxs/mxs-pcm.c157
-rw-r--r--sound/soc/mxs/mxs-pcm.h16
-rw-r--r--sound/soc/mxs/mxs-saif.c51
-rw-r--r--sound/soc/omap/Kconfig15
-rw-r--r--sound/soc/omap/Makefile6
-rw-r--r--sound/soc/omap/am3517evm.c2
-rw-r--r--sound/soc/omap/ams-delta.c4
-rw-r--r--sound/soc/omap/igep0020.c2
-rw-r--r--sound/soc/omap/mcbsp.c (renamed from arch/arm/plat-omap/mcbsp.c)549
-rw-r--r--sound/soc/omap/mcbsp.h346
-rw-r--r--sound/soc/omap/n810.c19
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c349
-rw-r--r--sound/soc/omap/omap-dmic.c7
-rw-r--r--sound/soc/omap/omap-mcbsp.c321
-rw-r--r--sound/soc/omap/omap-mcbsp.h2
-rw-r--r--sound/soc/omap/omap-mcpdm.c2
-rw-r--r--sound/soc/omap/omap-pcm.h2
-rw-r--r--sound/soc/omap/omap3beagle.c2
-rw-r--r--sound/soc/omap/omap3evm.c2
-rw-r--r--sound/soc/omap/omap3pandora.c4
-rw-r--r--sound/soc/omap/osk5912.c2
-rw-r--r--sound/soc/omap/overo.c2
-rw-r--r--sound/soc/omap/rx51.c27
-rw-r--r--sound/soc/omap/sdp3430.c4
-rw-r--r--sound/soc/omap/sdp4430.c279
-rw-r--r--sound/soc/omap/zoom2.c4
-rw-r--r--sound/soc/pxa/corgi.c14
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/poodle.c14
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c10
-rw-r--r--sound/soc/pxa/raumfeld.c2
-rw-r--r--sound/soc/pxa/spitz.c14
-rw-r--r--sound/soc/pxa/tosa.c2
-rw-r--r--sound/soc/s6000/s6000-pcm.c5
-rw-r--r--sound/soc/samsung/ac97.c4
-rw-r--r--sound/soc/samsung/dma.c2
-rw-r--r--sound/soc/samsung/i2s.c14
-rw-r--r--sound/soc/samsung/i2s.h2
-rw-r--r--sound/soc/samsung/littlemill.c3
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c73
-rw-r--r--sound/soc/samsung/pcm.c4
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c6
-rw-r--r--sound/soc/samsung/smdk_wm8580.c4
-rw-r--r--sound/soc/samsung/smdk_wm9713.c4
-rw-r--r--sound/soc/sh/fsi.c918
-rw-r--r--sound/soc/soc-core.c402
-rw-r--r--sound/soc/soc-dapm.c412
-rw-r--r--sound/soc/soc-dmaengine-pcm.c288
-rw-r--r--sound/soc/soc-io.c7
-rw-r--r--sound/soc/soc-pcm.c104
-rw-r--r--sound/soc/soc-utils.c20
-rw-r--r--sound/soc/tegra/tegra_alc5632.c129
-rw-r--r--sound/soc/tegra/tegra_pcm.c2
-rw-r--r--sound/spi/at73c213.c12
-rw-r--r--sound/usb/6fire/chip.c3
-rw-r--r--sound/usb/6fire/chip.h1
-rw-r--r--sound/usb/6fire/comm.c1
-rw-r--r--sound/usb/6fire/comm.h1
-rw-r--r--sound/usb/6fire/common.h1
-rw-r--r--sound/usb/6fire/control.c341
-rw-r--r--sound/usb/6fire/control.h7
-rw-r--r--sound/usb/6fire/firmware.c1
-rw-r--r--sound/usb/6fire/midi.c1
-rw-r--r--sound/usb/6fire/midi.h1
-rw-r--r--sound/usb/6fire/pcm.c1
-rw-r--r--sound/usb/6fire/pcm.h1
-rw-r--r--sound/usb/Kconfig1
-rw-r--r--sound/usb/caiaq/audio.c5
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/format.c4
-rw-r--r--sound/usb/pcm.c6
-rw-r--r--sound/usb/quirks-table.h8
-rw-r--r--sound/usb/quirks.c6
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c4
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
-rw-r--r--tools/perf/Makefile7
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S6
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/builtin-top.c13
-rw-r--r--tools/perf/util/event.c2
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/probe-event.c2
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/trace-event-parse.c3
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/ui/helpline.c1
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--virt/kvm/kvm_main.c2
1017 files changed, 22874 insertions, 57711 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 2f7fd4360848..9c27e5125dd2 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -102,9 +102,12 @@ X!Iinclude/linux/kobject.h
!Iinclude/linux/device.h
</sect1>
<sect1><title>Device Drivers Base</title>
+!Idrivers/base/init.c
!Edrivers/base/driver.c
!Edrivers/base/core.c
+!Edrivers/base/syscore.c
!Edrivers/base/class.c
+!Idrivers/base/node.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
<!-- Cannot be included, because
@@ -113,7 +116,7 @@ X!Iinclude/linux/kobject.h
exceed allowed 44 characters maximum
X!Edrivers/base/attribute_container.c
-->
-!Edrivers/base/sys.c
+!Edrivers/base/dd.c
<!--
X!Edrivers/base/interface.c
-->
@@ -121,6 +124,11 @@ X!Edrivers/base/interface.c
!Edrivers/base/platform.c
!Edrivers/base/bus.c
</sect1>
+ <sect1><title>Device Drivers DMA Management</title>
+!Edrivers/base/dma-buf.c
+!Edrivers/base/dma-coherent.c
+!Edrivers/base/dma-mapping.c
+ </sect1>
<sect1><title>Device Drivers Power Management</title>
!Edrivers/base/power/main.c
</sect1>
@@ -219,7 +227,7 @@ X!Isound/sound_firmware.c
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250.c
+!Edrivers/tty/serial/8250/8250.c
</chapter>
<chapter id="fbdev">
diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt
new file mode 100644
index 000000000000..8608f747dcfe
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/alc5632.txt
@@ -0,0 +1,24 @@
+ALC5632 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+ - compatible : "realtek,alc5632"
+
+ - reg : the I2C address of the device.
+
+ - gpio-controller : Indicates this device is a GPIO controller.
+
+ - #gpio-cells : Should be two. The first cell is the pin number and the
+ second cell is used to specify optional parameters (currently unused).
+
+Example:
+
+alc5632: alc5632@1e {
+ compatible = "realtek,alc5632";
+ reg = <0x1a>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt
new file mode 100644
index 000000000000..215aa9817213
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt
@@ -0,0 +1,13 @@
+Freescale Digital Audio Mux (AUDMUX) device
+
+Required properties:
+- compatible : "fsl,imx21-audmux" for AUDMUX version firstly used on i.MX21,
+ or "fsl,imx31-audmux" for the version firstly used on i.MX31.
+- reg : Should contain AUDMUX registers location and length
+
+Example:
+
+audmux@021d8000 {
+ compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
+ reg = <0x021d8000 0x4000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt
index 2c3cd413f042..2c3cd413f042 100644
--- a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
+++ b/Documentation/devicetree/bindings/sound/sgtl5000.txt
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
new file mode 100644
index 000000000000..b77a97c9101e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
@@ -0,0 +1,59 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-alc5632"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names for sources and
+ sinks are the ALC5632's pins:
+
+ ALC5632 pins:
+
+ * SPK_OUTP
+ * SPK_OUTN
+ * HP_OUT_L
+ * HP_OUT_R
+ * AUX_OUT_P
+ * AUX_OUT_N
+ * LINE_IN_L
+ * LINE_IN_R
+ * PHONE_P
+ * PHONE_N
+ * MIC1_P
+ * MIC1_N
+ * MIC2_P
+ * MIC2_N
+ * MICBIAS1
+ * DMICDAT
+
+ Board connectors:
+
+ * Headset Stereophone
+ * Int Spk
+ * Headset Mic
+ * Digital Mic
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller
+- nvidia,audio-codec : The phandle of the ALC5632 audio codec
+
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-alc5632-paz00",
+ "nvidia,tegra-audio-alc5632";
+
+ nvidia,model = "Compal PAZ00";
+
+ nvidia,audio-routing =
+ "Int Spk", "SPK_OUTP",
+ "Int Spk", "SPK_OUTN",
+ "Headset Mic","MICBIAS1",
+ "MIC1_N", "Headset Mic",
+ "MIC1_P", "Headset Mic",
+ "Headset Stereophone", "HP_OUT_R",
+ "Headset Stereophone", "HP_OUT_L";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&alc5632>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index ecc6a6cd26c1..ca8ee14bf004 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -33,6 +33,7 @@ nxp NXP Semiconductors
powervr Imagination Technologies
qcom Qualcomm, Inc.
ramtron Ramtron International
+realtek Realtek Semiconductor Corp.
samsung Samsung Semiconductor
sbs Smart Battery System
schindler Schindler
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 41c0c5d1ba14..b49829eca792 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -271,3 +271,6 @@ IOMAP
pcim_iounmap()
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
+
+REGULATOR
+ devm_regulator_get()
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
index 23fcb05175be..53305bd08182 100644
--- a/Documentation/input/event-codes.txt
+++ b/Documentation/input/event-codes.txt
@@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in
class/input/event*/device/capabilities/, and the properties of a device are
provided in class/input/event*/device/properties.
-Types:
-==========
-Types are groupings of codes under a logical input construct. Each type has a
-set of applicable codes to be used in generating events. See the Codes section
-for details on valid codes for each type.
+Event types:
+===========
+Event types are groupings of codes under a logical input construct. Each
+type has a set of applicable codes to be used in generating events. See the
+Codes section for details on valid codes for each type.
* EV_SYN:
- Used as markers to separate events. Events may be separated in time or in
@@ -63,9 +63,9 @@ for details on valid codes for each type.
* EV_FF_STATUS:
- Used to receive force feedback device status.
-Codes:
-==========
-Codes define the precise type of event.
+Event codes:
+===========
+Event codes define the precise type of event.
EV_SYN:
----------
@@ -220,6 +220,56 @@ EV_PWR:
EV_PWR events are a special type of event used specifically for power
mangement. Its usage is not well defined. To be addressed later.
+Device properties:
+=================
+Normally, userspace sets up an input device based on the data it emits,
+i.e., the event types. In the case of two devices emitting the same event
+types, additional information can be provided in the form of device
+properties.
+
+INPUT_PROP_DIRECT + INPUT_PROP_POINTER:
+--------------------------------------
+The INPUT_PROP_DIRECT property indicates that device coordinates should be
+directly mapped to screen coordinates (not taking into account trivial
+transformations, such as scaling, flipping and rotating). Non-direct input
+devices require non-trivial transformation, such as absolute to relative
+transformation for touchpads. Typical direct input devices: touchscreens,
+drawing tablets; non-direct devices: touchpads, mice.
+
+The INPUT_PROP_POINTER property indicates that the device is not transposed
+on the screen and thus requires use of an on-screen pointer to trace user's
+movements. Typical pointer devices: touchpads, tablets, mice; non-pointer
+device: touchscreen.
+
+If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is
+considered undefined and the device type should be deduced in the
+traditional way, using emitted event types.
+
+INPUT_PROP_BUTTONPAD:
+--------------------
+For touchpads where the button is placed beneath the surface, such that
+pressing down on the pad causes a button click, this property should be
+set. Common in clickpad notebooks and macbooks from 2009 and onwards.
+
+Originally, the buttonpad property was coded into the bcm5974 driver
+version field under the name integrated button. For backwards
+compatibility, both methods need to be checked in userspace.
+
+INPUT_PROP_SEMI_MT:
+------------------
+Some touchpads, most common between 2008 and 2011, can detect the presence
+of multiple contacts without resolving the individual positions; only the
+number of contacts and a rectangular shape is known. For such
+touchpads, the semi-mt property should be set.
+
+Depending on the device, the rectangle may enclose all touches, like a
+bounding box, or just some of them, for instance the two most recent
+touches. The diversity makes the rectangle of limited use, but some
+gestures can normally be extracted from it.
+
+If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT
+device.
+
Guidelines:
==========
The guidelines below ensure proper single-touch and multi-finger functionality.
@@ -240,6 +290,8 @@ used to report when a touch is active on the screen.
BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
contact. BTN_TOOL_<name> events should be reported where possible.
+For new hardware, INPUT_PROP_DIRECT should be set.
+
Trackpads:
----------
Legacy trackpads that only provide relative position information must report
@@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active
on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
be used to report the number of touches active on the trackpad.
+For new hardware, INPUT_PROP_POINTER should be set.
+
Tablets:
----------
BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
@@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.
BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
purpose on the device.
+
+For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 936699e4f04b..9af64c508ab4 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -860,7 +860,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
[Multiple options for each card instance]
model - force the model name
- position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
+ position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF,
+ 3 = VIACOMBO, 4 = COMBO)
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
When the bit 8 (0x100) is set, the lower 8 bits are used
as the "fixed" codec slots; i.e. the driver probes the
@@ -925,6 +926,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
(Usually SD_LPIB register is more accurate than the
position buffer.)
+ position_fix=3 is specific to VIA devices. The position
+ of the capture stream is checked from both LPIB and POSBUF
+ values. position_fix=4 is a combination mode, using LPIB
+ for playback and POSBUF for capture.
+
NB: If you get many "azx_get_response timeout" messages at
loading, it's likely a problem of interrupts (e.g. ACPI irq
routing). Try to boot with options like "pci=noacpi". Also, you
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index c8c54544abc5..d97d992ced14 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -8,37 +8,10 @@ ALC880
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
6stack 6-jack in back, 2-jack in front
6stack-digout 6-jack with a SPDIF out
- w810 3-jack
- z71v 3-jack (HP shared SPDIF)
- asus 3-jack (ASUS Mobo)
- asus-w1v ASUS W1V
- asus-dig ASUS with SPDIF out
- asus-dig2 ASUS with SPDIF out (using GPIO2)
- uniwill 3-jack
- fujitsu Fujitsu Laptops (Pi1536)
- F1734 2-jack
- lg LG laptop (m1 express dual)
- lg-lw LG LW20/LW25 laptop
- tcl TCL S700
- clevo Clevo laptops (m520G, m665n)
- medion Medion Rim 2150
- test for testing/debugging purpose, almost all controls can be
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
ALC260
======
- fujitsu Fujitsu S7020
- acer Acer TravelMate
- will Will laptops (PB V7900)
- replacer Replacer 672V
- favorit100 Maxdata Favorit 100XS
- basic fixed pin assignment (old default model)
- test for testing/debugging purpose, almost all controls can
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
+ N/A
ALC262
======
@@ -70,55 +43,7 @@ ALC680
ALC882/883/885/888/889
======================
- 3stack-dig 3-jack with SPDIF I/O
- 6stack-dig 6-jack digital with SPDIF I/O
- arima Arima W820Di1
- targa Targa T8, MSI-1049 T8
- asus-a7j ASUS A7J
- asus-a7m ASUS A7M
- macpro MacPro support
- mb5 Macbook 5,1
- macmini3 Macmini 3,1
- mba21 Macbook Air 2,1
- mbp3 Macbook Pro rev3
- imac24 iMac 24'' with jack detection
- imac91 iMac 9,1
- w2jc ASUS W2JC
- 3stack-2ch-dig 3-jack with SPDIF I/O (ALC883)
- alc883-6stack-dig 6-jack digital with SPDIF I/O (ALC883)
- 3stack-6ch 3-jack 6-channel
- 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
- 6stack-dig-demo 6-jack digital for Intel demo board
- acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
- acer-aspire Acer Aspire 9810
- acer-aspire-4930g Acer Aspire 4930G
- acer-aspire-6530g Acer Aspire 6530G
- acer-aspire-7730g Acer Aspire 7730G
- acer-aspire-8930g Acer Aspire 8930G
- medion Medion Laptops
- targa-dig Targa/MSI
- targa-2ch-dig Targa/MSI with 2-channel
- targa-8ch-dig Targa/MSI with 8-channel (MSI GX620)
- laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
- lenovo-101e Lenovo 101E
- lenovo-nb0763 Lenovo NB0763
- lenovo-ms7195-dig Lenovo MS7195
- lenovo-sky Lenovo Sky
- haier-w66 Haier W66
- 3stack-hp HP machines with 3stack (Lucknow, Samba boards)
- 6stack-dell Dell machines with 6stack (Inspiron 530)
- mitac Mitac 8252D
- clevo-m540r Clevo M540R (6ch + digital)
- clevo-m720 Clevo M720 laptop series
- fujitsu-pi2515 Fujitsu AMILO Pi2515
- fujitsu-xa3530 Fujitsu AMILO XA3530
- 3stack-6ch-intel Intel DG33* boards
- intel-alc889a Intel IbexPeak with ALC889A
- intel-x58 Intel DX58 with ALC889
- asus-p5q ASUS P5Q-EM boards
- mb31 MacBook 3,1
- sony-vaio-tt Sony VAIO TT
- auto auto-config reading BIOS (default)
+ N/A
ALC861/660
==========
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 91fee3b45fb8..7813c06a5c71 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -59,7 +59,12 @@ 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.
`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
+for some VIA controllers. The capture stream position is corrected
+by comparing both LPIB and position-buffer values.
+`position_fix=4` is another combination available for all controllers,
+and uses LPIB for the playback and the position-buffer for the capture
+streams.
+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.
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 8c20fbd8b42d..6d78841fd416 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -601,6 +601,8 @@ can be ORed together:
instead of using the one provided by the hardware.
512 - A kernel warning has occurred.
1024 - A module from drivers/staging was loaded.
+2048 - The system is working around a severe firmware bug.
+4096 - An out-of-tree module has been loaded.
==============================================================
diff --git a/MAINTAINERS b/MAINTAINERS
index a1fce9a3ab20..9a648eb8e213 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -159,7 +159,7 @@ S: Maintained
F: drivers/net/ethernet/realtek/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org
W: http://serial.sourceforge.net
S: Maintained
@@ -789,12 +789,6 @@ F: arch/arm/mach-mx*/
F: arch/arm/mach-imx/
F: arch/arm/plat-mxc/
-ARM/FREESCALE IMX51
-M: Amit Kucheria <amit.kucheria@canonical.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-F: arch/arm/mach-mx5/
-
ARM/FREESCALE IMX6
M: Shawn Guo <shawn.guo@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1783,9 +1777,9 @@ X: net/wireless/wext*
CHAR and MISC DRIVERS
M: Arnd Bergmann <arnd@arndb.de>
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-S: Maintained
+S: Supported
F: drivers/char/*
F: drivers/misc/*
@@ -2287,7 +2281,7 @@ F: drivers/acpi/dock.c
DOCUMENTATION
M: Randy Dunlap <rdunlap@xenotime.net>
L: linux-doc@vger.kernel.org
-T: quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/
+T: quilt http://xenotime.net/kernel-doc-patches/current/
S: Maintained
F: Documentation/
@@ -2320,7 +2314,7 @@ F: lib/lru_cache.c
F: Documentation/blockdev/drbd/
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
S: Supported
F: Documentation/kobject.txt
@@ -3324,6 +3318,12 @@ S: Maintained
F: net/ieee802154/
F: drivers/ieee802154/
+IIO SUBSYSTEM AND DRIVERS
+M: Jonathan Cameron <jic23@cam.ac.uk>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: drivers/staging/iio/
+
IKANOS/ADI EAGLE ADSL USB DRIVER
M: Matthieu Castet <castet.matthieu@free.fr>
M: Stanislaw Gruszka <stf_xl@wp.pl>
@@ -3992,11 +3992,11 @@ M: Rusty Russell <rusty@rustcorp.com.au>
L: lguest@lists.ozlabs.org
W: http://lguest.ozlabs.org/
S: Odd Fixes
-F: Documentation/virtual/lguest/
+F: arch/x86/include/asm/lguest*.h
F: arch/x86/lguest/
F: drivers/lguest/
F: include/linux/lguest*.h
-F: arch/x86/include/asm/lguest*.h
+F: tools/lguest/
LINUX FOR IBM pSERIES (RS/6000)
M: Paul Mackerras <paulus@au.ibm.com>
@@ -4136,7 +4136,7 @@ L: linux-ntfs-dev@lists.sourceforge.net
W: http://www.linux-ntfs.org/content/view/19/37/
S: Maintained
F: Documentation/ldm.txt
-F: fs/partitions/ldm.*
+F: block/partitions/ldm.*
LogFS
M: Joern Engel <joern@logfs.org>
@@ -5633,7 +5633,7 @@ W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
F: arch/s390/
F: drivers/s390/
-F: fs/partitions/ibm.c
+F: block/partitions/ibm.c
F: Documentation/s390/
F: Documentation/DocBook/s390*
@@ -6276,15 +6276,15 @@ S: Maintained
F: arch/alpha/kernel/srm_env.c
STABLE BRANCH
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: stable@vger.kernel.org
-S: Maintained
+S: Supported
STAGING SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L: devel@driverdev.osuosl.org
-S: Maintained
+S: Supported
F: drivers/staging/
STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
@@ -6396,11 +6396,6 @@ M: Omar Ramirez Luna <omar.ramirez@ti.com>
S: Odd Fixes
F: drivers/staging/tidspbridge/
-STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
-L: linux-media@vger.kernel.org
-S: Odd Fixes
-F: drivers/staging/tm6000/
-
STAGING - USB ENE SM/MS CARD READER DRIVER
M: Al Cho <acho@novell.com>
S: Odd Fixes
@@ -6669,8 +6664,8 @@ S: Maintained
K: ^Subject:.*(?i)trivial
TTY LAYER
-M: Greg Kroah-Hartman <gregkh@suse.de>
-S: Maintained
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
F: drivers/tty/
F: drivers/tty/serial/serial_core.c
@@ -6958,7 +6953,7 @@ S: Maintained
F: drivers/usb/serial/digi_acceleport.c
USB SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
S: Supported
F: Documentation/usb/usb-serial.txt
@@ -6973,9 +6968,8 @@ S: Maintained
F: drivers/usb/serial/empeg.c
USB SERIAL KEYSPAN DRIVER
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
-W: http://www.kroah.com/linux/
S: Maintained
F: drivers/usb/serial/*keyspan*
@@ -7003,7 +6997,7 @@ F: Documentation/video4linux/sn9c102.txt
F: drivers/media/video/sn9c102/
USB SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
@@ -7090,7 +7084,7 @@ F: fs/hppfs/
USERSPACE I/O (UIO)
M: "Hans J. Koch" <hjk@hansjkoch.de>
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained
F: Documentation/DocBook/uio-howto.tmpl
F: drivers/uio/
diff --git a/Makefile b/Makefile
index e3b23e864a53..4ddd641ab615 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 3
SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 63d7578856c1..a1dd2ee83753 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -29,6 +29,7 @@
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
interrupt-controller;
+ cpu-offset = <0x8000>;
reg = <0x10490000 0x1000>, <0x10480000 0x100>;
};
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts
index 1a1d7023b69b..825d2957da0b 100644
--- a/arch/arm/boot/dts/tegra-paz00.dts
+++ b/arch/arm/boot/dts/tegra-paz00.dts
@@ -46,11 +46,11 @@
};
serial@70006200 {
- status = "disable";
+ clock-frequency = <216000000>;
};
serial@70006300 {
- clock-frequency = <216000000>;
+ status = "disable";
};
serial@70006400 {
@@ -60,7 +60,7 @@
sdhci@c8000000 {
cd-gpios = <&gpio 173 0>; /* gpio PV5 */
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
- power-gpios = <&gpio 155 0>; /* gpio PT3 */
+ power-gpios = <&gpio 169 0>; /* gpio PV1 */
};
sdhci@c8000200 {
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 5d3ed7e38561..314d4664eae7 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long addr)
{
pgtable_page_dtor(pte);
- tlb_add_flush(tlb, addr);
+
+ /*
+ * With the classic ARM MMU, a pte page has two corresponding pmd
+ * entries, each covering 1MB.
+ */
+ addr &= PMD_MASK;
+ tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
+ tlb_add_flush(tlb, addr + SZ_1M);
+
tlb_remove_page(tlb, pte);
}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3a456c6c7005..be16a48007b4 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -790,7 +790,7 @@ __kuser_cmpxchg64: @ 0xffff0f60
smp_dmb arm
rsbs r0, r3, #0 @ set returned val and C flag
ldmfd sp!, {r4, r5, r6, r7}
- bx lr
+ usr_ret lr
#elif !defined(CONFIG_SMP)
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 460bbbb6b885..6933244c68f9 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
@@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e1d5e1929fbd..e33870ff0ac0 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -699,10 +699,13 @@ static int vfp_set(struct task_struct *target,
{
int ret;
struct thread_info *thread = task_thread_info(target);
- struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
+ struct vfp_hard_struct new_vfp;
const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
+ vfp_sync_hwstate(thread);
+ new_vfp = thread->vfpstate.hard;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&new_vfp.fpregs,
user_fpregs_offset,
@@ -723,9 +726,8 @@ static int vfp_set(struct task_struct *target,
if (ret)
return ret;
- vfp_sync_hwstate(thread);
- thread->vfpstate.hard = new_vfp;
vfp_flush_hwstate(thread);
+ thread->vfpstate.hard = new_vfp;
return 0;
}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 0340224cf73c..9e617bd4a146 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
return -EINVAL;
+ vfp_flush_hwstate(thread);
+
/*
* Copy the floating point registers. There can be unused
* registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
- if (!err)
- vfp_flush_hwstate(thread);
-
return err ? -EFAULT : 0;
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 99a572702509..f84dfe67724f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -266,6 +266,7 @@ void die(const char *str, struct pt_regs *regs, int err)
{
struct thread_info *thread = current_thread_info();
int ret;
+ enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
oops_enter();
@@ -273,7 +274,9 @@ void die(const char *str, struct pt_regs *regs, int err)
console_verbose();
bust_spinlocks(1);
if (!user_mode(regs))
- report_bug(regs->ARM_pc, regs);
+ bug_type = report_bug(regs->ARM_pc, regs);
+ if (bug_type != BUG_TRAP_TYPE_NONE)
+ str = "Oops - BUG";
ret = __die(str, err, thread, regs);
if (regs && kexec_should_crash(thread->task))
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 1e19691e0406..43a31fb06318 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -10,6 +10,7 @@
#include <asm/page.h>
#define PROC_INFO \
+ . = ALIGN(4); \
VMLINUX_SYMBOL(__proc_info_begin) = .; \
*(.proc.info.init) \
VMLINUX_SYMBOL(__proc_info_end) = .;
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 18bacec2b094..97676bdae998 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -83,7 +83,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
* USB Device (Gadget)
* -------------------------------------------------------------------- */
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
static struct at91_udc_data udc_data;
static struct resource udc_resources[] = {
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 642ccb6d26b2..5a24f0b4554d 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -84,7 +84,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
* USB Device (Gadget)
* -------------------------------------------------------------------- */
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
static struct at91_udc_data udc_data;
static struct resource udc_resources[] = {
@@ -1215,8 +1215,7 @@ void __init at91_add_device_serial(void) {}
* CF/IDE
* -------------------------------------------------------------------- */
-#if defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) || \
- defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
+#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
static struct at91_cf_data cf0_data;
@@ -1313,10 +1312,8 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
if (data->flags & AT91_CF_TRUE_IDE)
#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE)
pdev->name = "pata_at91";
-#elif defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
- pdev->name = "at91_ide";
#else
-#warning "board requires AT91_CF_TRUE_IDE: enable either at91_ide or pata_at91"
+#warning "board requires AT91_CF_TRUE_IDE: enable pata_at91"
#endif
else
pdev->name = "at91_cf";
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index fc59cbdb0e3c..1e28bed8f425 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -87,7 +87,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
* USB Device (Gadget)
* -------------------------------------------------------------------- */
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
static struct at91_udc_data udc_data;
static struct resource udc_resources[] = {
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 7b46b2787022..366a7765635b 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -92,7 +92,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
* USB Device (Gadget)
* -------------------------------------------------------------------- */
-#ifdef CONFIG_USB_AT91
+#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
static struct at91_udc_data udc_data;
static struct resource udc_resources[] = {
@@ -355,8 +355,8 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
* Compact Flash (PCMCIA or IDE)
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
- defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
+ defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
static struct at91_cf_data cf0_data;
@@ -450,7 +450,7 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
at91_set_A_periph(AT91_PIN_PD9, 0); /* CFCE2 */
at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
- pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf";
+ pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "pata_at91" : "at91_cf";
platform_device_register(pdev);
}
#else
diff --git a/arch/arm/mach-at91/include/mach/at91sam9_smc.h b/arch/arm/mach-at91/include/mach/at91sam9_smc.h
index eb18a70fa647..175e1fdd9fe8 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9_smc.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9_smc.h
@@ -18,6 +18,35 @@
#include <mach/cpu.h>
+#ifndef __ASSEMBLY__
+struct sam9_smc_config {
+ /* Setup register */
+ u8 ncs_read_setup;
+ u8 nrd_setup;
+ u8 ncs_write_setup;
+ u8 nwe_setup;
+
+ /* Pulse register */
+ u8 ncs_read_pulse;
+ u8 nrd_pulse;
+ u8 ncs_write_pulse;
+ u8 nwe_pulse;
+
+ /* Cycle register */
+ u16 read_cycle;
+ u16 write_cycle;
+
+ /* Mode register */
+ u32 mode;
+ u8 tdf_cycles:4;
+};
+
+extern void sam9_smc_configure(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_read(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_read_mode(int id, int cs, struct sam9_smc_config *config);
+extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config);
+#endif
+
#define AT91_SMC_SETUP 0x00 /* Setup Register for CS n */
#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */
#define AT91_SMC_NWESETUP_(x) ((x) << 0)
diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c
index 8294783b679d..99a0a1d2b7dc 100644
--- a/arch/arm/mach-at91/sam9_smc.c
+++ b/arch/arm/mach-at91/sam9_smc.c
@@ -2,6 +2,7 @@
* linux/arch/arm/mach-at91/sam9_smc.c
*
* Copyright (C) 2008 Andrew Victor
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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
@@ -22,7 +23,22 @@
static void __iomem *smc_base_addr[2];
-static void __init sam9_smc_cs_configure(void __iomem *base, struct sam9_smc_config* config)
+static void sam9_smc_cs_write_mode(void __iomem *base,
+ struct sam9_smc_config *config)
+{
+ __raw_writel(config->mode
+ | AT91_SMC_TDF_(config->tdf_cycles),
+ base + AT91_SMC_MODE);
+}
+
+void sam9_smc_write_mode(int id, int cs,
+ struct sam9_smc_config *config)
+{
+ sam9_smc_cs_write_mode(AT91_SMC_CS(id, cs), config);
+}
+
+static void sam9_smc_cs_configure(void __iomem *base,
+ struct sam9_smc_config *config)
{
/* Setup register */
@@ -45,16 +61,66 @@ static void __init sam9_smc_cs_configure(void __iomem *base, struct sam9_smc_con
base + AT91_SMC_CYCLE);
/* Mode register */
- __raw_writel(config->mode
- | AT91_SMC_TDF_(config->tdf_cycles),
- base + AT91_SMC_MODE);
+ sam9_smc_cs_write_mode(base, config);
}
-void __init sam9_smc_configure(int id, int cs, struct sam9_smc_config* config)
+void sam9_smc_configure(int id, int cs,
+ struct sam9_smc_config *config)
{
sam9_smc_cs_configure(AT91_SMC_CS(id, cs), config);
}
+static void sam9_smc_cs_read_mode(void __iomem *base,
+ struct sam9_smc_config *config)
+{
+ u32 val = __raw_readl(base + AT91_SMC_MODE);
+
+ config->mode = (val & ~AT91_SMC_NWECYCLE);
+ config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ;
+}
+
+void sam9_smc_read_mode(int id, int cs,
+ struct sam9_smc_config *config)
+{
+ sam9_smc_cs_read_mode(AT91_SMC_CS(id, cs), config);
+}
+
+static void sam9_smc_cs_read(void __iomem *base,
+ struct sam9_smc_config *config)
+{
+ u32 val;
+
+ /* Setup register */
+ val = __raw_readl(base + AT91_SMC_SETUP);
+
+ config->nwe_setup = val & AT91_SMC_NWESETUP;
+ config->ncs_write_setup = (val & AT91_SMC_NCS_WRSETUP) >> 8;
+ config->nrd_setup = (val & AT91_SMC_NRDSETUP) >> 16;
+ config->ncs_read_setup = (val & AT91_SMC_NCS_RDSETUP) >> 24;
+
+ /* Pulse register */
+ val = __raw_readl(base + AT91_SMC_PULSE);
+
+ config->nwe_setup = val & AT91_SMC_NWEPULSE;
+ config->ncs_write_pulse = (val & AT91_SMC_NCS_WRPULSE) >> 8;
+ config->nrd_pulse = (val & AT91_SMC_NRDPULSE) >> 16;
+ config->ncs_read_pulse = (val & AT91_SMC_NCS_RDPULSE) >> 24;
+
+ /* Cycle register */
+ val = __raw_readl(base + AT91_SMC_CYCLE);
+
+ config->write_cycle = val & AT91_SMC_NWECYCLE;
+ config->read_cycle = (val & AT91_SMC_NRDCYCLE) >> 16;
+
+ /* Mode register */
+ sam9_smc_cs_read_mode(base, config);
+}
+
+void sam9_smc_read(int id, int cs, struct sam9_smc_config *config)
+{
+ sam9_smc_cs_read(AT91_SMC_CS(id, cs), config);
+}
+
void __init at91sam9_ioremap_smc(int id, u32 addr)
{
if (id > 1) {
diff --git a/arch/arm/mach-at91/sam9_smc.h b/arch/arm/mach-at91/sam9_smc.h
index 039c5ce17aec..3e52dcd4a59f 100644
--- a/arch/arm/mach-at91/sam9_smc.h
+++ b/arch/arm/mach-at91/sam9_smc.h
@@ -8,27 +8,4 @@
* published by the Free Software Foundation.
*/
-struct sam9_smc_config {
- /* Setup register */
- u8 ncs_read_setup;
- u8 nrd_setup;
- u8 ncs_write_setup;
- u8 nwe_setup;
-
- /* Pulse register */
- u8 ncs_read_pulse;
- u8 nrd_pulse;
- u8 ncs_write_pulse;
- u8 nwe_pulse;
-
- /* Cycle register */
- u16 read_cycle;
- u16 write_cycle;
-
- /* Mode register */
- u32 mode;
- u8 tdf_cycles:4;
-};
-
-extern void __init sam9_smc_configure(int id, int cs, struct sam9_smc_config* config);
extern void __init at91sam9_ioremap_smc(int id, u32 addr);
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 9e5e7552498c..45c97b1ee9b1 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -194,6 +194,6 @@ MACHINE_START(BCMRING, "BCMRING")
.init_early = bcmring_init_early,
.init_irq = bcmring_init_irq,
.timer = &bcmring_timer,
- .init_machine = bcmring_init_machine
+ .init_machine = bcmring_init_machine,
.restart = bcmring_restart,
MACHINE_END
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index 1a1a27dd5654..1024396797e1 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -33,17 +33,11 @@
#include <mach/timer.h>
-#include <linux/mm.h>
#include <linux/pfn.h>
#include <linux/atomic.h>
#include <linux/sched.h>
#include <mach/dma.h>
-/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
-/* especially since dc4 doesn't use kmalloc'd memory. */
-
-#define ALLOW_MAP_OF_KMALLOC_MEMORY 0
-
/* ---- Public Variables ------------------------------------------------- */
/* ---- Private Constants and Types -------------------------------------- */
@@ -53,24 +47,12 @@
#define CONTROLLER_FROM_HANDLE(handle) (((handle) >> 4) & 0x0f)
#define CHANNEL_FROM_HANDLE(handle) ((handle) & 0x0f)
-#define DMA_MAP_DEBUG 0
-
-#if DMA_MAP_DEBUG
-# define DMA_MAP_PRINT(fmt, args...) printk("%s: " fmt, __func__, ## args)
-#else
-# define DMA_MAP_PRINT(fmt, args...)
-#endif
/* ---- Private Variables ------------------------------------------------ */
static DMA_Global_t gDMA;
static struct proc_dir_entry *gDmaDir;
-static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);
-
#include "dma_device.c"
/* ---- Private Function Prototypes -------------------------------------- */
@@ -79,34 +61,6 @@ static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);
/****************************************************************************/
/**
-* Displays information for /proc/dma/mem-type
-*/
-/****************************************************************************/
-
-static int dma_proc_read_mem_type(char *buf, char **start, off_t offset,
- int count, int *eof, void *data)
-{
- int len = 0;
-
- len += sprintf(buf + len, "dma_map_mem statistics\n");
- len +=
- sprintf(buf + len, "coherent: %d\n",
- atomic_read(&gDmaStatMemTypeCoherent));
- len +=
- sprintf(buf + len, "kmalloc: %d\n",
- atomic_read(&gDmaStatMemTypeKmalloc));
- len +=
- sprintf(buf + len, "vmalloc: %d\n",
- atomic_read(&gDmaStatMemTypeVmalloc));
- len +=
- sprintf(buf + len, "user: %d\n",
- atomic_read(&gDmaStatMemTypeUser));
-
- return len;
-}
-
-/****************************************************************************/
-/**
* Displays information for /proc/dma/channels
*/
/****************************************************************************/
@@ -846,8 +800,6 @@ int dma_init(void)
dma_proc_read_channels, NULL);
create_proc_read_entry("devices", 0, gDmaDir,
dma_proc_read_devices, NULL);
- create_proc_read_entry("mem-type", 0, gDmaDir,
- dma_proc_read_mem_type, NULL);
}
out:
@@ -1565,767 +1517,3 @@ int dma_set_device_handler(DMA_Device_t dev, /* Device to set the callback for.
}
EXPORT_SYMBOL(dma_set_device_handler);
-
-/****************************************************************************/
-/**
-* Initializes a memory mapping structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap)
-{
- memset(memMap, 0, sizeof(*memMap));
-
- sema_init(&memMap->lock, 1);
-
- return 0;
-}
-
-EXPORT_SYMBOL(dma_init_mem_map);
-
-/****************************************************************************/
-/**
-* Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap)
-{
- down(&memMap->lock); /* Just being paranoid */
-
- /* Free up any allocated memory */
-
- up(&memMap->lock);
- memset(memMap, 0, sizeof(*memMap));
-
- return 0;
-}
-
-EXPORT_SYMBOL(dma_term_mem_map);
-
-/****************************************************************************/
-/**
-* Looks at a memory address and categorizes it.
-*
-* @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr)
-{
- unsigned long addrVal = (unsigned long)addr;
-
- if (addrVal >= CONSISTENT_BASE) {
- /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */
-
- /* dma_alloc_xxx pages are physically and virtually contiguous */
-
- return DMA_MEM_TYPE_DMA;
- }
-
- /* Technically, we could add one more classification. Addresses between VMALLOC_END */
- /* and the beginning of the DMA virtual address could be considered to be I/O space. */
- /* Right now, nobody cares about this particular classification, so we ignore it. */
-
- if (is_vmalloc_addr(addr)) {
- /* Address comes from the vmalloc'd region. Pages are virtually */
- /* contiguous but NOT physically contiguous */
-
- return DMA_MEM_TYPE_VMALLOC;
- }
-
- if (addrVal >= PAGE_OFFSET) {
- /* PAGE_OFFSET is typically 0xC0000000 */
-
- /* kmalloc'd pages are physically contiguous */
-
- return DMA_MEM_TYPE_KMALLOC;
- }
-
- return DMA_MEM_TYPE_USER;
-}
-
-EXPORT_SYMBOL(dma_mem_type);
-
-/****************************************************************************/
-/**
-* Looks at a memory address and determines if we support DMA'ing to/from
-* that type of memory.
-*
-* @return boolean -
-* return value != 0 means dma supported
-* return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr)
-{
- DMA_MemType_t memType = dma_mem_type(addr);
-
- return (memType == DMA_MEM_TYPE_DMA)
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- || (memType == DMA_MEM_TYPE_KMALLOC)
-#endif
- || (memType == DMA_MEM_TYPE_USER);
-}
-
-EXPORT_SYMBOL(dma_mem_supports_dma);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- ) {
- int rc;
-
- down(&memMap->lock);
-
- DMA_MAP_PRINT("memMap: %p\n", memMap);
-
- if (memMap->inUse) {
- printk(KERN_ERR "%s: memory map %p is already being used\n",
- __func__, memMap);
- rc = -EBUSY;
- goto out;
- }
-
- memMap->inUse = 1;
- memMap->dir = dir;
- memMap->numRegionsUsed = 0;
-
- rc = 0;
-
-out:
-
- DMA_MAP_PRINT("returning %d", rc);
-
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_start);
-
-/****************************************************************************/
-/**
-* Adds a segment of memory to a memory map. Each segment is both
-* physically and virtually contiguous.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-static int dma_map_add_segment(DMA_MemMap_t *memMap, /* Stores state information about the map */
- DMA_Region_t *region, /* Region that the segment belongs to */
- void *virtAddr, /* Virtual address of the segment being added */
- dma_addr_t physAddr, /* Physical address of the segment being added */
- size_t numBytes /* Number of bytes of the segment being added */
- ) {
- DMA_Segment_t *segment;
-
- DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr,
- physAddr, numBytes);
-
- /* Sanity check */
-
- if (((unsigned long)virtAddr < (unsigned long)region->virtAddr)
- || (((unsigned long)virtAddr + numBytes)) >
- ((unsigned long)region->virtAddr + region->numBytes)) {
- printk(KERN_ERR
- "%s: virtAddr %p is outside region @ %p len: %d\n",
- __func__, virtAddr, region->virtAddr, region->numBytes);
- return -EINVAL;
- }
-
- if (region->numSegmentsUsed > 0) {
- /* Check to see if this segment is physically contiguous with the previous one */
-
- segment = &region->segment[region->numSegmentsUsed - 1];
-
- if ((segment->physAddr + segment->numBytes) == physAddr) {
- /* It is - just add on to the end */
-
- DMA_MAP_PRINT("appending %d bytes to last segment\n",
- numBytes);
-
- segment->numBytes += numBytes;
-
- return 0;
- }
- }
-
- /* Reallocate to hold more segments, if required. */
-
- if (region->numSegmentsUsed >= region->numSegmentsAllocated) {
- DMA_Segment_t *newSegment;
- size_t oldSize =
- region->numSegmentsAllocated * sizeof(*newSegment);
- int newAlloc = region->numSegmentsAllocated + 4;
- size_t newSize = newAlloc * sizeof(*newSegment);
-
- newSegment = kmalloc(newSize, GFP_KERNEL);
- if (newSegment == NULL) {
- return -ENOMEM;
- }
- memcpy(newSegment, region->segment, oldSize);
- memset(&((uint8_t *) newSegment)[oldSize], 0,
- newSize - oldSize);
- kfree(region->segment);
-
- region->numSegmentsAllocated = newAlloc;
- region->segment = newSegment;
- }
-
- segment = &region->segment[region->numSegmentsUsed];
- region->numSegmentsUsed++;
-
- segment->virtAddr = virtAddr;
- segment->physAddr = physAddr;
- segment->numBytes = numBytes;
-
- DMA_MAP_PRINT("returning success\n");
-
- return 0;
-}
-
-/****************************************************************************/
-/**
-* Adds a region of memory to a memory map. Each region is virtually
-* contiguous, but not necessarily physically contiguous.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes /* Number of bytes being mapped */
- ) {
- unsigned long addr = (unsigned long)mem;
- unsigned int offset;
- int rc = 0;
- DMA_Region_t *region;
- dma_addr_t physAddr;
-
- down(&memMap->lock);
-
- DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes);
-
- if (!memMap->inUse) {
- printk(KERN_ERR "%s: Make sure you call dma_map_start first\n",
- __func__);
- rc = -EINVAL;
- goto out;
- }
-
- /* Reallocate to hold more regions. */
-
- if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) {
- DMA_Region_t *newRegion;
- size_t oldSize =
- memMap->numRegionsAllocated * sizeof(*newRegion);
- int newAlloc = memMap->numRegionsAllocated + 4;
- size_t newSize = newAlloc * sizeof(*newRegion);
-
- newRegion = kmalloc(newSize, GFP_KERNEL);
- if (newRegion == NULL) {
- rc = -ENOMEM;
- goto out;
- }
- memcpy(newRegion, memMap->region, oldSize);
- memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize);
-
- kfree(memMap->region);
-
- memMap->numRegionsAllocated = newAlloc;
- memMap->region = newRegion;
- }
-
- region = &memMap->region[memMap->numRegionsUsed];
- memMap->numRegionsUsed++;
-
- offset = addr & ~PAGE_MASK;
-
- region->memType = dma_mem_type(mem);
- region->virtAddr = mem;
- region->numBytes = numBytes;
- region->numSegmentsUsed = 0;
- region->numLockedPages = 0;
- region->lockedPages = NULL;
-
- switch (region->memType) {
- case DMA_MEM_TYPE_VMALLOC:
- {
- atomic_inc(&gDmaStatMemTypeVmalloc);
-
- /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */
-
- /* vmalloc'd pages are not physically contiguous */
-
- rc = -EINVAL;
- break;
- }
-
- case DMA_MEM_TYPE_KMALLOC:
- {
- atomic_inc(&gDmaStatMemTypeKmalloc);
-
- /* kmalloc'd pages are physically contiguous, so they'll have exactly */
- /* one segment */
-
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- physAddr =
- dma_map_single(NULL, mem, numBytes, memMap->dir);
- rc = dma_map_add_segment(memMap, region, mem, physAddr,
- numBytes);
-#else
- rc = -EINVAL;
-#endif
- break;
- }
-
- case DMA_MEM_TYPE_DMA:
- {
- /* dma_alloc_xxx pages are physically contiguous */
-
- atomic_inc(&gDmaStatMemTypeCoherent);
-
- physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset;
-
- dma_sync_single_for_cpu(NULL, physAddr, numBytes,
- memMap->dir);
- rc = dma_map_add_segment(memMap, region, mem, physAddr,
- numBytes);
- break;
- }
-
- case DMA_MEM_TYPE_USER:
- {
- size_t firstPageOffset;
- size_t firstPageSize;
- struct page **pages;
- struct task_struct *userTask;
-
- atomic_inc(&gDmaStatMemTypeUser);
-
-#if 1
- /* If the pages are user pages, then the dma_mem_map_set_user_task function */
- /* must have been previously called. */
-
- if (memMap->userTask == NULL) {
- printk(KERN_ERR
- "%s: must call dma_mem_map_set_user_task when using user-mode memory\n",
- __func__);
- return -EINVAL;
- }
-
- /* User pages need to be locked. */
-
- firstPageOffset =
- (unsigned long)region->virtAddr & (PAGE_SIZE - 1);
- firstPageSize = PAGE_SIZE - firstPageOffset;
-
- region->numLockedPages = (firstPageOffset
- + region->numBytes +
- PAGE_SIZE - 1) / PAGE_SIZE;
- pages =
- kmalloc(region->numLockedPages *
- sizeof(struct page *), GFP_KERNEL);
-
- if (pages == NULL) {
- region->numLockedPages = 0;
- return -ENOMEM;
- }
-
- userTask = memMap->userTask;
-
- down_read(&userTask->mm->mmap_sem);
- rc = get_user_pages(userTask, /* task */
- userTask->mm, /* mm */
- (unsigned long)region->virtAddr, /* start */
- region->numLockedPages, /* len */
- memMap->dir == DMA_FROM_DEVICE, /* write */
- 0, /* force */
- pages, /* pages (array of pointers to page) */
- NULL); /* vmas */
- up_read(&userTask->mm->mmap_sem);
-
- if (rc != region->numLockedPages) {
- kfree(pages);
- region->numLockedPages = 0;
-
- if (rc >= 0) {
- rc = -EINVAL;
- }
- } else {
- uint8_t *virtAddr = region->virtAddr;
- size_t bytesRemaining;
- int pageIdx;
-
- rc = 0; /* Since get_user_pages returns +ve number */
-
- region->lockedPages = pages;
-
- /* We've locked the user pages. Now we need to walk them and figure */
- /* out the physical addresses. */
-
- /* The first page may be partial */
-
- dma_map_add_segment(memMap,
- region,
- virtAddr,
- PFN_PHYS(page_to_pfn
- (pages[0])) +
- firstPageOffset,
- firstPageSize);
-
- virtAddr += firstPageSize;
- bytesRemaining =
- region->numBytes - firstPageSize;
-
- for (pageIdx = 1;
- pageIdx < region->numLockedPages;
- pageIdx++) {
- size_t bytesThisPage =
- (bytesRemaining >
- PAGE_SIZE ? PAGE_SIZE :
- bytesRemaining);
-
- DMA_MAP_PRINT
- ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n",
- pageIdx, pages[pageIdx],
- page_to_pfn(pages[pageIdx]),
- PFN_PHYS(page_to_pfn
- (pages[pageIdx])));
-
- dma_map_add_segment(memMap,
- region,
- virtAddr,
- PFN_PHYS(page_to_pfn
- (pages
- [pageIdx])),
- bytesThisPage);
-
- virtAddr += bytesThisPage;
- bytesRemaining -= bytesThisPage;
- }
- }
-#else
- printk(KERN_ERR
- "%s: User mode pages are not yet supported\n",
- __func__);
-
- /* user pages are not physically contiguous */
-
- rc = -EINVAL;
-#endif
- break;
- }
-
- default:
- {
- printk(KERN_ERR "%s: Unsupported memory type: %d\n",
- __func__, region->memType);
-
- rc = -EINVAL;
- break;
- }
- }
-
- if (rc != 0) {
- memMap->numRegionsUsed--;
- }
-
-out:
-
- DMA_MAP_PRINT("returning %d\n", rc);
-
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_add_segment);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes, /* Number of bytes being mapped */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- ) {
- int rc;
-
- rc = dma_map_start(memMap, dir);
- if (rc == 0) {
- rc = dma_map_add_region(memMap, mem, numBytes);
- if (rc < 0) {
- /* Since the add fails, this function will fail, and the caller won't */
- /* call unmap, so we need to do it here. */
-
- dma_unmap(memMap, 0);
- }
- }
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_mem);
-
-/****************************************************************************/
-/**
-* Setup a descriptor ring for a given memory map.
-*
-* It is assumed that the descriptor ring has already been initialized, and
-* this routine will only reallocate a new descriptor ring if the existing
-* one is too small.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */
- DMA_MemMap_t *memMap, /* Memory map that will be used */
- dma_addr_t devPhysAddr /* Physical address of device */
- ) {
- int rc;
- int numDescriptors;
- DMA_DeviceAttribute_t *devAttr;
- DMA_Region_t *region;
- DMA_Segment_t *segment;
- dma_addr_t srcPhysAddr;
- dma_addr_t dstPhysAddr;
- int regionIdx;
- int segmentIdx;
-
- devAttr = &DMA_gDeviceAttribute[dev];
-
- down(&memMap->lock);
-
- /* Figure out how many descriptors we need */
-
- numDescriptors = 0;
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = &region->segment[segmentIdx];
-
- if (memMap->dir == DMA_TO_DEVICE) {
- srcPhysAddr = segment->physAddr;
- dstPhysAddr = devPhysAddr;
- } else {
- srcPhysAddr = devPhysAddr;
- dstPhysAddr = segment->physAddr;
- }
-
- rc =
- dma_calculate_descriptor_count(dev, srcPhysAddr,
- dstPhysAddr,
- segment->
- numBytes);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_calculate_descriptor_count failed: %d\n",
- __func__, rc);
- goto out;
- }
- numDescriptors += rc;
- }
- }
-
- /* Adjust the size of the ring, if it isn't big enough */
-
- if (numDescriptors > devAttr->ring.descriptorsAllocated) {
- dma_free_descriptor_ring(&devAttr->ring);
- rc =
- dma_alloc_descriptor_ring(&devAttr->ring,
- numDescriptors);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_alloc_descriptor_ring failed: %d\n",
- __func__, rc);
- goto out;
- }
- } else {
- rc =
- dma_init_descriptor_ring(&devAttr->ring,
- numDescriptors);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_init_descriptor_ring failed: %d\n",
- __func__, rc);
- goto out;
- }
- }
-
- /* Populate the descriptors */
-
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = &region->segment[segmentIdx];
-
- if (memMap->dir == DMA_TO_DEVICE) {
- srcPhysAddr = segment->physAddr;
- dstPhysAddr = devPhysAddr;
- } else {
- srcPhysAddr = devPhysAddr;
- dstPhysAddr = segment->physAddr;
- }
-
- rc =
- dma_add_descriptors(&devAttr->ring, dev,
- srcPhysAddr, dstPhysAddr,
- segment->numBytes);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_add_descriptors failed: %d\n",
- __func__, rc);
- goto out;
- }
- }
- }
-
- rc = 0;
-
-out:
-
- up(&memMap->lock);
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_create_descriptor_ring);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
- int dirtied /* non-zero if any of the pages were modified */
- ) {
-
- int rc = 0;
- int regionIdx;
- int segmentIdx;
- DMA_Region_t *region;
- DMA_Segment_t *segment;
-
- down(&memMap->lock);
-
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = &region->segment[segmentIdx];
-
- switch (region->memType) {
- case DMA_MEM_TYPE_VMALLOC:
- {
- printk(KERN_ERR
- "%s: vmalloc'd pages are not yet supported\n",
- __func__);
- rc = -EINVAL;
- goto out;
- }
-
- case DMA_MEM_TYPE_KMALLOC:
- {
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- dma_unmap_single(NULL,
- segment->physAddr,
- segment->numBytes,
- memMap->dir);
-#endif
- break;
- }
-
- case DMA_MEM_TYPE_DMA:
- {
- dma_sync_single_for_cpu(NULL,
- segment->
- physAddr,
- segment->
- numBytes,
- memMap->dir);
- break;
- }
-
- case DMA_MEM_TYPE_USER:
- {
- /* Nothing to do here. */
-
- break;
- }
-
- default:
- {
- printk(KERN_ERR
- "%s: Unsupported memory type: %d\n",
- __func__, region->memType);
- rc = -EINVAL;
- goto out;
- }
- }
-
- segment->virtAddr = NULL;
- segment->physAddr = 0;
- segment->numBytes = 0;
- }
-
- if (region->numLockedPages > 0) {
- int pageIdx;
-
- /* Some user pages were locked. We need to go and unlock them now. */
-
- for (pageIdx = 0; pageIdx < region->numLockedPages;
- pageIdx++) {
- struct page *page =
- region->lockedPages[pageIdx];
-
- if (memMap->dir == DMA_FROM_DEVICE) {
- SetPageDirty(page);
- }
- page_cache_release(page);
- }
- kfree(region->lockedPages);
- region->numLockedPages = 0;
- region->lockedPages = NULL;
- }
-
- region->memType = DMA_MEM_TYPE_NONE;
- region->virtAddr = NULL;
- region->numBytes = 0;
- region->numSegmentsUsed = 0;
- }
- memMap->userTask = NULL;
- memMap->numRegionsUsed = 0;
- memMap->inUse = 0;
-
-out:
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_unmap);
diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h
index 1f2c5319c056..72543781207b 100644
--- a/arch/arm/mach-bcmring/include/mach/dma.h
+++ b/arch/arm/mach-bcmring/include/mach/dma.h
@@ -26,15 +26,9 @@
/* ---- Include Files ---------------------------------------------------- */
#include <linux/kernel.h>
-#include <linux/wait.h>
#include <linux/semaphore.h>
#include <csp/dmacHw.h>
#include <mach/timer.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
/* ---- Constants and Types ---------------------------------------------- */
@@ -113,78 +107,6 @@ typedef struct {
/****************************************************************************
*
-* The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
-* DMA chains from a variety of memory sources.
-*
-*****************************************************************************/
-
-#define DMA_MEM_MAP_MIN_SIZE 4096 /* Pages less than this size are better */
- /* off not being DMA'd. */
-
-typedef enum {
- DMA_MEM_TYPE_NONE, /* Not a valid setting */
- DMA_MEM_TYPE_VMALLOC, /* Memory came from vmalloc call */
- DMA_MEM_TYPE_KMALLOC, /* Memory came from kmalloc call */
- DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */
- DMA_MEM_TYPE_USER, /* Memory came from user space. */
-
-} DMA_MemType_t;
-
-/* A segment represents a physically and virtually contiguous chunk of memory. */
-/* i.e. each segment can be DMA'd */
-/* A user of the DMA code will add memory regions. Each region may need to be */
-/* represented by one or more segments. */
-
-typedef struct {
- void *virtAddr; /* Virtual address used for this segment */
- dma_addr_t physAddr; /* Physical address this segment maps to */
- size_t numBytes; /* Size of the segment, in bytes */
-
-} DMA_Segment_t;
-
-/* A region represents a virtually contiguous chunk of memory, which may be */
-/* made up of multiple segments. */
-
-typedef struct {
- DMA_MemType_t memType;
- void *virtAddr;
- size_t numBytes;
-
- /* Each region (virtually contiguous) consists of one or more segments. Each */
- /* segment is virtually and physically contiguous. */
-
- int numSegmentsUsed;
- int numSegmentsAllocated;
- DMA_Segment_t *segment;
-
- /* When a region corresponds to user memory, we need to lock all of the pages */
- /* down before we can figure out the physical addresses. The lockedPage array contains */
- /* the pages that were locked, and which subsequently need to be unlocked once the */
- /* memory is unmapped. */
-
- unsigned numLockedPages;
- struct page **lockedPages;
-
-} DMA_Region_t;
-
-typedef struct {
- int inUse; /* Is this mapping currently being used? */
- struct semaphore lock; /* Acquired when using this structure */
- enum dma_data_direction dir; /* Direction this transfer is intended for */
-
- /* In the event that we're mapping user memory, we need to know which task */
- /* the memory is for, so that we can obtain the correct mm locks. */
-
- struct task_struct *userTask;
-
- int numRegionsUsed;
- int numRegionsAllocated;
- DMA_Region_t *region;
-
-} DMA_MemMap_t;
-
-/****************************************************************************
-*
* The DMA_DeviceAttribute_t contains information which describes a
* particular DMA device (or peripheral).
*
@@ -570,124 +492,6 @@ int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */
/****************************************************************************/
/**
-* Initializes a DMA_MemMap_t data structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
- );
-
-/****************************************************************************/
-/**
-* Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
- );
-
-/****************************************************************************/
-/**
-* Looks at a memory address and categorizes it.
-*
-* @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr);
-
-/****************************************************************************/
-/**
-* Sets the process (aka userTask) associated with a mem map. This is
-* required if user-mode segments will be added to the mapping.
-*/
-/****************************************************************************/
-
-static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
- struct task_struct *task)
-{
- memMap->userTask = task;
-}
-
-/****************************************************************************/
-/**
-* Looks at a memory address and determines if we support DMA'ing to/from
-* that type of memory.
-*
-* @return boolean -
-* return value != 0 means dma supported
-* return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr);
-
-/****************************************************************************/
-/**
-* Initializes a memory map for use. Since this function acquires a
-* sempaphore within the memory map, it is VERY important that dma_unmap
-* be called when you're finished using the map.
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- );
-
-/****************************************************************************/
-/**
-* Adds a segment of memory to a memory map.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes /* Number of bytes being mapped */
- );
-
-/****************************************************************************/
-/**
-* Creates a descriptor ring from a memory mapping.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */
- DMA_MemMap_t *memMap, /* Memory map that will be used */
- dma_addr_t devPhysAddr /* Physical address of device */
- );
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *addr, /* Virtual address that we want to get a map of */
- size_t count, /* Number of bytes being mapped */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- );
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
- int dirtied /* non-zero if any of the pages were modified */
- );
-
-/****************************************************************************/
-/**
* Initiates a transfer when the descriptors have already been setup.
*
* This is a special case, and normally, the dma_transfer_xxx functions should
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 6b22b543a83f..d5088900af6c 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -44,7 +44,7 @@
#include <mach/aemif.h>
#include <mach/spi.h>
-#define DA850_EVM_PHY_ID "0:00"
+#define DA850_EVM_PHY_ID "davinci_mdio-0:00"
#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
#define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15)
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 346e1de2f5a8..849311d3cb7c 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -54,7 +54,7 @@ static inline int have_tvp7002(void)
return 0;
}
-#define DM365_EVM_PHY_ID "0:01"
+#define DM365_EVM_PHY_ID "davinci_mdio-0:01"
/*
* A MAX-II CPLD is used for various board control functions.
*/
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index a64b49cfedca..1247ecdcf752 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -40,7 +40,7 @@
#include <mach/usb.h>
#include <mach/aemif.h>
-#define DM644X_EVM_PHY_ID "0:01"
+#define DM644X_EVM_PHY_ID "davinci_mdio-0:01"
#define LXT971_PHY_ID (0x001378e2)
#define LXT971_PHY_MASK (0xfffffff0)
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 64017558860b..872ac69fa049 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -736,7 +736,7 @@ static struct davinci_uart_config uart_config __initdata = {
.enabled_uarts = (1 << 0),
};
-#define DM646X_EVM_PHY_ID "0:01"
+#define DM646X_EVM_PHY_ID "davinci_mdio-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
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 6c4a16415d47..8d34f513d415 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -39,7 +39,7 @@
#include <mach/mmc.h>
#include <mach/usb.h>
-#define NEUROS_OSD2_PHY_ID "0:01"
+#define NEUROS_OSD2_PHY_ID "davinci_mdio-0:01"
#define LXT971_PHY_ID 0x001378e2
#define LXT971_PHY_MASK 0xfffffff0
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index e7c0c7c53493..45e815760a27 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -21,7 +21,7 @@
#include <mach/da8xx.h>
#include <mach/mux.h>
-#define HAWKBOARD_PHY_ID "0:07"
+#define HAWKBOARD_PHY_ID "davinci_mdio-0:07"
#define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12)
#define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13)
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 0b136a831c59..31da3c5b2ba3 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -42,7 +42,7 @@
#include <mach/mux.h>
#include <mach/usb.h>
-#define SFFSDR_PHY_ID "0:01"
+#define SFFSDR_PHY_ID "davinci_mdio-0:01"
static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
/* U-Boot Environment: Block 0
* UBL: Block 1
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 0ed7fdb64efb..992c4c410185 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -153,34 +153,6 @@ static struct clk pll1_sysclk3 = {
.div_reg = PLLDIV3,
};
-static struct clk pll1_sysclk4 = {
- .name = "pll1_sysclk4",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
- .name = "pll1_sysclk5",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
- .name = "pll0_sysclk6",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV6,
-};
-
-static struct clk pll1_sysclk7 = {
- .name = "pll1_sysclk7",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV7,
-};
-
static struct clk i2c0_clk = {
.name = "i2c0",
.parent = &pll0_aux_clk,
@@ -397,10 +369,6 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "pll1_aux", &pll1_aux_clk),
CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
- CLK(NULL, "pll1_sysclk4", &pll1_sysclk4),
- CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
- CLK(NULL, "pll1_sysclk6", &pll1_sysclk6),
- CLK(NULL, "pll1_sysclk7", &pll1_sysclk7),
CLK("i2c_davinci.1", NULL, &i2c0_clk),
CLK(NULL, "timer0", &timerp64_0_clk),
CLK("watchdog", NULL, &timerp64_1_clk),
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index dd1429ae6405..bda7aca04ca0 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -28,6 +28,7 @@
#include <asm/mach/arch.h>
#include <linux/irq.h>
#include <plat/time.h>
+#include <plat/ehci-orion.h>
#include <plat/common.h>
#include <plat/addr-map.h>
#include "common.h"
@@ -71,7 +72,7 @@ void __init dove_map_io(void)
****************************************************************************/
void __init dove_ehci0_init(void)
{
- orion_ehci_init(DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0);
+ orion_ehci_init(DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0, EHCI_PHY_NA);
}
/*****************************************************************************
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 24203f9a6796..b5c1dae8327f 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -817,23 +817,12 @@ void __init ep93xx_register_i2s(void)
#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
EP93XX_SYSCON_I2SCLKDIV_SPOL)
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
+int ep93xx_i2s_acquire(void)
{
unsigned val;
- /* Sanity check */
- if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
- return -EINVAL;
- if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
- return -EINVAL;
-
- /* Must have only one of I2SONSSP/I2SONAC97 set */
- if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
- (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
- return -EINVAL;
-
- ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
- ep93xx_devcfg_set_bits(i2s_pins);
+ ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97,
+ EP93XX_SYSCON_DEVCFG_I2S_MASK);
/*
* This is potentially racy with the clock api for i2s_mclk, sclk and
@@ -843,7 +832,7 @@ int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
*/
val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
val &= ~EP93XX_I2SCLKDIV_MASK;
- val |= i2s_config;
+ val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
return 0;
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index d4c934931f9d..ad63d4be693f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -59,7 +59,7 @@ void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
void ep93xx_keypad_release_gpio(struct platform_device *pdev);
void ep93xx_register_i2s(void);
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
+int ep93xx_i2s_acquire(void);
void ep93xx_i2s_release(void);
void ep93xx_register_ac97(void);
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
index 03dd4012043e..d5fb44f16d31 100644
--- a/arch/arm/mach-ep93xx/vision_ep9307.c
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -32,6 +32,7 @@
#include <mach/hardware.h>
#include <mach/fb.h>
#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
@@ -153,7 +154,6 @@ static struct i2c_board_info vision_i2c_info[] __initdata = {
}, {
I2C_BOARD_INFO("pca9539", 0x74),
.platform_data = &pca953x_74_gpio_data,
- .irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
}, {
I2C_BOARD_INFO("pca9539", 0x75),
.platform_data = &pca953x_75_gpio_data,
@@ -348,6 +348,8 @@ static void __init vision_init_machine(void)
"pca9539:74"))
pr_warn("cannot request interrupt gpio for pca9539:74\n");
+ vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
+
ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
ARRAY_SIZE(vision_i2c_info));
ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
index a5823a7f249e..13312ccb2d93 100644
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ b/arch/arm/mach-exynos/clock-exynos4210.c
@@ -32,6 +32,7 @@
#include "common.h"
+#ifdef CONFIG_PM_SLEEP
static struct sleep_save exynos4210_clock_save[] = {
SAVE_ITEM(S5P_CLKSRC_IMAGE),
SAVE_ITEM(S5P_CLKSRC_LCD1),
@@ -42,6 +43,7 @@ static struct sleep_save exynos4210_clock_save[] = {
SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
};
+#endif
static struct clksrc_clk *sysclks[] = {
/* nothing here yet */
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
index 26a668b0d101..48af28566fa1 100644
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ b/arch/arm/mach-exynos/clock-exynos4212.c
@@ -32,12 +32,14 @@
#include "common.h"
+#ifdef CONFIG_PM_SLEEP
static struct sleep_save exynos4212_clock_save[] = {
SAVE_ITEM(S5P_CLKSRC_IMAGE),
SAVE_ITEM(S5P_CLKDIV_IMAGE),
SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
};
+#endif
static struct clk *clk_src_mpll_user_list[] = {
[0] = &clk_fin_mpll,
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 5a8c42e90005..187287aa57ab 100644
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -30,6 +30,7 @@
#include "common.h"
+#ifdef CONFIG_PM_SLEEP
static struct sleep_save exynos4_clock_save[] = {
SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
@@ -93,6 +94,7 @@ static struct sleep_save exynos4_clock_save[] = {
SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
SAVE_ITEM(S5P_CLKGATE_IP_CPU),
};
+#endif
struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 85fa02767d67..e6b02fdf1b09 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -15,11 +15,13 @@
#include <linux/serial_core.h>
#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/regs-serial.h>
-#include <plat/exynos4.h>
+
+#include "common.h"
/*
* The following lookup table is used to override device names when devices
@@ -60,7 +62,7 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
static void __init exynos4210_dt_map_io(void)
{
- s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ exynos_init_io(NULL, 0);
s3c24xx_init_clocks(24000000);
}
@@ -79,7 +81,9 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
.init_irq = exynos4_init_irq,
.map_io = exynos4210_dt_map_io,
+ .handle_irq = gic_handle_irq,
.init_machine = exynos4210_dt_machine_init,
.timer = &exynos4_timer,
.dt_compat = exynos4210_dt_compat,
+ .restart = exynos4_restart,
MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index b895ec031105..435261f83f46 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -220,14 +220,14 @@ static struct s3c_fb_pd_win nuri_fb_win0 = {
.lower_margin = 1,
.hsync_len = 48,
.vsync_len = 3,
- .xres = 1280,
- .yres = 800,
+ .xres = 1024,
+ .yres = 600,
.refresh = 60,
},
.max_bpp = 24,
.default_bpp = 16,
- .virtual_x = 1280,
- .virtual_y = 800,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
};
static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 37ac93e8d6d9..0fc65ffde8ff 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -910,7 +910,7 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
.bus_type = FIMC_MIPI_CSI2,
.board_info = &m5mols_board_info,
.i2c_bus_num = 0,
- .clk_frequency = 21600000UL,
+ .clk_frequency = 24000000UL,
.csi_data_align = 32,
},
};
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index a4f61a43c7ba..e19013051772 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -206,7 +206,7 @@ static void exynos4_pm_prepare(void)
}
-static int exynos4_pm_add(struct device *dev)
+static int exynos4_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = exynos4_pm_prepare;
pm_cpu_sleep = exynos4_cpu_suspend;
@@ -384,7 +384,9 @@ static void exynos4_pm_resume(void)
exynos4_restore_pll();
+#ifdef CONFIG_SMP
scu_enable(S5P_VA_SCU);
+#endif
#ifdef CONFIG_CACHE_L2X0
s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4defb97bbfc8..3919fba52ac8 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -46,7 +46,6 @@ config SOC_IMX21
bool
select MACH_MX21
select CPU_ARM926T
- select ARCH_MXC_AUDMUX_V1
select IMX_HAVE_DMA_V1
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
@@ -55,7 +54,6 @@ config SOC_IMX25
bool
select ARCH_MX25
select CPU_ARM926T
- select ARCH_MXC_AUDMUX_V2
select ARCH_MXC_IOMUX_V3
select MXC_AVIC
@@ -63,7 +61,6 @@ config SOC_IMX27
bool
select MACH_MX27
select CPU_ARM926T
- select ARCH_MXC_AUDMUX_V1
select IMX_HAVE_DMA_V1
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
@@ -72,7 +69,6 @@ config SOC_IMX31
bool
select CPU_V6
select IMX_HAVE_PLATFORM_MXC_RNGA
- select ARCH_MXC_AUDMUX_V2
select MXC_AVIC
select SMP_ON_UP if SMP
@@ -80,7 +76,6 @@ config SOC_IMX35
bool
select CPU_V6
select ARCH_MXC_IOMUX_V3
- select ARCH_MXC_AUDMUX_V2
select HAVE_EPIT
select MXC_AVIC
select SMP_ON_UP if SMP
@@ -89,7 +84,6 @@ config SOC_IMX5
select CPU_V7
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
- select ARCH_MXC_AUDMUX_V2
select ARCH_HAS_CPUFREQ
select ARCH_MX5
bool
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 5db3e1463af7..5f2f91d1798b 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -32,7 +32,6 @@
#include <mach/common.h>
#include <mach/iomux-mx27.h>
#include <mach/hardware.h>
-#include <mach/audmux.h>
#include "devices-imx27.h"
@@ -306,25 +305,6 @@ void __init eukrea_mbimx27_baseboard_init(void)
mxc_gpio_setup_multiple_pins(eukrea_mbimx27_pins,
ARRAY_SIZE(eukrea_mbimx27_pins), "MBIMX27");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320) \
- || defined(CONFIG_SND_SOC_EUKREA_TLV320_MODULE)
- /* SSI unit master I2S codec connected to SSI_PINS_4*/
- mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_TFSDIR |
- MXC_AUDMUX_V1_PCR_TCLKDIR |
- MXC_AUDMUX_V1_PCR_RFSDIR |
- MXC_AUDMUX_V1_PCR_RCLKDIR |
- MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
- MXC_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
- );
- mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
- );
-#endif
-
imx27_add_imx_uart1(&uart_pdata);
imx27_add_imx_uart2(&uart_pdata);
#if !defined(MACH_EUKREA_CPUIMX27_USEUART4)
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
index d817fc80b986..aaa592fdb9ce 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
@@ -37,7 +37,6 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
#include "devices-imx51.h"
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 66e8726253fa..2cf603e11c4f 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -31,7 +31,6 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/mx25.h>
-#include <mach/audmux.h>
#include "devices-imx25.h"
@@ -241,22 +240,6 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
ARRAY_SIZE(eukrea_mbimxsd_pads)))
printk(KERN_ERR "error setting mbimxsd pads !\n");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
- /* SSI unit master I2S codec connected to SSI_AUD5*/
- mxc_audmux_v2_configure_port(0,
- MXC_AUDMUX_V2_PTCR_SYN |
- MXC_AUDMUX_V2_PTCR_TFSDIR |
- MXC_AUDMUX_V2_PTCR_TFSEL(4) |
- MXC_AUDMUX_V2_PTCR_TCLKDIR |
- MXC_AUDMUX_V2_PTCR_TCSEL(4),
- MXC_AUDMUX_V2_PDCR_RXDSEL(4)
- );
- mxc_audmux_v2_configure_port(4,
- MXC_AUDMUX_V2_PTCR_SYN,
- MXC_AUDMUX_V2_PDCR_RXDSEL(0)
- );
-#endif
-
imx25_add_imx_uart1(&uart_pdata);
imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata);
imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 0f0af02b3182..fd8bf8a425a7 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -38,7 +38,6 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-mx35.h>
-#include <mach/audmux.h>
#include "devices-imx35.h"
@@ -252,22 +251,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
ARRAY_SIZE(eukrea_mbimxsd_pads)))
printk(KERN_ERR "error setting mbimxsd pads !\n");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
- /* SSI unit master I2S codec connected to SSI_AUD4 */
- mxc_audmux_v2_configure_port(0,
- MXC_AUDMUX_V2_PTCR_SYN |
- MXC_AUDMUX_V2_PTCR_TFSDIR |
- MXC_AUDMUX_V2_PTCR_TFSEL(3) |
- MXC_AUDMUX_V2_PTCR_TCLKDIR |
- MXC_AUDMUX_V2_PTCR_TCSEL(3),
- MXC_AUDMUX_V2_PDCR_RXDSEL(3)
- );
- mxc_audmux_v2_configure_port(3,
- MXC_AUDMUX_V2_PTCR_SYN,
- MXC_AUDMUX_V2_PDCR_RXDSEL(0)
- );
-#endif
-
imx35_add_imx_uart1(&uart_pdata);
imx35_add_ipu_core(&mx3_ipu_data);
imx35_add_mx3_sdc_fb(&mx3fb_pdata);
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index c2766ae02b4f..428459fbca4b 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -263,6 +263,7 @@ static void __init visstrim_m10_board_init(void)
imx27_add_fec(NULL);
imx_add_gpio_keys(&visstrim_gpio_keys_platform_data);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0);
}
static void __init visstrim_m10_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index d3b9c6b5edde..541152e450c4 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -36,7 +36,6 @@
#include <mach/hardware.h>
#include <mach/iomux-mx27.h>
#include <asm/mach/time.h>
-#include <mach/audmux.h>
#include <mach/irqs.h>
#include <mach/ulpi.h>
@@ -359,18 +358,6 @@ static void __init pca100_init(void)
imx27_soc_init();
- /* SSI unit */
- mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
- MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
- MXC_AUDMUX_V1_PCR_TFCSEL(3) |
- MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
- MXC_AUDMUX_V1_PCR_RXDSEL(3));
- mxc_audmux_v1_configure_port(3,
- MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
- MXC_AUDMUX_V1_PCR_TFCSEL(0) |
- MXC_AUDMUX_V1_PCR_TFSDIR |
- MXC_AUDMUX_V1_PCR_RXDSEL(0));
-
ret = mxc_gpio_setup_multiple_pins(pca100_pins,
ARRAY_SIZE(pca100_pins), "PCA100");
if (ret)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 06dc106519ae..237474fcca23 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -37,7 +37,6 @@
#include <mach/common.h>
#include <mach/iomux-mx35.h>
#include <mach/ulpi.h>
-#include <mach/audmux.h>
#include "devices-imx35.h"
@@ -362,18 +361,6 @@ static void __init pcm043_init(void)
mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
- mxc_audmux_v2_configure_port(3,
- MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
- MXC_AUDMUX_V2_PTCR_TFSEL(0) |
- MXC_AUDMUX_V2_PTCR_TFSDIR,
- MXC_AUDMUX_V2_PDCR_RXDSEL(0));
-
- mxc_audmux_v2_configure_port(0,
- MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
- MXC_AUDMUX_V2_PTCR_TCSEL(3) |
- MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
- MXC_AUDMUX_V2_PDCR_RXDSEL(3));
-
imx35_add_fec(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
imx35_add_imx2_wdt(NULL);
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 3f05dfebacc9..14d540edfd1e 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -75,6 +75,10 @@ void __init mx21_init_irq(void)
mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
}
+static const struct resource imx21_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX21_AUDMUX_BASE_ADDR, SZ_4K),
+};
+
void __init imx21_soc_init(void)
{
mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
@@ -85,4 +89,6 @@ void __init imx21_soc_init(void)
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
imx_add_imx_dma();
+ platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
+ ARRAY_SIZE(imx21_audmux_res));
}
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index cc4d152bd9bd..153b457acdc0 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -83,6 +83,10 @@ static struct sdma_platform_data imx25_sdma_pdata __initdata = {
.script_addrs = &imx25_sdma_script,
};
+static const struct resource imx25_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX25_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
void __init imx25_soc_init(void)
{
/* i.mx25 has the i.mx31 type gpio */
@@ -93,4 +97,7 @@ void __init imx25_soc_init(void)
/* i.mx25 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+ /* i.mx25 has the i.mx31 type audmux */
+ platform_device_register_simple("imx31-audmux", 0, imx25_audmux_res,
+ ARRAY_SIZE(imx25_audmux_res));
}
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index 96dd1f5ea7bd..8cb3f5e3e569 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -75,6 +75,10 @@ void __init mx27_init_irq(void)
mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
}
+static const struct resource imx27_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K),
+};
+
void __init imx27_soc_init(void)
{
/* i.mx27 has the i.mx21 type gpio */
@@ -86,4 +90,7 @@ void __init imx27_soc_init(void)
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
imx_add_imx_dma();
+ /* imx27 has the imx21 type audmux */
+ platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
+ ARRAY_SIZE(imx27_audmux_res));
}
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index 31807d2a8b7b..2530c151b7b3 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -158,6 +158,10 @@ static struct sdma_platform_data imx31_sdma_pdata __initdata = {
.script_addrs = &imx31_to2_sdma_script,
};
+static const struct resource imx31_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX31_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
void __init imx31_soc_init(void)
{
int to_version = mx31_revision() >> 4;
@@ -175,6 +179,8 @@ void __init imx31_soc_init(void)
}
imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+ platform_device_register_simple("imx31-audmux", 0, imx31_audmux_res,
+ ARRAY_SIZE(imx31_audmux_res));
}
#endif /* ifdef CONFIG_SOC_IMX31 */
@@ -241,6 +247,10 @@ static struct sdma_platform_data imx35_sdma_pdata __initdata = {
.script_addrs = &imx35_to2_sdma_script,
};
+static const struct resource imx35_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX35_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
void __init imx35_soc_init(void)
{
int to_version = mx35_revision() >> 4;
@@ -259,5 +269,8 @@ void __init imx35_soc_init(void)
}
imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+ /* i.mx35 has the i.mx31 type audmux */
+ platform_device_register_simple("imx31-audmux", 0, imx35_audmux_res,
+ ARRAY_SIZE(imx35_audmux_res));
}
#endif /* ifdef CONFIG_SOC_IMX35 */
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index bc17dfea3817..90d7880bb372 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -170,6 +170,18 @@ static struct sdma_platform_data imx53_sdma_pdata __initdata = {
.script_addrs = &imx53_sdma_script,
};
+static const struct resource imx50_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
+static const struct resource imx51_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
+static const struct resource imx53_audmux_res[] __initconst = {
+ DEFINE_RES_MEM(MX53_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
void __init imx50_soc_init(void)
{
/* i.mx50 has the i.mx31 type gpio */
@@ -179,6 +191,10 @@ void __init imx50_soc_init(void)
mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+
+ /* i.mx50 has the i.mx31 type audmux */
+ platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
+ ARRAY_SIZE(imx50_audmux_res));
}
void __init imx51_soc_init(void)
@@ -191,6 +207,9 @@ void __init imx51_soc_init(void)
/* i.mx51 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+ /* i.mx51 has the i.mx31 type audmux */
+ platform_device_register_simple("imx31-audmux", 0, imx51_audmux_res,
+ ARRAY_SIZE(imx51_audmux_res));
}
void __init imx53_soc_init(void)
@@ -206,4 +225,7 @@ void __init imx53_soc_init(void)
/* i.mx53 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+ /* i.mx53 has the i.mx31 type audmux */
+ platform_device_register_simple("imx31-audmux", 0, imx53_audmux_res,
+ ARRAY_SIZE(imx53_audmux_res));
}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index cc15426787b1..77d4852e19f2 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -27,6 +27,7 @@
#include <plat/cache-feroceon-l2.h>
#include <plat/mvsdio.h>
#include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
#include <plat/common.h>
#include <plat/time.h>
#include <plat/addr-map.h>
@@ -73,7 +74,7 @@ unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
void __init kirkwood_ehci_init(void)
{
kirkwood_clk_ctrl |= CGC_USB0;
- orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB);
+ orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
}
diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
index e8fda45c0736..d5a0d1da2e0e 100644
--- a/arch/arm/mach-kirkwood/mpp.h
+++ b/arch/arm/mach-kirkwood/mpp.h
@@ -31,314 +31,314 @@
#define MPP_F6282_MASK MPP( 0, 0x0, 0, 0, 0, 0, 0, 0, 1 )
#define MPP0_GPIO MPP( 0, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP0_NF_IO2 MPP( 0, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP0_SPI_SCn MPP( 0, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP0_NF_IO2 MPP( 0, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP0_SPI_SCn MPP( 0, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP1_GPO MPP( 1, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP1_NF_IO3 MPP( 1, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP1_SPI_MOSI MPP( 1, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP1_NF_IO3 MPP( 1, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP1_SPI_MOSI MPP( 1, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP2_GPO MPP( 2, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP2_NF_IO4 MPP( 2, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP2_SPI_SCK MPP( 2, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP2_NF_IO4 MPP( 2, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP2_SPI_SCK MPP( 2, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP3_GPO MPP( 3, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP3_NF_IO5 MPP( 3, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP3_SPI_MISO MPP( 3, 0x2, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP3_NF_IO5 MPP( 3, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP3_SPI_MISO MPP( 3, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP4_GPIO MPP( 4, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP4_NF_IO6 MPP( 4, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP4_UART0_RXD MPP( 4, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP4_SATA1_ACTn MPP( 4, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP4_NF_IO6 MPP( 4, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP4_UART0_RXD MPP( 4, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP4_SATA1_ACTn MPP( 4, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP4_LCD_VGA_HSYNC MPP( 4, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP4_PTP_CLK MPP( 4, 0xd, 1, 0, 1, 1, 1, 1, 0 )
+#define MPP4_PTP_CLK MPP( 4, 0xd, 0, 0, 1, 1, 1, 1, 0 )
#define MPP5_GPO MPP( 5, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP5_NF_IO7 MPP( 5, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP5_UART0_TXD MPP( 5, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP5_PTP_TRIG_GEN MPP( 5, 0x4, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP5_SATA0_ACTn MPP( 5, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP5_NF_IO7 MPP( 5, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP5_UART0_TXD MPP( 5, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP5_PTP_TRIG_GEN MPP( 5, 0x4, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP5_SATA0_ACTn MPP( 5, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP5_LCD_VGA_VSYNC MPP( 5, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP6_SYSRST_OUTn MPP( 6, 0x1, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP6_SPI_MOSI MPP( 6, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP6_PTP_TRIG_GEN MPP( 6, 0x3, 0, 1, 1, 1, 1, 1, 0 )
+#define MPP6_SYSRST_OUTn MPP( 6, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP6_SPI_MOSI MPP( 6, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP6_PTP_TRIG_GEN MPP( 6, 0x3, 0, 0, 1, 1, 1, 1, 0 )
#define MPP7_GPO MPP( 7, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP7_PEX_RST_OUTn MPP( 7, 0x1, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP7_SPI_SCn MPP( 7, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP7_PTP_TRIG_GEN MPP( 7, 0x3, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP7_LCD_PWM MPP( 7, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP7_PEX_RST_OUTn MPP( 7, 0x1, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP7_SPI_SCn MPP( 7, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP7_PTP_TRIG_GEN MPP( 7, 0x3, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP7_LCD_PWM MPP( 7, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP8_GPIO MPP( 8, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP8_TW0_SDA MPP( 8, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP8_UART0_RTS MPP( 8, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP8_UART1_RTS MPP( 8, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP8_MII0_RXERR MPP( 8, 0x4, 1, 0, 0, 1, 1, 1, 1 )
-#define MPP8_SATA1_PRESENTn MPP( 8, 0x5, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP8_PTP_CLK MPP( 8, 0xc, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP8_MII0_COL MPP( 8, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP8_TW0_SDA MPP( 8, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_UART0_RTS MPP( 8, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_UART1_RTS MPP( 8, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_MII0_RXERR MPP( 8, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP8_SATA1_PRESENTn MPP( 8, 0x5, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP8_PTP_CLK MPP( 8, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP8_MII0_COL MPP( 8, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP9_GPIO MPP( 9, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP9_TW0_SCK MPP( 9, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP9_UART0_CTS MPP( 9, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP9_UART1_CTS MPP( 9, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP9_SATA0_PRESENTn MPP( 9, 0x5, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP9_PTP_EVENT_REQ MPP( 9, 0xc, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP9_MII0_CRS MPP( 9, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP9_TW0_SCK MPP( 9, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_UART0_CTS MPP( 9, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_UART1_CTS MPP( 9, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_SATA0_PRESENTn MPP( 9, 0x5, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP9_PTP_EVENT_REQ MPP( 9, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP9_MII0_CRS MPP( 9, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP10_GPO MPP( 10, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_SPI_SCK MPP( 10, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 1, 1, 1, 1, 1, 0 )
+#define MPP10_SPI_SCK MPP( 10, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 0, 1, 1, 1, 1, 0 )
#define MPP11_GPIO MPP( 11, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP11_SPI_MISO MPP( 11, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP11_UART0_RXD MPP( 11, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_CLK MPP( 11, 0xd, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP11_SPI_MISO MPP( 11, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP11_UART0_RXD MPP( 11, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_PTP_CLK MPP( 11, 0xd, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP12_GPO MPP( 12, 0x0, 0, 1, 1, 1, 1, 1, 1 )
#define MPP12_GPIO MPP( 12, 0x0, 1, 1, 0, 0, 0, 1, 0 )
-#define MPP12_SD_CLK MPP( 12, 0x1, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP12_TW1_SDA MPP( 12, 0xd, 1, 0, 0, 0, 0, 0, 1 )
+#define MPP12_SD_CLK MPP( 12, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP12_TW1_SDA MPP( 12, 0xd, 0, 0, 0, 0, 0, 0, 1 )
#define MPP13_GPIO MPP( 13, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP13_SD_CMD MPP( 13, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP13_UART1_TXD MPP( 13, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP13_AU_SPDIFRMCLK MPP( 13, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP13_LCDPWM MPP( 13, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP13_SD_CMD MPP( 13, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP13_UART1_TXD MPP( 13, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP13_AU_SPDIFRMCLK MPP( 13, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP13_LCDPWM MPP( 13, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP14_GPIO MPP( 14, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP14_SD_D0 MPP( 14, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP14_UART1_RXD MPP( 14, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP14_SATA1_PRESENTn MPP( 14, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP14_AU_SPDIFI MPP( 14, 0xa, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP14_AU_I2SDI MPP( 14, 0xb, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP14_MII0_COL MPP( 14, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP14_SD_D0 MPP( 14, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP14_UART1_RXD MPP( 14, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP14_SATA1_PRESENTn MPP( 14, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP14_AU_SPDIFI MPP( 14, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP14_AU_I2SDI MPP( 14, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP14_MII0_COL MPP( 14, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP15_GPIO MPP( 15, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP15_SD_D1 MPP( 15, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP15_UART0_RTS MPP( 15, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP15_UART1_TXD MPP( 15, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP15_SATA0_ACTn MPP( 15, 0x4, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP15_SPI_CSn MPP( 15, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP15_SD_D1 MPP( 15, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_UART0_RTS MPP( 15, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_UART1_TXD MPP( 15, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_SATA0_ACTn MPP( 15, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP15_SPI_CSn MPP( 15, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP16_GPIO MPP( 16, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP16_SD_D2 MPP( 16, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP16_UART0_CTS MPP( 16, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP16_UART1_RXD MPP( 16, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP16_SATA1_ACTn MPP( 16, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP16_LCD_EXT_REF_CLK MPP( 16, 0xb, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP16_MII0_CRS MPP( 16, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP16_SD_D2 MPP( 16, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_UART0_CTS MPP( 16, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_UART1_RXD MPP( 16, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_SATA1_ACTn MPP( 16, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP16_LCD_EXT_REF_CLK MPP( 16, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP16_MII0_CRS MPP( 16, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP17_GPIO MPP( 17, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP17_SD_D3 MPP( 17, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP17_SATA0_PRESENTn MPP( 17, 0x4, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP17_SATA1_ACTn MPP( 17, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP17_TW1_SCK MPP( 17, 0xd, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP17_SD_D3 MPP( 17, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP17_SATA0_PRESENTn MPP( 17, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP17_SATA1_ACTn MPP( 17, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP17_TW1_SCK MPP( 17, 0xd, 0, 0, 0, 0, 0, 0, 1 )
#define MPP18_GPO MPP( 18, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP18_NF_IO0 MPP( 18, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP18_PEX0_CLKREQ MPP( 18, 0x2, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP18_NF_IO0 MPP( 18, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP18_PEX0_CLKREQ MPP( 18, 0x2, 0, 0, 0, 0, 0, 0, 1 )
#define MPP19_GPO MPP( 19, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP19_NF_IO1 MPP( 19, 0x1, 1, 1, 1, 1, 1, 1, 1 )
+#define MPP19_NF_IO1 MPP( 19, 0x1, 0, 0, 1, 1, 1, 1, 1 )
#define MPP20_GPIO MPP( 20, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP20_TSMP0 MPP( 20, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP20_TDM_CH0_TX_QL MPP( 20, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP20_TSMP0 MPP( 20, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP20_TDM_CH0_TX_QL MPP( 20, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP20_GE1_TXD0 MPP( 20, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP20_AU_SPDIFI MPP( 20, 0x4, 1, 0, 0, 0, 1, 1, 1 )
-#define MPP20_SATA1_ACTn MPP( 20, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP20_AU_SPDIFI MPP( 20, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP20_SATA1_ACTn MPP( 20, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP20_LCD_D0 MPP( 20, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP21_GPIO MPP( 21, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP21_TSMP1 MPP( 21, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP21_TDM_CH0_RX_QL MPP( 21, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP21_TSMP1 MPP( 21, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP21_TDM_CH0_RX_QL MPP( 21, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP21_GE1_TXD1 MPP( 21, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP21_AU_SPDIFO MPP( 21, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP21_SATA0_ACTn MPP( 21, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP21_AU_SPDIFO MPP( 21, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP21_SATA0_ACTn MPP( 21, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP21_LCD_D1 MPP( 21, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP22_GPIO MPP( 22, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP22_TSMP2 MPP( 22, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP22_TDM_CH2_TX_QL MPP( 22, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP22_TSMP2 MPP( 22, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP22_TDM_CH2_TX_QL MPP( 22, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP22_GE1_TXD2 MPP( 22, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP22_AU_SPDIFRMKCLK MPP( 22, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP22_SATA1_PRESENTn MPP( 22, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP22_AU_SPDIFRMKCLK MPP( 22, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP22_SATA1_PRESENTn MPP( 22, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP22_LCD_D2 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP23_GPIO MPP( 23, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP23_TSMP3 MPP( 23, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP23_TDM_CH2_RX_QL MPP( 23, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP23_TSMP3 MPP( 23, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP23_TDM_CH2_RX_QL MPP( 23, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP23_GE1_TXD3 MPP( 23, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP23_AU_I2SBCLK MPP( 23, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP23_SATA0_PRESENTn MPP( 23, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP23_AU_I2SBCLK MPP( 23, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP23_SATA0_PRESENTn MPP( 23, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP23_LCD_D3 MPP( 23, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP24_GPIO MPP( 24, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP24_TSMP4 MPP( 24, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP24_TDM_SPI_CS0 MPP( 24, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP24_TSMP4 MPP( 24, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP24_TDM_SPI_CS0 MPP( 24, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP24_GE1_RXD0 MPP( 24, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP24_AU_I2SDO MPP( 24, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP24_AU_I2SDO MPP( 24, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP24_LCD_D4 MPP( 24, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP25_GPIO MPP( 25, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP25_TSMP5 MPP( 25, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP25_TDM_SPI_SCK MPP( 25, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP25_TSMP5 MPP( 25, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP25_TDM_SPI_SCK MPP( 25, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP25_GE1_RXD1 MPP( 25, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP25_AU_I2SLRCLK MPP( 25, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP25_AU_I2SLRCLK MPP( 25, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP25_LCD_D5 MPP( 25, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP26_GPIO MPP( 26, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP26_TSMP6 MPP( 26, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP26_TDM_SPI_MISO MPP( 26, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP26_TSMP6 MPP( 26, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP26_TDM_SPI_MISO MPP( 26, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP26_GE1_RXD2 MPP( 26, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP26_AU_I2SMCLK MPP( 26, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP26_AU_I2SMCLK MPP( 26, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP26_LCD_D6 MPP( 26, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP27_GPIO MPP( 27, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP27_TSMP7 MPP( 27, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP27_TDM_SPI_MOSI MPP( 27, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP27_TSMP7 MPP( 27, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP27_TDM_SPI_MOSI MPP( 27, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP27_GE1_RXD3 MPP( 27, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP27_AU_I2SDI MPP( 27, 0x4, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP27_AU_I2SDI MPP( 27, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP27_LCD_D7 MPP( 27, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP28_GPIO MPP( 28, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP28_TSMP8 MPP( 28, 0x1, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP28_TSMP8 MPP( 28, 0x1, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_TDM_CODEC_INTn MPP( 28, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_GE1_COL MPP( 28, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP28_AU_EXTCLK MPP( 28, 0x4, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP28_AU_EXTCLK MPP( 28, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_LCD_D8 MPP( 28, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP29_GPIO MPP( 29, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP29_TSMP9 MPP( 29, 0x1, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP29_TSMP9 MPP( 29, 0x1, 0, 0, 0, 0, 1, 1, 1 )
#define MPP29_TDM_CODEC_RSTn MPP( 29, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP29_GE1_TCLK MPP( 29, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP29_LCD_D9 MPP( 29, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP30_GPIO MPP( 30, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP30_TSMP10 MPP( 30, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP30_TDM_PCLK MPP( 30, 0x2, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP30_TSMP10 MPP( 30, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP30_TDM_PCLK MPP( 30, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP30_GE1_RXCTL MPP( 30, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP30_LCD_D10 MPP( 30, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP31_GPIO MPP( 31, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP31_TSMP11 MPP( 31, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP31_TDM_FS MPP( 31, 0x2, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP31_TSMP11 MPP( 31, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP31_TDM_FS MPP( 31, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP31_GE1_RXCLK MPP( 31, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP31_LCD_D11 MPP( 31, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP32_GPIO MPP( 32, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP32_TSMP12 MPP( 32, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP32_TDM_DRX MPP( 32, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP32_TSMP12 MPP( 32, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP32_TDM_DRX MPP( 32, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP32_GE1_TCLKOUT MPP( 32, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP32_LCD_D12 MPP( 32, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP33_GPO MPP( 33, 0x0, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP33_TDM_DTX MPP( 33, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP33_TDM_DTX MPP( 33, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP33_GE1_TXCTL MPP( 33, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP33_LCD_D13 MPP( 33, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP34_GPIO MPP( 34, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP34_TDM_SPI_CS1 MPP( 34, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP34_TDM_SPI_CS1 MPP( 34, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP34_GE1_TXEN MPP( 34, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP34_SATA1_ACTn MPP( 34, 0x5, 0, 1, 0, 0, 0, 1, 1 )
+#define MPP34_SATA1_ACTn MPP( 34, 0x5, 0, 0, 0, 0, 0, 1, 1 )
#define MPP34_LCD_D14 MPP( 34, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP35_GPIO MPP( 35, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP35_TDM_CH0_TX_QL MPP( 35, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP35_TDM_CH0_TX_QL MPP( 35, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP35_GE1_RXERR MPP( 35, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP35_SATA0_ACTn MPP( 35, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP35_SATA0_ACTn MPP( 35, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP35_LCD_D15 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP35_MII0_RXERR MPP( 35, 0xc, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP35_MII0_RXERR MPP( 35, 0xc, 0, 0, 1, 1, 1, 1, 1 )
#define MPP36_GPIO MPP( 36, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP36_TSMP0 MPP( 36, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP36_TDM_SPI_CS1 MPP( 36, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP36_AU_SPDIFI MPP( 36, 0x4, 1, 0, 1, 0, 0, 1, 1 )
-#define MPP36_TW1_SDA MPP( 36, 0xb, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP36_TSMP0 MPP( 36, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP36_TDM_SPI_CS1 MPP( 36, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP36_AU_SPDIFI MPP( 36, 0x4, 0, 0, 1, 0, 0, 1, 1 )
+#define MPP36_TW1_SDA MPP( 36, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP37_GPIO MPP( 37, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP37_TSMP1 MPP( 37, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP37_TDM_CH2_TX_QL MPP( 37, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP37_AU_SPDIFO MPP( 37, 0x4, 0, 1, 1, 0, 0, 1, 1 )
-#define MPP37_TW1_SCK MPP( 37, 0xb, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP37_TSMP1 MPP( 37, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP37_TDM_CH2_TX_QL MPP( 37, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP37_AU_SPDIFO MPP( 37, 0x4, 0, 0, 1, 0, 0, 1, 1 )
+#define MPP37_TW1_SCK MPP( 37, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP38_GPIO MPP( 38, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP38_TSMP2 MPP( 38, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP38_TDM_CH2_RX_QL MPP( 38, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP38_AU_SPDIFRMLCLK MPP( 38, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP38_TSMP2 MPP( 38, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP38_TDM_CH2_RX_QL MPP( 38, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP38_AU_SPDIFRMLCLK MPP( 38, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP38_LCD_D18 MPP( 38, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP39_GPIO MPP( 39, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP39_TSMP3 MPP( 39, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP39_TDM_SPI_CS0 MPP( 39, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP39_AU_I2SBCLK MPP( 39, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP39_TSMP3 MPP( 39, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP39_TDM_SPI_CS0 MPP( 39, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP39_AU_I2SBCLK MPP( 39, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP39_LCD_D19 MPP( 39, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP40_GPIO MPP( 40, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP40_TSMP4 MPP( 40, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP40_TDM_SPI_SCK MPP( 40, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP40_AU_I2SDO MPP( 40, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP40_TSMP4 MPP( 40, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP40_TDM_SPI_SCK MPP( 40, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP40_AU_I2SDO MPP( 40, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP40_LCD_D20 MPP( 40, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP41_GPIO MPP( 41, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP41_TSMP5 MPP( 41, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP41_TDM_SPI_MISO MPP( 41, 0x2, 1, 0, 0, 0, 0, 1, 1 )
-#define MPP41_AU_I2SLRCLK MPP( 41, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP41_TSMP5 MPP( 41, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP41_TDM_SPI_MISO MPP( 41, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP41_AU_I2SLRCLK MPP( 41, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP41_LCD_D21 MPP( 41, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP42_GPIO MPP( 42, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP42_TSMP6 MPP( 42, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP42_TDM_SPI_MOSI MPP( 42, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP42_AU_I2SMCLK MPP( 42, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP42_TSMP6 MPP( 42, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP42_TDM_SPI_MOSI MPP( 42, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP42_AU_I2SMCLK MPP( 42, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP42_LCD_D22 MPP( 42, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP43_GPIO MPP( 43, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP43_TSMP7 MPP( 43, 0x1, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP43_TSMP7 MPP( 43, 0x1, 0, 0, 0, 0, 0, 1, 1 )
#define MPP43_TDM_CODEC_INTn MPP( 43, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP43_AU_I2SDI MPP( 43, 0x4, 1, 0, 1, 0, 0, 1, 1 )
+#define MPP43_AU_I2SDI MPP( 43, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP43_LCD_D23 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP44_GPIO MPP( 44, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP44_TSMP8 MPP( 44, 0x1, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP44_TSMP8 MPP( 44, 0x1, 0, 0, 0, 0, 0, 1, 1 )
#define MPP44_TDM_CODEC_RSTn MPP( 44, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP44_AU_EXTCLK MPP( 44, 0x4, 1, 0, 1, 0, 0, 1, 1 )
+#define MPP44_AU_EXTCLK MPP( 44, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP44_LCD_CLK MPP( 44, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP45_GPIO MPP( 45, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP45_TSMP9 MPP( 45, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP45_TDM_PCLK MPP( 45, 0x2, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP45_TSMP9 MPP( 45, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP45_TDM_PCLK MPP( 45, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP245_LCD_E MPP( 45, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP46_GPIO MPP( 46, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP46_TSMP10 MPP( 46, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP46_TDM_FS MPP( 46, 0x2, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP46_TSMP10 MPP( 46, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP46_TDM_FS MPP( 46, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP46_LCD_HSYNC MPP( 46, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP47_GPIO MPP( 47, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP47_TSMP11 MPP( 47, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP47_TDM_DRX MPP( 47, 0x2, 1, 0, 0, 0, 0, 1, 1 )
+#define MPP47_TSMP11 MPP( 47, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP47_TDM_DRX MPP( 47, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP47_LCD_VSYNC MPP( 47, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP48_GPIO MPP( 48, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP48_TSMP12 MPP( 48, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 1, 0, 0, 0, 1, 1 )
+#define MPP48_TSMP12 MPP( 48, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP48_LCD_D16 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP49_GPIO MPP( 49, 0x0, 1, 1, 0, 0, 0, 1, 0 )
#define MPP49_GPO MPP( 49, 0x0, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP49_TSMP9 MPP( 49, 0x1, 1, 1, 0, 0, 0, 1, 0 )
-#define MPP49_TDM_CH0_RX_QL MPP( 49, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP49_PTP_CLK MPP( 49, 0x5, 1, 0, 0, 0, 0, 1, 0 )
-#define MPP49_PEX0_CLKREQ MPP( 49, 0xa, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP49_TSMP9 MPP( 49, 0x1, 0, 0, 0, 0, 0, 1, 0 )
+#define MPP49_TDM_CH0_RX_QL MPP( 49, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP49_PTP_CLK MPP( 49, 0x5, 0, 0, 0, 0, 0, 1, 0 )
+#define MPP49_PEX0_CLKREQ MPP( 49, 0xa, 0, 0, 0, 0, 0, 0, 1 )
#define MPP49_LCD_D17 MPP( 49, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP_MAX 49
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 01f8c8992880..7e99c3f340fc 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -83,6 +83,11 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
},
};
+static struct platform_device openrd_client_audio_device = {
+ .name = "openrd-client-audio",
+ .id = -1,
+};
+
static int __initdata uart1;
static int __init sd_uart_selection(char *str)
@@ -172,6 +177,7 @@ static void __init openrd_init(void)
kirkwood_i2c_init();
if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
+ platform_device_register(&openrd_client_audio_device);
i2c_register_board_info(0, i2c_board_info,
ARRAY_SIZE(i2c_board_info));
kirkwood_audio_init();
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index 966b2b3bb813..f9d2a11b7f96 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -106,6 +106,11 @@ static struct platform_device hp_t5325_button_device = {
}
};
+static struct platform_device hp_t5325_audio_device = {
+ .name = "t5325-audio",
+ .id = -1,
+};
+
static unsigned int hp_t5325_mpp_config[] __initdata = {
MPP0_NF_IO2,
MPP1_SPI_MOSI,
@@ -179,6 +184,7 @@ static void __init hp_t5325_init(void)
kirkwood_sata_init(&hp_t5325_sata_data);
kirkwood_ehci_init();
platform_device_register(&hp_t5325_button_device);
+ platform_device_register(&hp_t5325_audio_device);
i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
kirkwood_audio_init();
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 0cdd41004ad0..a5dcf766a3f9 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -19,6 +19,7 @@
#include <mach/mv78xx0.h>
#include <mach/bridge-regs.h>
#include <plat/cache-feroceon-l2.h>
+#include <plat/ehci-orion.h>
#include <plat/orion_nand.h>
#include <plat/time.h>
#include <plat/common.h>
@@ -169,7 +170,7 @@ void __init mv78xx0_map_io(void)
****************************************************************************/
void __init mv78xx0_ehci0_init(void)
{
- orion_ehci_init(USB0_PHYS_BASE, IRQ_MV78XX0_USB_0);
+ orion_ehci_init(USB0_PHYS_BASE, IRQ_MV78XX0_USB_0, EHCI_PHY_NA);
}
diff --git a/arch/arm/mach-mv78xx0/mpp.h b/arch/arm/mach-mv78xx0/mpp.h
index b61b50927123..3752302ae2ee 100644
--- a/arch/arm/mach-mv78xx0/mpp.h
+++ b/arch/arm/mach-mv78xx0/mpp.h
@@ -24,296 +24,296 @@
#define MPP_78100_A0_MASK MPP(0, 0x0, 0, 0, 1)
#define MPP0_GPIO MPP(0, 0x0, 1, 1, 1)
-#define MPP0_GE0_COL MPP(0, 0x1, 1, 0, 1)
-#define MPP0_GE1_TXCLK MPP(0, 0x2, 0, 1, 1)
+#define MPP0_GE0_COL MPP(0, 0x1, 0, 0, 1)
+#define MPP0_GE1_TXCLK MPP(0, 0x2, 0, 0, 1)
#define MPP0_UNUSED MPP(0, 0x3, 0, 0, 1)
#define MPP1_GPIO MPP(1, 0x0, 1, 1, 1)
-#define MPP1_GE0_RXERR MPP(1, 0x1, 1, 0, 1)
-#define MPP1_GE1_TXCTL MPP(1, 0x2, 0, 1, 1)
+#define MPP1_GE0_RXERR MPP(1, 0x1, 0, 0, 1)
+#define MPP1_GE1_TXCTL MPP(1, 0x2, 0, 0, 1)
#define MPP1_UNUSED MPP(1, 0x3, 0, 0, 1)
#define MPP2_GPIO MPP(2, 0x0, 1, 1, 1)
-#define MPP2_GE0_CRS MPP(2, 0x1, 1, 0, 1)
-#define MPP2_GE1_RXCTL MPP(2, 0x2, 1, 0, 1)
+#define MPP2_GE0_CRS MPP(2, 0x1, 0, 0, 1)
+#define MPP2_GE1_RXCTL MPP(2, 0x2, 0, 0, 1)
#define MPP2_UNUSED MPP(2, 0x3, 0, 0, 1)
#define MPP3_GPIO MPP(3, 0x0, 1, 1, 1)
-#define MPP3_GE0_TXERR MPP(3, 0x1, 0, 1, 1)
-#define MPP3_GE1_RXCLK MPP(3, 0x2, 1, 0, 1)
+#define MPP3_GE0_TXERR MPP(3, 0x1, 0, 0, 1)
+#define MPP3_GE1_RXCLK MPP(3, 0x2, 0, 0, 1)
#define MPP3_UNUSED MPP(3, 0x3, 0, 0, 1)
#define MPP4_GPIO MPP(4, 0x0, 1, 1, 1)
-#define MPP4_GE0_TXD4 MPP(4, 0x1, 0, 1, 1)
-#define MPP4_GE1_TXD0 MPP(4, 0x2, 0, 1, 1)
+#define MPP4_GE0_TXD4 MPP(4, 0x1, 0, 0, 1)
+#define MPP4_GE1_TXD0 MPP(4, 0x2, 0, 0, 1)
#define MPP4_UNUSED MPP(4, 0x3, 0, 0, 1)
#define MPP5_GPIO MPP(5, 0x0, 1, 1, 1)
-#define MPP5_GE0_TXD5 MPP(5, 0x1, 0, 1, 1)
-#define MPP5_GE1_TXD1 MPP(5, 0x2, 0, 1, 1)
+#define MPP5_GE0_TXD5 MPP(5, 0x1, 0, 0, 1)
+#define MPP5_GE1_TXD1 MPP(5, 0x2, 0, 0, 1)
#define MPP5_UNUSED MPP(5, 0x3, 0, 0, 1)
#define MPP6_GPIO MPP(6, 0x0, 1, 1, 1)
-#define MPP6_GE0_TXD6 MPP(6, 0x1, 0, 1, 1)
-#define MPP6_GE1_TXD2 MPP(6, 0x2, 0, 1, 1)
+#define MPP6_GE0_TXD6 MPP(6, 0x1, 0, 0, 1)
+#define MPP6_GE1_TXD2 MPP(6, 0x2, 0, 0, 1)
#define MPP6_UNUSED MPP(6, 0x3, 0, 0, 1)
#define MPP7_GPIO MPP(7, 0x0, 1, 1, 1)
-#define MPP7_GE0_TXD7 MPP(7, 0x1, 0, 1, 1)
-#define MPP7_GE1_TXD3 MPP(7, 0x2, 0, 1, 1)
+#define MPP7_GE0_TXD7 MPP(7, 0x1, 0, 0, 1)
+#define MPP7_GE1_TXD3 MPP(7, 0x2, 0, 0, 1)
#define MPP7_UNUSED MPP(7, 0x3, 0, 0, 1)
#define MPP8_GPIO MPP(8, 0x0, 1, 1, 1)
-#define MPP8_GE0_RXD4 MPP(8, 0x1, 1, 0, 1)
-#define MPP8_GE1_RXD0 MPP(8, 0x2, 1, 0, 1)
+#define MPP8_GE0_RXD4 MPP(8, 0x1, 0, 0, 1)
+#define MPP8_GE1_RXD0 MPP(8, 0x2, 0, 0, 1)
#define MPP8_UNUSED MPP(8, 0x3, 0, 0, 1)
#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1)
-#define MPP9_GE0_RXD5 MPP(9, 0x1, 1, 0, 1)
-#define MPP9_GE1_RXD1 MPP(9, 0x2, 1, 0, 1)
+#define MPP9_GE0_RXD5 MPP(9, 0x1, 0, 0, 1)
+#define MPP9_GE1_RXD1 MPP(9, 0x2, 0, 0, 1)
#define MPP9_UNUSED MPP(9, 0x3, 0, 0, 1)
#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1)
-#define MPP10_GE0_RXD6 MPP(10, 0x1, 1, 0, 1)
-#define MPP10_GE1_RXD2 MPP(10, 0x2, 1, 0, 1)
+#define MPP10_GE0_RXD6 MPP(10, 0x1, 0, 0, 1)
+#define MPP10_GE1_RXD2 MPP(10, 0x2, 0, 0, 1)
#define MPP10_UNUSED MPP(10, 0x3, 0, 0, 1)
#define MPP11_GPIO MPP(11, 0x0, 1, 1, 1)
-#define MPP11_GE0_RXD7 MPP(11, 0x1, 1, 0, 1)
-#define MPP11_GE1_RXD3 MPP(11, 0x2, 1, 0, 1)
+#define MPP11_GE0_RXD7 MPP(11, 0x1, 0, 0, 1)
+#define MPP11_GE1_RXD3 MPP(11, 0x2, 0, 0, 1)
#define MPP11_UNUSED MPP(11, 0x3, 0, 0, 1)
#define MPP12_GPIO MPP(12, 0x0, 1, 1, 1)
-#define MPP12_M_BB MPP(12, 0x3, 1, 0, 1)
-#define MPP12_UA0_CTSn MPP(12, 0x4, 1, 0, 1)
-#define MPP12_NAND_FLASH_REn0 MPP(12, 0x5, 0, 1, 1)
-#define MPP12_TDM0_SCSn MPP(12, 0X6, 0, 1, 1)
+#define MPP12_M_BB MPP(12, 0x3, 0, 0, 1)
+#define MPP12_UA0_CTSn MPP(12, 0x4, 0, 0, 1)
+#define MPP12_NAND_FLASH_REn0 MPP(12, 0x5, 0, 0, 1)
+#define MPP12_TDM0_SCSn MPP(12, 0X6, 0, 0, 1)
#define MPP12_UNUSED MPP(12, 0x1, 0, 0, 1)
#define MPP13_GPIO MPP(13, 0x0, 1, 1, 1)
-#define MPP13_SYSRST_OUTn MPP(13, 0x3, 0, 1, 1)
-#define MPP13_UA0_RTSn MPP(13, 0x4, 0, 1, 1)
-#define MPP13_NAN_FLASH_WEn0 MPP(13, 0x5, 0, 1, 1)
-#define MPP13_TDM_SCLK MPP(13, 0x6, 0, 1, 1)
+#define MPP13_SYSRST_OUTn MPP(13, 0x3, 0, 0, 1)
+#define MPP13_UA0_RTSn MPP(13, 0x4, 0, 0, 1)
+#define MPP13_NAN_FLASH_WEn0 MPP(13, 0x5, 0, 0, 1)
+#define MPP13_TDM_SCLK MPP(13, 0x6, 0, 0, 1)
#define MPP13_UNUSED MPP(13, 0x1, 0, 0, 1)
#define MPP14_GPIO MPP(14, 0x0, 1, 1, 1)
-#define MPP14_SATA1_ACTn MPP(14, 0x3, 0, 1, 1)
-#define MPP14_UA1_CTSn MPP(14, 0x4, 1, 0, 1)
-#define MPP14_NAND_FLASH_REn1 MPP(14, 0x5, 0, 1, 1)
-#define MPP14_TDM_SMOSI MPP(14, 0x6, 0, 1, 1)
+#define MPP14_SATA1_ACTn MPP(14, 0x3, 0, 0, 1)
+#define MPP14_UA1_CTSn MPP(14, 0x4, 0, 0, 1)
+#define MPP14_NAND_FLASH_REn1 MPP(14, 0x5, 0, 0, 1)
+#define MPP14_TDM_SMOSI MPP(14, 0x6, 0, 0, 1)
#define MPP14_UNUSED MPP(14, 0x1, 0, 0, 1)
#define MPP15_GPIO MPP(15, 0x0, 1, 1, 1)
-#define MPP15_SATA0_ACTn MPP(15, 0x3, 0, 1, 1)
-#define MPP15_UA1_RTSn MPP(15, 0x4, 0, 1, 1)
-#define MPP15_NAND_FLASH_WEn1 MPP(15, 0x5, 0, 1, 1)
-#define MPP15_TDM_SMISO MPP(15, 0x6, 1, 0, 1)
+#define MPP15_SATA0_ACTn MPP(15, 0x3, 0, 0, 1)
+#define MPP15_UA1_RTSn MPP(15, 0x4, 0, 0, 1)
+#define MPP15_NAND_FLASH_WEn1 MPP(15, 0x5, 0, 0, 1)
+#define MPP15_TDM_SMISO MPP(15, 0x6, 0, 0, 1)
#define MPP15_UNUSED MPP(15, 0x1, 0, 0, 1)
#define MPP16_GPIO MPP(16, 0x0, 1, 1, 1)
-#define MPP16_SATA1_PRESENTn MPP(16, 0x3, 0, 1, 1)
-#define MPP16_UA2_TXD MPP(16, 0x4, 0, 1, 1)
-#define MPP16_NAND_FLASH_REn3 MPP(16, 0x5, 0, 1, 1)
-#define MPP16_TDM_INTn MPP(16, 0x6, 1, 0, 1)
+#define MPP16_SATA1_PRESENTn MPP(16, 0x3, 0, 0, 1)
+#define MPP16_UA2_TXD MPP(16, 0x4, 0, 0, 1)
+#define MPP16_NAND_FLASH_REn3 MPP(16, 0x5, 0, 0, 1)
+#define MPP16_TDM_INTn MPP(16, 0x6, 0, 0, 1)
#define MPP16_UNUSED MPP(16, 0x1, 0, 0, 1)
#define MPP17_GPIO MPP(17, 0x0, 1, 1, 1)
-#define MPP17_SATA0_PRESENTn MPP(17, 0x3, 0, 1, 1)
-#define MPP17_UA2_RXD MPP(17, 0x4, 1, 0, 1)
-#define MPP17_NAND_FLASH_WEn3 MPP(17, 0x5, 0, 1, 1)
-#define MPP17_TDM_RSTn MPP(17, 0x6, 0, 1, 1)
+#define MPP17_SATA0_PRESENTn MPP(17, 0x3, 0, 0, 1)
+#define MPP17_UA2_RXD MPP(17, 0x4, 0, 0, 1)
+#define MPP17_NAND_FLASH_WEn3 MPP(17, 0x5, 0, 0, 1)
+#define MPP17_TDM_RSTn MPP(17, 0x6, 0, 0, 1)
#define MPP17_UNUSED MPP(17, 0x1, 0, 0, 1)
#define MPP18_GPIO MPP(18, 0x0, 1, 1, 1)
-#define MPP18_UA0_CTSn MPP(18, 0x4, 1, 0, 1)
-#define MPP18_BOOT_FLASH_REn MPP(18, 0x5, 0, 1, 1)
+#define MPP18_UA0_CTSn MPP(18, 0x4, 0, 0, 1)
+#define MPP18_BOOT_FLASH_REn MPP(18, 0x5, 0, 0, 1)
#define MPP18_UNUSED MPP(18, 0x1, 0, 0, 1)
#define MPP19_GPIO MPP(19, 0x0, 1, 1, 1)
-#define MPP19_UA0_CTSn MPP(19, 0x4, 0, 1, 1)
-#define MPP19_BOOT_FLASH_WEn MPP(19, 0x5, 0, 1, 1)
+#define MPP19_UA0_CTSn MPP(19, 0x4, 0, 0, 1)
+#define MPP19_BOOT_FLASH_WEn MPP(19, 0x5, 0, 0, 1)
#define MPP19_UNUSED MPP(19, 0x1, 0, 0, 1)
#define MPP20_GPIO MPP(20, 0x0, 1, 1, 1)
-#define MPP20_UA1_CTSs MPP(20, 0x4, 1, 0, 1)
-#define MPP20_TDM_PCLK MPP(20, 0x6, 1, 1, 0)
+#define MPP20_UA1_CTSs MPP(20, 0x4, 0, 0, 1)
+#define MPP20_TDM_PCLK MPP(20, 0x6, 0, 0, 0)
#define MPP20_UNUSED MPP(20, 0x1, 0, 0, 1)
#define MPP21_GPIO MPP(21, 0x0, 1, 1, 1)
-#define MPP21_UA1_CTSs MPP(21, 0x4, 0, 1, 1)
-#define MPP21_TDM_FSYNC MPP(21, 0x6, 1, 1, 0)
+#define MPP21_UA1_CTSs MPP(21, 0x4, 0, 0, 1)
+#define MPP21_TDM_FSYNC MPP(21, 0x6, 0, 0, 0)
#define MPP21_UNUSED MPP(21, 0x1, 0, 0, 1)
#define MPP22_GPIO MPP(22, 0x0, 1, 1, 1)
-#define MPP22_UA3_TDX MPP(22, 0x4, 0, 1, 1)
-#define MPP22_NAND_FLASH_REn2 MPP(22, 0x5, 0, 1, 1)
-#define MPP22_TDM_DRX MPP(22, 0x6, 1, 0, 1)
+#define MPP22_UA3_TDX MPP(22, 0x4, 0, 0, 1)
+#define MPP22_NAND_FLASH_REn2 MPP(22, 0x5, 0, 0, 1)
+#define MPP22_TDM_DRX MPP(22, 0x6, 0, 0, 1)
#define MPP22_UNUSED MPP(22, 0x1, 0, 0, 1)
#define MPP23_GPIO MPP(23, 0x0, 1, 1, 1)
-#define MPP23_UA3_RDX MPP(23, 0x4, 1, 0, 1)
-#define MPP23_NAND_FLASH_WEn2 MPP(23, 0x5, 0, 1, 1)
-#define MPP23_TDM_DTX MPP(23, 0x6, 0, 1, 1)
+#define MPP23_UA3_RDX MPP(23, 0x4, 0, 0, 1)
+#define MPP23_NAND_FLASH_WEn2 MPP(23, 0x5, 0, 0, 1)
+#define MPP23_TDM_DTX MPP(23, 0x6, 0, 0, 1)
#define MPP23_UNUSED MPP(23, 0x1, 0, 0, 1)
#define MPP24_GPIO MPP(24, 0x0, 1, 1, 1)
-#define MPP24_UA2_TXD MPP(24, 0x4, 0, 1, 1)
-#define MPP24_TDM_INTn MPP(24, 0x6, 1, 0, 1)
+#define MPP24_UA2_TXD MPP(24, 0x4, 0, 0, 1)
+#define MPP24_TDM_INTn MPP(24, 0x6, 0, 0, 1)
#define MPP24_UNUSED MPP(24, 0x1, 0, 0, 1)
#define MPP25_GPIO MPP(25, 0x0, 1, 1, 1)
-#define MPP25_UA2_RXD MPP(25, 0x4, 1, 0, 1)
-#define MPP25_TDM_RSTn MPP(25, 0x6, 0, 1, 1)
+#define MPP25_UA2_RXD MPP(25, 0x4, 0, 0, 1)
+#define MPP25_TDM_RSTn MPP(25, 0x6, 0, 0, 1)
#define MPP25_UNUSED MPP(25, 0x1, 0, 0, 1)
#define MPP26_GPIO MPP(26, 0x0, 1, 1, 1)
-#define MPP26_UA2_CTSn MPP(26, 0x4, 1, 0, 1)
-#define MPP26_TDM_PCLK MPP(26, 0x6, 1, 1, 1)
+#define MPP26_UA2_CTSn MPP(26, 0x4, 0, 0, 1)
+#define MPP26_TDM_PCLK MPP(26, 0x6, 0, 0, 1)
#define MPP26_UNUSED MPP(26, 0x1, 0, 0, 1)
#define MPP27_GPIO MPP(27, 0x0, 1, 1, 1)
-#define MPP27_UA2_RTSn MPP(27, 0x4, 0, 1, 1)
-#define MPP27_TDM_FSYNC MPP(27, 0x6, 1, 1, 1)
+#define MPP27_UA2_RTSn MPP(27, 0x4, 0, 0, 1)
+#define MPP27_TDM_FSYNC MPP(27, 0x6, 0, 0, 1)
#define MPP27_UNUSED MPP(27, 0x1, 0, 0, 1)
#define MPP28_GPIO MPP(28, 0x0, 1, 1, 1)
-#define MPP28_UA3_TXD MPP(28, 0x4, 0, 1, 1)
-#define MPP28_TDM_DRX MPP(28, 0x6, 1, 0, 1)
+#define MPP28_UA3_TXD MPP(28, 0x4, 0, 0, 1)
+#define MPP28_TDM_DRX MPP(28, 0x6, 0, 0, 1)
#define MPP28_UNUSED MPP(28, 0x1, 0, 0, 1)
#define MPP29_GPIO MPP(29, 0x0, 1, 1, 1)
-#define MPP29_UA3_RXD MPP(29, 0x4, 1, 0, 1)
-#define MPP29_SYSRST_OUTn MPP(29, 0x5, 0, 1, 1)
-#define MPP29_TDM_DTX MPP(29, 0x6, 0, 1, 1)
+#define MPP29_UA3_RXD MPP(29, 0x4, 0, 0, 1)
+#define MPP29_SYSRST_OUTn MPP(29, 0x5, 0, 0, 1)
+#define MPP29_TDM_DTX MPP(29, 0x6, 0, 0, 1)
#define MPP29_UNUSED MPP(29, 0x1, 0, 0, 1)
#define MPP30_GPIO MPP(30, 0x0, 1, 1, 1)
-#define MPP30_UA3_CTSn MPP(30, 0x4, 1, 0, 1)
+#define MPP30_UA3_CTSn MPP(30, 0x4, 0, 0, 1)
#define MPP30_UNUSED MPP(30, 0x1, 0, 0, 1)
#define MPP31_GPIO MPP(31, 0x0, 1, 1, 1)
-#define MPP31_UA3_RTSn MPP(31, 0x4, 0, 1, 1)
-#define MPP31_TDM1_SCSn MPP(31, 0x6, 0, 1, 1)
+#define MPP31_UA3_RTSn MPP(31, 0x4, 0, 0, 1)
+#define MPP31_TDM1_SCSn MPP(31, 0x6, 0, 0, 1)
#define MPP31_UNUSED MPP(31, 0x1, 0, 0, 1)
#define MPP32_GPIO MPP(32, 0x1, 1, 1, 1)
-#define MPP32_UA3_TDX MPP(32, 0x4, 0, 1, 1)
-#define MPP32_SYSRST_OUTn MPP(32, 0x5, 0, 1, 1)
-#define MPP32_TDM0_RXQ MPP(32, 0x6, 0, 1, 1)
+#define MPP32_UA3_TDX MPP(32, 0x4, 0, 0, 1)
+#define MPP32_SYSRST_OUTn MPP(32, 0x5, 0, 0, 1)
+#define MPP32_TDM0_RXQ MPP(32, 0x6, 0, 0, 1)
#define MPP32_UNUSED MPP(32, 0x3, 0, 0, 1)
#define MPP33_GPIO MPP(33, 0x1, 1, 1, 1)
-#define MPP33_UA3_RDX MPP(33, 0x4, 1, 0, 1)
-#define MPP33_TDM0_TXQ MPP(33, 0x6, 0, 1, 1)
+#define MPP33_UA3_RDX MPP(33, 0x4, 0, 0, 1)
+#define MPP33_TDM0_TXQ MPP(33, 0x6, 0, 0, 1)
#define MPP33_UNUSED MPP(33, 0x3, 0, 0, 1)
#define MPP34_GPIO MPP(34, 0x1, 1, 1, 1)
-#define MPP34_UA2_TDX MPP(34, 0x4, 0, 1, 1)
-#define MPP34_TDM1_RXQ MPP(34, 0x6, 0, 1, 1)
+#define MPP34_UA2_TDX MPP(34, 0x4, 0, 0, 1)
+#define MPP34_TDM1_RXQ MPP(34, 0x6, 0, 0, 1)
#define MPP34_UNUSED MPP(34, 0x3, 0, 0, 1)
#define MPP35_GPIO MPP(35, 0x1, 1, 1, 1)
-#define MPP35_UA2_RDX MPP(35, 0x4, 1, 0, 1)
-#define MPP35_TDM1_TXQ MPP(35, 0x6, 0, 1, 1)
+#define MPP35_UA2_RDX MPP(35, 0x4, 0, 0, 1)
+#define MPP35_TDM1_TXQ MPP(35, 0x6, 0, 0, 1)
#define MPP35_UNUSED MPP(35, 0x3, 0, 0, 1)
#define MPP36_GPIO MPP(36, 0x1, 1, 1, 1)
-#define MPP36_UA0_CTSn MPP(36, 0x2, 1, 0, 1)
-#define MPP36_UA2_TDX MPP(36, 0x4, 0, 1, 1)
-#define MPP36_TDM0_SCSn MPP(36, 0x6, 0, 1, 1)
+#define MPP36_UA0_CTSn MPP(36, 0x2, 0, 0, 1)
+#define MPP36_UA2_TDX MPP(36, 0x4, 0, 0, 1)
+#define MPP36_TDM0_SCSn MPP(36, 0x6, 0, 0, 1)
#define MPP36_UNUSED MPP(36, 0x3, 0, 0, 1)
#define MPP37_GPIO MPP(37, 0x1, 1, 1, 1)
-#define MPP37_UA0_RTSn MPP(37, 0x2, 0, 1, 1)
-#define MPP37_UA2_RXD MPP(37, 0x4, 1, 0, 1)
-#define MPP37_SYSRST_OUTn MPP(37, 0x5, 0, 1, 1)
-#define MPP37_TDM_SCLK MPP(37, 0x6, 0, 1, 1)
+#define MPP37_UA0_RTSn MPP(37, 0x2, 0, 0, 1)
+#define MPP37_UA2_RXD MPP(37, 0x4, 0, 0, 1)
+#define MPP37_SYSRST_OUTn MPP(37, 0x5, 0, 0, 1)
+#define MPP37_TDM_SCLK MPP(37, 0x6, 0, 0, 1)
#define MPP37_UNUSED MPP(37, 0x3, 0, 0, 1)
#define MPP38_GPIO MPP(38, 0x1, 1, 1, 1)
-#define MPP38_UA1_CTSn MPP(38, 0x2, 1, 0, 1)
-#define MPP38_UA3_TXD MPP(38, 0x4, 0, 1, 1)
-#define MPP38_SYSRST_OUTn MPP(38, 0x5, 0, 1, 1)
-#define MPP38_TDM_SMOSI MPP(38, 0x6, 0, 1, 1)
+#define MPP38_UA1_CTSn MPP(38, 0x2, 0, 0, 1)
+#define MPP38_UA3_TXD MPP(38, 0x4, 0, 0, 1)
+#define MPP38_SYSRST_OUTn MPP(38, 0x5, 0, 0, 1)
+#define MPP38_TDM_SMOSI MPP(38, 0x6, 0, 0, 1)
#define MPP38_UNUSED MPP(38, 0x3, 0, 0, 1)
#define MPP39_GPIO MPP(39, 0x1, 1, 1, 1)
-#define MPP39_UA1_RTSn MPP(39, 0x2, 0, 1, 1)
-#define MPP39_UA3_RXD MPP(39, 0x4, 1, 0, 1)
-#define MPP39_SYSRST_OUTn MPP(39, 0x5, 0, 1, 1)
-#define MPP39_TDM_SMISO MPP(39, 0x6, 1, 0, 1)
+#define MPP39_UA1_RTSn MPP(39, 0x2, 0, 0, 1)
+#define MPP39_UA3_RXD MPP(39, 0x4, 0, 0, 1)
+#define MPP39_SYSRST_OUTn MPP(39, 0x5, 0, 0, 1)
+#define MPP39_TDM_SMISO MPP(39, 0x6, 0, 0, 1)
#define MPP39_UNUSED MPP(39, 0x3, 0, 0, 1)
#define MPP40_GPIO MPP(40, 0x1, 1, 1, 1)
-#define MPP40_TDM_INTn MPP(40, 0x6, 1, 0, 1)
+#define MPP40_TDM_INTn MPP(40, 0x6, 0, 0, 1)
#define MPP40_UNUSED MPP(40, 0x0, 0, 0, 1)
#define MPP41_GPIO MPP(41, 0x1, 1, 1, 1)
-#define MPP41_TDM_RSTn MPP(41, 0x6, 0, 1, 1)
+#define MPP41_TDM_RSTn MPP(41, 0x6, 0, 0, 1)
#define MPP41_UNUSED MPP(41, 0x0, 0, 0, 1)
#define MPP42_GPIO MPP(42, 0x1, 1, 1, 1)
-#define MPP42_TDM_PCLK MPP(42, 0x6, 1, 1, 1)
+#define MPP42_TDM_PCLK MPP(42, 0x6, 0, 0, 1)
#define MPP42_UNUSED MPP(42, 0x0, 0, 0, 1)
#define MPP43_GPIO MPP(43, 0x1, 1, 1, 1)
-#define MPP43_TDM_FSYNC MPP(43, 0x6, 1, 1, 1)
+#define MPP43_TDM_FSYNC MPP(43, 0x6, 0, 0, 1)
#define MPP43_UNUSED MPP(43, 0x0, 0, 0, 1)
#define MPP44_GPIO MPP(44, 0x1, 1, 1, 1)
-#define MPP44_TDM_DRX MPP(44, 0x6, 1, 0, 1)
+#define MPP44_TDM_DRX MPP(44, 0x6, 0, 0, 1)
#define MPP44_UNUSED MPP(44, 0x0, 0, 0, 1)
#define MPP45_GPIO MPP(45, 0x1, 1, 1, 1)
-#define MPP45_SATA0_ACTn MPP(45, 0x3, 0, 1, 1)
-#define MPP45_TDM_DRX MPP(45, 0x6, 0, 1, 1)
+#define MPP45_SATA0_ACTn MPP(45, 0x3, 0, 0, 1)
+#define MPP45_TDM_DRX MPP(45, 0x6, 0, 0, 1)
#define MPP45_UNUSED MPP(45, 0x0, 0, 0, 1)
#define MPP46_GPIO MPP(46, 0x1, 1, 1, 1)
-#define MPP46_TDM_SCSn MPP(46, 0x6, 0, 1, 1)
+#define MPP46_TDM_SCSn MPP(46, 0x6, 0, 0, 1)
#define MPP46_UNUSED MPP(46, 0x0, 0, 0, 1)
@@ -323,14 +323,14 @@
#define MPP48_GPIO MPP(48, 0x1, 1, 1, 1)
-#define MPP48_SATA1_ACTn MPP(48, 0x3, 0, 1, 1)
+#define MPP48_SATA1_ACTn MPP(48, 0x3, 0, 0, 1)
#define MPP48_UNUSED MPP(48, 0x2, 0, 0, 1)
#define MPP49_GPIO MPP(49, 0x1, 1, 1, 1)
-#define MPP49_SATA0_ACTn MPP(49, 0x3, 0, 1, 1)
-#define MPP49_M_BB MPP(49, 0x4, 1, 0, 1)
+#define MPP49_SATA0_ACTn MPP(49, 0x3, 0, 0, 1)
+#define MPP49_M_BB MPP(49, 0x4, 0, 0, 1)
#define MPP49_UNUSED MPP(49, 0x2, 0, 0, 1)
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 4f8d66f044e7..922ab0dc2bcd 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -37,7 +37,6 @@ comment "OMAP Board Type"
config MACH_OMAP_INNOVATOR
bool "TI Innovator"
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
- select OMAP_MCBSP
help
TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
have such a board.
@@ -45,7 +44,6 @@ config MACH_OMAP_INNOVATOR
config MACH_OMAP_H2
bool "TI H2 Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
- select OMAP_MCBSP
help
TI OMAP 1610/1611B H2 board support. Say Y here if you have such
a board.
@@ -72,7 +70,6 @@ config MACH_HERALD
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
- select OMAP_MCBSP
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 11c85cd2731a..9923f92b5450 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -6,7 +6,9 @@
obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
+obj-y += mcbsp.o
+endif
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 1d76a63c0983..187b2fe132e9 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -28,7 +28,6 @@
#include <plat/mux.h>
#include <plat/mmc.h>
#include <plat/omap7xx.h>
-#include <plat/mcbsp.h>
#include "clock.h"
@@ -250,16 +249,8 @@ static struct platform_device omap_pcm = {
.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);
}
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 91f9abbd3250..3e8410a99990 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -420,18 +420,6 @@ static int __init omap1_mcbsp_init(void)
return -ENODEV;
if (cpu_is_omap7xx())
- omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
- else if (cpu_is_omap15xx())
- omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
- else if (cpu_is_omap16xx())
- omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
-
- mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
- GFP_KERNEL);
- if (!mcbsp_ptr)
- return -ENOMEM;
-
- if (cpu_is_omap7xx())
omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
OMAP7XX_MCBSP_RES_SZ,
omap7xx_mcbsp_pdata,
@@ -449,7 +437,7 @@ static int __init omap1_mcbsp_init(void)
omap16xx_mcbsp_pdata,
OMAP16XX_MCBSP_COUNT);
- return omap_mcbsp_init();
+ return 0;
}
arch_initcall(omap1_mcbsp_init);
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 41e6612ecbaf..d965da45160e 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -213,13 +213,12 @@ config MACH_OMAP3_PANDORA
depends on ARCH_OMAP3
default y
select OMAP_PACKAGE_CBB
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP3_TOUCHBOOK
bool "OMAP3 Touch Book"
depends on ARCH_OMAP3
default y
- select BACKLIGHT_CLASS_DEVICE
config MACH_OMAP_3430SDP
bool "OMAP 3430 SDP board"
@@ -265,7 +264,7 @@ config MACH_OMAP_ZOOM2
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP_ZOOM3
bool "OMAP3630 Zoom3 board"
@@ -275,7 +274,7 @@ config MACH_OMAP_ZOOM3
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_CM_T35
bool "CompuLab CM-T35/CM-T3730 modules"
@@ -334,7 +333,7 @@ config MACH_OMAP_4430SDP
depends on ARCH_OMAP4
select OMAP_PACKAGE_CBL
select OMAP_PACKAGE_CBS
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP4_PANDA
bool "OMAP4 Panda Board"
@@ -342,7 +341,7 @@ config MACH_OMAP4_PANDA
depends on ARCH_OMAP4
select OMAP_PACKAGE_CBL
select OMAP_PACKAGE_CBS
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config OMAP3_EMU
bool "OMAP3 debugging peripherals"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index fc9b238cbc19..06326a6e460d 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -11,13 +11,15 @@ hwmod-common = omap_hwmod.o \
omap_hwmod_common_data.o
clock-common = clock.o clock_common_data.o \
clkt_dpll.o clkt_clksel.o
-secure-common = omap-smc.o omap-secure.o
+secure-common = omap-smc.o omap-secure.o
-obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
+obj-y += mcbsp.o
+endif
obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 39fba9df17fb..90c76d340fb3 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -41,6 +41,7 @@
#include <video/omap-panel-nokia-dsi.h>
#include <video/omap-panel-picodlp.h>
#include <linux/wl12xx.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
#include "mux.h"
#include "hsmmc.h"
@@ -52,8 +53,9 @@
#define ETH_KS8851_QUART 138
#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184
#define OMAP4_SFH7741_ENABLE_GPIO 188
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD 63 /* Hotplug detect */
#define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */
#define DLP_POWER_ON_GPIO 40
@@ -377,12 +379,40 @@ static struct platform_device sdp4430_dmic_codec = {
.id = -1,
};
+static struct omap_abe_twl6040_data sdp4430_abe_audio_data = {
+ .card_name = "SDP4430",
+ .has_hs = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ .has_hf = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ .has_ep = 1,
+ .has_aux = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ .has_vibra = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+
+ .has_dmic = 1,
+ .has_hsmic = 1,
+ .has_mainmic = 1,
+ .has_submic = 1,
+ .has_afm = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+
+ .jack_detection = 1,
+ /* MCLK input is 38.4MHz */
+ .mclk_freq = 38400000,
+};
+
+static struct platform_device sdp4430_abe_audio = {
+ .name = "omap-abe-twl6040",
+ .id = -1,
+ .dev = {
+ .platform_data = &sdp4430_abe_audio_data,
+ },
+};
+
static struct platform_device *sdp4430_devices[] __initdata = {
&sdp4430_gpio_keys_device,
&sdp4430_leds_gpio,
&sdp4430_leds_pwm,
&sdp4430_vbat,
&sdp4430_dmic_codec,
+ &sdp4430_abe_audio,
};
static struct omap_musb_board_data musb_board_data = {
@@ -603,8 +633,9 @@ static void __init omap_sfh7741prox_init(void)
}
static struct gpio sdp4430_hdmi_gpios[] = {
- { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
+ { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+ { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
};
static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -621,8 +652,7 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
{
- gpio_free(HDMI_GPIO_LS_OE);
- gpio_free(HDMI_GPIO_HPD);
+ gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
}
static struct nokia_dsi_panel_data dsi1_panel = {
@@ -738,6 +768,10 @@ static void sdp4430_lcd_init(void)
pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
}
+static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+ .hpd_gpio = HDMI_GPIO_HPD,
+};
+
static struct omap_dss_device sdp4430_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
@@ -745,6 +779,7 @@ static struct omap_dss_device sdp4430_hdmi_device = {
.platform_enable = sdp4430_panel_enable_hdmi,
.platform_disable = sdp4430_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,
+ .data = &sdp4430_hdmi_data,
};
static struct picodlp_panel_data sdp4430_picodlp_pdata = {
@@ -808,7 +843,7 @@ static struct omap_dss_board_info sdp4430_dss_data = {
.default_device = &sdp4430_lcd_device,
};
-static void omap_4430sdp_display_init(void)
+static void __init omap_4430sdp_display_init(void)
{
int r;
@@ -829,6 +864,10 @@ static void omap_4430sdp_display_init(void)
omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
else
omap_hdmi_init(0);
+
+ omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
}
#ifdef CONFIG_OMAP_MUX
@@ -841,7 +880,7 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
-static void omap4_sdp4430_wifi_mux_init(void)
+static void __init omap4_sdp4430_wifi_mux_init(void)
{
omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
OMAP_PIN_OFF_WAKEUPENABLE);
@@ -868,12 +907,17 @@ static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {
.board_tcxo_clock = WL12XX_TCXOCLOCK_26,
};
-static void omap4_sdp4430_wifi_init(void)
+static void __init omap4_sdp4430_wifi_init(void)
{
+ int ret;
+
omap4_sdp4430_wifi_mux_init();
- if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data))
- pr_err("Error setting wl12xx data\n");
- platform_device_register(&omap_vwlan_device);
+ ret = wl12xx_set_platform_data(&omap4_sdp4430_wlan_data);
+ if (ret)
+ pr_err("Error setting wl12xx data: %d\n", ret);
+ ret = platform_device_register(&omap_vwlan_device);
+ if (ret)
+ pr_err("Error registering wl12xx device: %d\n", ret);
}
static void __init omap_4430sdp_init(void)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e921e3be24a4..d73316ed4207 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -437,7 +437,7 @@ static struct usbhs_omap_board_data usbhs_bdata __initdata = {
.reset_gpio_port[2] = -EINVAL
};
-static void cm_t35_init_usbh(void)
+static void __init cm_t35_init_usbh(void)
{
int err;
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index d58756060483..ad497620539b 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -17,6 +17,7 @@
#include <linux/i2c/twl.h>
#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
#include <plat/board.h>
@@ -102,6 +103,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
.map_io = omap242x_map_io,
.init_early = omap2420_init_early,
.init_irq = omap2_init_irq,
+ .handle_irq = omap2_intc_handle_irq,
.init_machine = omap_generic_init,
.timer = &omap2_timer,
.dt_compat = omap242x_boards_compat,
@@ -141,6 +143,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
+ .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3_init,
.timer = &omap3_timer,
.dt_compat = omap3_boards_compat,
@@ -160,6 +163,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
.map_io = omap4_map_io,
.init_early = omap4430_init_early,
.init_irq = gic_init_irq,
+ .handle_irq = gic_handle_irq,
.init_machine = omap4_init,
.timer = &omap4_timer,
.dt_compat = omap4_boards_compat,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 003fe34c9343..c775bead1497 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -617,6 +617,21 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
{ OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW, "select EHCI port" },
};
+static void __init omap3_evm_wl12xx_init(void)
+{
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+ int ret;
+
+ /* WL12xx WLAN Init */
+ ret = wl12xx_set_platform_data(&omap3evm_wlan_data);
+ if (ret)
+ pr_err("error setting wl12xx data: %d\n", ret);
+ ret = platform_device_register(&omap3evm_wlan_regulator);
+ if (ret)
+ pr_err("error registering wl12xx device: %d\n", ret);
+#endif
+}
+
static void __init omap3_evm_init(void)
{
omap3_evm_get_revision();
@@ -665,13 +680,7 @@ static void __init omap3_evm_init(void)
omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
omap3evm_init_smsc911x();
omap3_evm_display_init();
-
-#ifdef CONFIG_WL12XX_PLATFORM_DATA
- /* WL12xx WLAN Init */
- if (wl12xx_set_platform_data(&omap3evm_wlan_data))
- pr_err("error setting wl12xx data\n");
- platform_device_register(&omap3evm_wlan_regulator);
-#endif
+ omap3_evm_wl12xx_init();
}
MACHINE_START(OMAP3EVM, "OMAP3 EVM")
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 30ad40db2cf3..e4415917693f 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -28,6 +28,7 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/wl12xx.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
#include <mach/hardware.h>
#include <asm/hardware/gic.h>
@@ -51,8 +52,9 @@
#define GPIO_HUB_NRESET 62
#define GPIO_WIFI_PMENA 43
#define GPIO_WIFI_IRQ 53
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD 63 /* Hotplug detect */
/* wl127x BT, FM, GPS connectivity chip */
static int wl1271_gpios[] = {46, -1, -1};
@@ -90,9 +92,34 @@ static struct platform_device leds_gpio = {
},
};
+static struct omap_abe_twl6040_data panda_abe_audio_data = {
+ /* Audio out */
+ .has_hs = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ /* HandsFree through expasion connector */
+ .has_hf = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ /* PandaBoard: FM TX, PandaBoardES: can be connected to audio out */
+ .has_aux = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ /* PandaBoard: FM RX, PandaBoardES: audio in */
+ .has_afm = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+ /* No jack detection. */
+ .jack_detection = 0,
+ /* MCLK input is 38.4MHz */
+ .mclk_freq = 38400000,
+
+};
+
+static struct platform_device panda_abe_audio = {
+ .name = "omap-abe-twl6040",
+ .id = -1,
+ .dev = {
+ .platform_data = &panda_abe_audio_data,
+ },
+};
+
static struct platform_device *panda_devices[] __initdata = {
&leds_gpio,
&wl1271_device,
+ &panda_abe_audio,
};
static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
@@ -251,8 +278,25 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
return 0;
}
+static struct twl4030_codec_data twl6040_codec = {
+ /* single-step ramp for headset and handsfree */
+ .hs_left_step = 0x0f,
+ .hs_right_step = 0x0f,
+ .hf_left_step = 0x1d,
+ .hf_right_step = 0x1d,
+};
+
+static struct twl4030_audio_data twl6040_audio = {
+ .codec = &twl6040_codec,
+ .audpwron_gpio = 127,
+ .naudint_irq = OMAP44XX_IRQ_SYS_2N,
+ .irq_base = TWL6040_CODEC_IRQ_BASE,
+};
+
/* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata;
+static struct twl4030_platform_data omap4_panda_twldata = {
+ .audio = &twl6040_audio,
+};
/*
* Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -413,8 +457,9 @@ int __init omap4_panda_dvi_init(void)
}
static struct gpio panda_hdmi_gpios[] = {
- { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
+ { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+ { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
};
static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -431,10 +476,13 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
{
- gpio_free(HDMI_GPIO_LS_OE);
- gpio_free(HDMI_GPIO_HPD);
+ gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
}
+static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+ .hpd_gpio = HDMI_GPIO_HPD,
+};
+
static struct omap_dss_device omap4_panda_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
@@ -442,6 +490,7 @@ static struct omap_dss_device omap4_panda_hdmi_device = {
.platform_enable = omap4_panda_panel_enable_hdmi,
.platform_disable = omap4_panda_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,
+ .data = &omap4_panda_hdmi_data,
};
static struct omap_dss_device *omap4_panda_dss_devices[] = {
@@ -473,19 +522,40 @@ void omap4_panda_display_init(void)
omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
else
omap_hdmi_init(0);
+
+ omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
+}
+
+static void omap4_panda_init_rev(void)
+{
+ if (cpu_is_omap443x()) {
+ /* PandaBoard 4430 */
+ /* ASoC audio configuration */
+ panda_abe_audio_data.card_name = "PandaBoard";
+ panda_abe_audio_data.has_hsmic = 1;
+ } else {
+ /* PandaBoard ES */
+ /* ASoC audio configuration */
+ panda_abe_audio_data.card_name = "PandaBoardES";
+ }
}
static void __init omap4_panda_init(void)
{
int package = OMAP_PACKAGE_CBS;
+ int ret;
if (omap_rev() == OMAP4430_REV_ES1_0)
package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, NULL, package);
- if (wl12xx_set_platform_data(&omap_panda_wlan_data))
- pr_err("error setting wl12xx data\n");
+ ret = wl12xx_set_platform_data(&omap_panda_wlan_data);
+ if (ret)
+ pr_err("error setting wl12xx data: %d\n", ret);
+ omap4_panda_init_rev();
omap4_panda_i2c_init();
platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
platform_device_register(&omap_vwlan_device);
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 8d7ce11cfeaf..c126461836ac 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -296,8 +296,10 @@ static void enable_board_wakeup_source(void)
void __init zoom_peripherals_init(void)
{
- if (wl12xx_set_platform_data(&omap_zoom_wlan_data))
- pr_err("error setting wl12xx data\n");
+ int ret = wl12xx_set_platform_data(&omap_zoom_wlan_data);
+
+ if (ret)
+ pr_err("error setting wl12xx data: %d\n", ret);
omap_i2c_init();
platform_device_register(&omap_vwlan_device);
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 0b510ad01a00..e9fae652cd04 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -26,7 +26,6 @@
#include <plat/tc.h>
#include <plat/board.h>
-#include <plat/mcbsp.h>
#include <plat/mmc.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
@@ -304,29 +303,8 @@ static struct platform_device omap_pcm = {
.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);
}
@@ -405,6 +383,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
break;
default:
pr_err("Invalid McSPI Revision value\n");
+ kfree(pdata);
return -EINVAL;
}
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 3c446d1a1781..3677b1f58b85 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -103,12 +103,8 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
u32 reg;
u16 control_i2c_1;
- /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
- omap_mux_init_signal("hdmi_hpd",
- OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_cec",
OMAP_PIN_INPUT_PULLUP);
- /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal("hdmi_ddc_scl",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_ddc_sda",
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 130034bf01d5..dfffbbf4c009 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
case GPMC_CONFIG_DEV_SIZE:
regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+ /* clear 2 target bits */
+ regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+
+ /* set the proper value */
regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
break;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index bd844af13af5..b40c28895298 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -175,14 +175,15 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)
{
u32 reg;
- if (mmc->slots[0].internal_clock) {
- reg = omap_ctrl_readl(control_devconf1_offset);
+ reg = omap_ctrl_readl(control_devconf1_offset);
+ if (mmc->slots[0].internal_clock)
reg |= OMAP2_MMCSDIO2ADPCLKISEL;
- omap_ctrl_writel(reg, control_devconf1_offset);
- }
+ else
+ reg &= ~OMAP2_MMCSDIO2ADPCLKISEL;
+ omap_ctrl_writel(reg, control_devconf1_offset);
}
-static void hsmmc23_before_set_reg(struct device *dev, int slot,
+static void hsmmc2_before_set_reg(struct device *dev, int slot,
int power_on, int vdd)
{
struct omap_mmc_platform_data *mmc = dev->platform_data;
@@ -292,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
}
}
-static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
- struct omap_mmc_platform_data *mmc)
+static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+ struct omap_mmc_platform_data *mmc)
{
char *hc_name;
@@ -407,14 +408,13 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
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) {
/* off-chip level shifting, or none */
- mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+ mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
mmc->slots[0].after_set_reg = NULL;
}
break;
+ case 3:
case 4:
case 5:
mmc->slots[0].before_set_reg = NULL;
@@ -430,7 +430,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
#define MAX_OMAP_MMC_HWMOD_NAME_LEN 16
-void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
{
struct omap_hwmod *oh;
struct platform_device *pdev;
@@ -487,7 +487,7 @@ done:
kfree(mmc_data);
}
-void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
{
u32 reg;
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 3f174d51f67f..eb50c29fb644 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -388,7 +388,7 @@ static void __init omap_hwmod_init_postsetup(void)
omap_pm_if_early_init();
}
-#ifdef CONFIG_ARCH_OMAP2
+#ifdef CONFIG_SOC_OMAP2420
void __init omap2420_init_early(void)
{
omap2_set_globals_242x();
@@ -400,7 +400,9 @@ void __init omap2420_init_early(void)
omap_hwmod_init_postsetup();
omap2420_clk_init();
}
+#endif
+#ifdef CONFIG_SOC_OMAP2430
void __init omap2430_init_early(void)
{
omap2_set_globals_243x();
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index fb4bcf81a183..ecc039e794db 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -34,7 +34,7 @@
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
-/* McBSP internal signal muxing function */
+/* McBSP1 internal signal muxing function for OMAP2/3 */
static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
const char *src)
{
@@ -65,6 +65,42 @@ static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
return 0;
}
+/* McBSP4 internal signal muxing function for OMAP4 */
+#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31)
+#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30)
+static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal,
+ const char *src)
+{
+ u32 v;
+
+ /*
+ * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR
+ * mux) is used */
+ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
+
+ if (!strcmp(signal, "clkr")) {
+ if (!strcmp(src, "clkr"))
+ v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
+ else if (!strcmp(src, "clkx"))
+ v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
+ else
+ return -EINVAL;
+ } else if (!strcmp(signal, "fsr")) {
+ if (!strcmp(src, "fsr"))
+ v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
+ else if (!strcmp(src, "fsx"))
+ v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
+ else
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
+
+ return 0;
+}
+
/* McBSP CLKS source switching function */
static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
const char *src)
@@ -146,9 +182,15 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
pdata->has_ccr = true;
}
pdata->set_clk_src = omap2_mcbsp_set_clk_src;
- if (id == 1)
+
+ /* On OMAP2/3 the McBSP1 port has 6 pin configuration */
+ if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4)
pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
+ /* On OMAP4 the McBSP4 port has 6 pin configuration */
+ if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4)
+ pdata->mux_signal = omap4_mcbsp4_mux_rx_clk;
+
if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
if (id == 2)
/* The FIFO has 1024 + 256 locations */
@@ -180,7 +222,6 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
name, oh->name);
return PTR_ERR(pdev);
}
- omap_mcbsp_count++;
return 0;
}
@@ -188,11 +229,6 @@ static int __init omap2_mcbsp_init(void)
{
omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
- mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
- GFP_KERNEL);
- if (!mcbsp_ptr)
- return -ENOMEM;
-
- return omap_mcbsp_init();
+ return 0;
}
arch_initcall(omap2_mcbsp_init);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index e1cc75d1a57a..fb8bc9fa43b1 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
static char *omap_mux_options;
-static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
- int gpio, int val)
+static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
+ int gpio, int val)
{
struct omap_mux_entry *e;
struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
return 0;
}
-int __init omap_mux_init_gpio(int gpio, int val)
+int omap_mux_init_gpio(int gpio, int val)
{
struct omap_mux_partition *partition;
int ret;
@@ -159,9 +159,9 @@ int __init omap_mux_init_gpio(int gpio, int val)
return -ENODEV;
}
-static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
- const char *muxname,
- struct omap_mux **found_mux)
+static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
+ const char *muxname,
+ struct omap_mux **found_mux)
{
struct omap_mux *mux = NULL;
struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
return -ENODEV;
}
-int __init omap_mux_init_signal(const char *muxname, int val)
+int omap_mux_init_signal(const char *muxname, int val)
{
struct omap_mux_partition *partition = NULL;
struct omap_mux *mux = NULL;
@@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
omap_mux_package_init_balls(package_balls, superset);
}
-static void omap_mux_init_signals(struct omap_mux_partition *partition,
- struct omap_board_mux *board_mux)
+static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
+ struct omap_board_mux *board_mux)
{
omap_mux_set_cmdline_signals();
omap_mux_write_array(partition, board_mux);
@@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
{
}
-static void omap_mux_init_signals(struct omap_mux_partition *partition,
- struct omap_board_mux *board_mux)
+static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
+ struct omap_board_mux *board_mux)
{
}
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index b13ef7ef5ef4..503ac777a2ba 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
+ __CPUINIT
/*
* OMAP4 specific entry point for secondary CPU to jump from ROM
* code. This routine also provides a holding flag into which
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 5192cabb40ed..eba6cd3816f5 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1517,8 +1517,8 @@ static int _enable(struct omap_hwmod *oh)
if (oh->_state != _HWMOD_STATE_INITIALIZED &&
oh->_state != _HWMOD_STATE_IDLE &&
oh->_state != _HWMOD_STATE_DISABLED) {
- WARN(1, "omap_hwmod: %s: enabled state can only be entered "
- "from initialized, idle, or disabled state\n", oh->name);
+ WARN(1, "omap_hwmod: %s: enabled state can only be entered from initialized, idle, or disabled state\n",
+ oh->name);
return -EINVAL;
}
@@ -1600,8 +1600,8 @@ static int _idle(struct omap_hwmod *oh)
pr_debug("omap_hwmod: %s: idling\n", oh->name);
if (oh->_state != _HWMOD_STATE_ENABLED) {
- WARN(1, "omap_hwmod: %s: idle state can only be entered from "
- "enabled state\n", oh->name);
+ WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n",
+ oh->name);
return -EINVAL;
}
@@ -1682,8 +1682,8 @@ static int _shutdown(struct omap_hwmod *oh)
if (oh->_state != _HWMOD_STATE_IDLE &&
oh->_state != _HWMOD_STATE_ENABLED) {
- WARN(1, "omap_hwmod: %s: disabled state can only be entered "
- "from idle, or enabled state\n", oh->name);
+ WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n",
+ oh->name);
return -EINVAL;
}
@@ -2240,8 +2240,8 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
BUG_ON(!oh);
if (!oh->class->sysc || !oh->class->sysc->sysc_flags) {
- WARN(1, "omap_device: %s: OCP barrier impossible due to "
- "device configuration\n", oh->name);
+ WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n",
+ oh->name);
return;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index c11273da5dcc..f08e442af397 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -56,27 +56,6 @@ struct omap_hwmod_class omap2_dss_hwmod_class = {
};
/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dispc_hwmod_class = {
- .name = "dispc",
- .sysc = &omap2_dispc_sysc,
-};
-
-/*
* 'rfbi' class
* remote frame buffer interface
*/
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 177dee20faef..2a6729741b06 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -28,6 +28,28 @@ struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
{ .name = "dispc", .dma_req = 5 },
{ .dma_req = -1 }
};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap2_dispc_sysc,
+};
+
/* OMAP2xxx Timer Common */
static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
.rev_offs = 0x0000,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 5324e8d93bc0..3c8dd928628e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1480,6 +1480,28 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
.masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
};
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSC_HAS_ENAWAKEUP),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap3_dispc_sysc,
+};
+
/* l4_core -> dss_dispc */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
.master = &omap3xxx_l4_core_hwmod,
@@ -1503,7 +1525,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.name = "dss_dispc",
- .class = &omap2_dispc_hwmod_class,
+ .class = &omap3_dispc_hwmod_class,
.mpu_irqs = omap2_dispc_irqs,
.main_clk = "dss1_alwon_fck",
.prcm = {
@@ -3523,12 +3545,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_uart2_hwmod,
&omap3xxx_uart3_hwmod,
- /* dss class */
- &omap3xxx_dss_dispc_hwmod,
- &omap3xxx_dss_dsi1_hwmod,
- &omap3xxx_dss_rfbi_hwmod,
- &omap3xxx_dss_venc_hwmod,
-
/* i2c class */
&omap3xxx_i2c1_hwmod,
&omap3xxx_i2c2_hwmod,
@@ -3635,6 +3651,15 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = {
NULL
};
+static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = {
+ /* dss class */
+ &omap3xxx_dss_dispc_hwmod,
+ &omap3xxx_dss_dsi1_hwmod,
+ &omap3xxx_dss_rfbi_hwmod,
+ &omap3xxx_dss_venc_hwmod,
+ NULL
+};
+
int __init omap3xxx_hwmod_init(void)
{
int r;
@@ -3708,6 +3733,21 @@ int __init omap3xxx_hwmod_init(void)
if (h)
r = omap_hwmod_register(h);
+ if (r < 0)
+ return r;
+
+ /*
+ * DSS code presumes that dss_core hwmod is handled first,
+ * _before_ any other DSS related hwmods so register common
+ * DSS hwmods last to ensure that dss_core is already registered.
+ * Otherwise some change things may happen, for ex. if dispc
+ * is handled before dss_core and DSS is enabled in bootloader
+ * DIPSC will be reset with outputs enabled which sometimes leads
+ * to unrecoverable L3 error.
+ * XXX The long-term fix to this is to ensure modules are set up
+ * in dependency order in the hwmod core code.
+ */
+ r = omap_hwmod_register(omap3xxx_dss_hwmods);
return r;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index f9f151081760..ef0524c10a84 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1031,6 +1031,7 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
{
+ .name = "mpu",
.pa_start = 0x4012e000,
.pa_end = 0x4012e07f,
.flags = ADDR_TYPE_RT
@@ -1049,6 +1050,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
{
+ .name = "dma",
.pa_start = 0x4902e000,
.pa_end = 0x4902e07f,
.flags = ADDR_TYPE_RT
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index b8822f8b2891..23de98d03841 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -82,13 +82,7 @@ static int omap2_fclks_active(void)
f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
- /* Ignore UART clocks. These are handled by UART core (serial.c) */
- f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
- f2 &= ~OMAP24XX_EN_UART3_MASK;
-
- if (f1 | f2)
- return 1;
- return 0;
+ return (f1 | f2) ? 1 : 0;
}
static void omap2_enter_full_retention(void)
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index c1c4d86a79a8..9ce765407ad5 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -19,6 +19,7 @@
#include "common.h"
#include <plat/cpu.h>
#include <plat/prcm.h>
+#include <plat/irqs.h>
#include "vp.h"
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 33dd655e6aab..a1d6154dc120 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -19,6 +19,7 @@
#include "common.h"
#include <plat/cpu.h>
+#include <plat/irqs.h>
#include <plat/prcm.h>
#include "vp.h"
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 247d89478f24..f590afc1f673 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -107,18 +107,18 @@ static void omap_uart_set_noidle(struct platform_device *pdev)
omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
}
-static void omap_uart_set_forceidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct platform_device *pdev)
{
struct omap_device *od = to_omap_device(pdev);
- omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
}
#else
static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
{}
static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_forceidle(struct platform_device *pdev) {}
+static void omap_uart_set_smartidle(struct platform_device *pdev) {}
#endif /* CONFIG_PM */
#ifdef CONFIG_OMAP_MUX
@@ -349,7 +349,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
omap_up.flags = UPF_BOOT_AUTOCONF;
omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
- omap_up.set_forceidle = omap_uart_set_forceidle;
+ omap_up.set_forceidle = omap_uart_set_smartidle;
omap_up.set_noidle = omap_uart_set_noidle;
omap_up.enable_wakeup = omap_uart_enable_wakeup;
omap_up.dma_rx_buf_size = info->dma_rx_buf_size;
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 9dd93453e563..7e755bb0ffc4 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -897,7 +897,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
ret = sr_late_init(sr_info);
if (ret) {
pr_warning("%s: Error in SR late init\n", __func__);
- return ret;
+ goto err_iounmap;
}
}
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 6eeff0e0ae01..5c9acea95761 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -270,7 +270,7 @@ static struct clocksource clocksource_gpt = {
static u32 notrace dmtimer_read_sched_clock(void)
{
if (clksrc.reserved)
- return __omap_dm_timer_read_counter(clksrc.io_base, 1);
+ return __omap_dm_timer_read_counter(&clksrc, 1);
return 0;
}
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 031d116fbf10..175b7d86d86a 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -247,7 +247,7 @@ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
* omap_vc_i2c_init - initialize I2C interface to PMIC
* @voltdm: voltage domain containing VC data
*
- * Use PMIC supplied seetings for I2C high-speed mode and
+ * Use PMIC supplied settings for I2C high-speed mode and
* master code (if set) and program the VC I2C configuration
* register.
*
@@ -265,8 +265,8 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
if (initialized) {
if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
- pr_warn("%s: I2C config for all channels must match.",
- __func__);
+ pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+ __func__, voltdm->name, i2c_high_speed);
return;
}
@@ -292,9 +292,7 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
u32 val;
if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
- pr_err("%s: PMIC info requried to configure vc for"
- "vdd_%s not populated.Hence cannot initialize vc\n",
- __func__, voltdm->name);
+ pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
return;
}
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index 807391d84a9d..0df88820978d 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -41,6 +41,11 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
u32 val, sys_clk_rate, timeout, waittime;
u32 vddmin, vddmax, vstepmin, vstepmax;
+ if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
+ return;
+ }
+
if (!voltdm->read || !voltdm->write) {
pr_err("%s: No read/write API for accessing vdd_%s regs\n",
__func__, voltdm->name);
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 0e28bae20bd4..5dad38ec00ea 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -29,6 +29,7 @@
#include <mach/hardware.h>
#include <mach/orion5x.h>
#include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
#include <plat/time.h>
#include <plat/common.h>
#include <plat/addr-map.h>
@@ -72,7 +73,8 @@ void __init orion5x_map_io(void)
****************************************************************************/
void __init orion5x_ehci0_init(void)
{
- orion_ehci_init(ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL);
+ orion_ehci_init(ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL,
+ EHCI_PHY_ORION);
}
diff --git a/arch/arm/mach-s3c2410/cpu-freq.c b/arch/arm/mach-s3c2410/cpu-freq.c
index 7dc6c46b5e2b..5404535da1a5 100644
--- a/arch/arm/mach-s3c2410/cpu-freq.c
+++ b/arch/arm/mach-s3c2410/cpu-freq.c
@@ -115,7 +115,8 @@ static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
};
-static int s3c2410_cpufreq_add(struct device *dev)
+static int s3c2410_cpufreq_add(struct device *dev,
+ struct subsys_interface *sif)
{
return s3c_cpufreq_register(&s3c2410_cpufreq_info);
}
@@ -133,7 +134,8 @@ static int __init s3c2410_cpufreq_init(void)
arch_initcall(s3c2410_cpufreq_init);
-static int s3c2410a_cpufreq_add(struct device *dev)
+static int s3c2410a_cpufreq_add(struct device *dev,
+ struct subsys_interface *sif)
{
/* alter the maximum freq settings for S3C2410A. If a board knows
* it only has a maximum of 200, then it should register its own
@@ -144,7 +146,7 @@ static int s3c2410a_cpufreq_add(struct device *dev)
s3c2410_cpufreq_info.max.pclk = 66500000;
s3c2410_cpufreq_info.name = "s3c2410a";
- return s3c2410_cpufreq_add(dev);
+ return s3c2410_cpufreq_add(dev, sif);
}
static struct subsys_interface s3c2410a_cpufreq_interface = {
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 2afd00014a77..4803338cf56e 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -132,7 +132,8 @@ static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
},
};
-static int __init s3c2410_dma_add(struct device *dev)
+static int __init s3c2410_dma_add(struct device *dev,
+ struct subsys_interface *sif)
{
s3c2410_dma_init();
s3c24xx_dma_order_set(&s3c2410_dma_order);
@@ -148,7 +149,7 @@ static struct subsys_interface s3c2410_dma_interface = {
static int __init s3c2410_dma_drvinit(void)
{
- return subsys_interface_register(&s3c2410_interface);
+ return subsys_interface_register(&s3c2410_dma_interface);
}
arch_initcall(s3c2410_dma_drvinit);
diff --git a/arch/arm/mach-s3c2410/pll.c b/arch/arm/mach-s3c2410/pll.c
index c07438bfc99f..e0b3b347da82 100644
--- a/arch/arm/mach-s3c2410/pll.c
+++ b/arch/arm/mach-s3c2410/pll.c
@@ -66,7 +66,7 @@ static struct cpufreq_frequency_table pll_vals_12MHz[] = {
{ .frequency = 270000000, .index = PLLVAL(127, 1, 1), },
};
-static int s3c2410_plls_add(struct device *dev)
+static int s3c2410_plls_add(struct device *dev, struct subsys_interface *sif)
{
return s3c_plltab_register(pll_vals_12MHz, ARRAY_SIZE(pll_vals_12MHz));
}
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index fda5385deff6..03f706dd6009 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -111,7 +111,7 @@ struct syscore_ops s3c2410_pm_syscore_ops = {
.resume = s3c2410_pm_resume,
};
-static int s3c2410_pm_add(struct device *dev)
+static int s3c2410_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = s3c2410_pm_prepare;
pm_cpu_sleep = s3c2410_cpu_suspend;
diff --git a/arch/arm/mach-s3c2412/cpu-freq.c b/arch/arm/mach-s3c2412/cpu-freq.c
index d8664b7652ce..125be7d5fa60 100644
--- a/arch/arm/mach-s3c2412/cpu-freq.c
+++ b/arch/arm/mach-s3c2412/cpu-freq.c
@@ -194,7 +194,8 @@ static struct s3c_cpufreq_info s3c2412_cpufreq_info = {
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
};
-static int s3c2412_cpufreq_add(struct device *dev)
+static int s3c2412_cpufreq_add(struct device *dev,
+ struct subsys_interface *sif)
{
unsigned long fclk_rate;
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 142acd3b5e15..38472ac920ff 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -159,7 +159,8 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
.map_size = ARRAY_SIZE(s3c2412_dma_mappings),
};
-static int __init s3c2412_dma_add(struct device *dev)
+static int __init s3c2412_dma_add(struct device *dev,
+ struct subsys_interface *sif)
{
s3c2410_dma_init();
return s3c24xx_dma_init_map(&s3c2412_dma_sel);
diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c
index a8a46c1644f4..e65619ddbccc 100644
--- a/arch/arm/mach-s3c2412/irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -170,7 +170,7 @@ static int s3c2412_irq_rtc_wake(struct irq_data *data, unsigned int state)
static struct irq_chip s3c2412_irq_rtc_chip;
-static int s3c2412_irq_add(struct device *dev)
+static int s3c2412_irq_add(struct device *dev, struct subsys_interface *sif)
{
unsigned int irqno;
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index d1adfa65f66d..d04588506ec4 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -56,7 +56,7 @@ static void s3c2412_pm_prepare(void)
{
}
-static int s3c2412_pm_add(struct device *dev)
+static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = s3c2412_pm_prepare;
pm_cpu_sleep = s3c2412_cpu_suspend;
diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c
index 36df761061de..fd49f35e448e 100644
--- a/arch/arm/mach-s3c2416/irq.c
+++ b/arch/arm/mach-s3c2416/irq.c
@@ -213,7 +213,8 @@ static int __init s3c2416_add_sub(unsigned int base,
return 0;
}
-static int __init s3c2416_irq_add(struct device *dev)
+static int __init s3c2416_irq_add(struct device *dev,
+ struct subsys_interface *sif)
{
printk(KERN_INFO "S3C2416: IRQ Support\n");
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
index 3bdb15a0d419..1bd4817b8eb8 100644
--- a/arch/arm/mach-s3c2416/pm.c
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -48,7 +48,7 @@ static void s3c2416_pm_prepare(void)
__raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1);
}
-static int s3c2416_pm_add(struct device *dev)
+static int s3c2416_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = s3c2416_pm_prepare;
pm_cpu_sleep = s3c2416_cpu_suspend;
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index bedbc87a3426..414364eb426c 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -149,7 +149,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
};
-static int s3c2440_clk_add(struct device *dev)
+static int s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
{
struct clk *clock_upll;
struct clk *clock_h;
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index 15b1ddf8f626..5f0a0c8ef84f 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -174,7 +174,8 @@ static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
},
};
-static int __init s3c2440_dma_add(struct device *dev)
+static int __init s3c2440_dma_add(struct device *dev,
+ struct subsys_interface *sif)
{
s3c2410_dma_init();
s3c24xx_dma_order_set(&s3c2440_dma_order);
diff --git a/arch/arm/mach-s3c2440/irq.c b/arch/arm/mach-s3c2440/irq.c
index 4fee9bc6bcb5..4a18cde439cc 100644
--- a/arch/arm/mach-s3c2440/irq.c
+++ b/arch/arm/mach-s3c2440/irq.c
@@ -92,7 +92,7 @@ static struct irq_chip s3c_irq_wdtac97 = {
.irq_ack = s3c_irq_wdtac97_ack,
};
-static int s3c2440_irq_add(struct device *dev)
+static int s3c2440_irq_add(struct device *dev, struct subsys_interface *sif)
{
unsigned int irqno;
diff --git a/arch/arm/mach-s3c2440/s3c2440-cpufreq.c b/arch/arm/mach-s3c2440/s3c2440-cpufreq.c
index cf7596694efe..61776764d9f4 100644
--- a/arch/arm/mach-s3c2440/s3c2440-cpufreq.c
+++ b/arch/arm/mach-s3c2440/s3c2440-cpufreq.c
@@ -270,7 +270,8 @@ struct s3c_cpufreq_info s3c2440_cpufreq_info = {
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
};
-static int s3c2440_cpufreq_add(struct device *dev)
+static int s3c2440_cpufreq_add(struct device *dev,
+ struct subsys_interface *sif)
{
xtal = s3c_cpufreq_clk_get(NULL, "xtal");
hclk = s3c_cpufreq_clk_get(NULL, "hclk");
diff --git a/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c b/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
index b5368ae8d7fe..551fb433be87 100644
--- a/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
+++ b/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
@@ -51,7 +51,7 @@ static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
{ .frequency = 400000000, .index = PLLVAL(0x5c, 1, 1), }, /* FVco 800.000000 */
};
-static int s3c2440_plls12_add(struct device *dev)
+static int s3c2440_plls12_add(struct device *dev, struct subsys_interface *sif)
{
struct clk *xtal_clk;
unsigned long xtal;
diff --git a/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c b/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
index 42f2b5cd2399..3f15bcf64290 100644
--- a/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
+++ b/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
@@ -79,7 +79,8 @@ static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
{ .frequency = 402192000, .index = PLLVAL(87, 2, 1), }, /* FVco 804.384000 */
};
-static int s3c2440_plls169344_add(struct device *dev)
+static int s3c2440_plls169344_add(struct device *dev,
+ struct subsys_interface *sif)
{
struct clk *xtal_clk;
unsigned long xtal;
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
index 8004e0497bf4..22cb7c94a8c8 100644
--- a/arch/arm/mach-s3c2440/s3c2442.c
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -122,7 +122,7 @@ static struct clk s3c2442_clk_cam_upll = {
},
};
-static int s3c2442_clk_add(struct device *dev)
+static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif)
{
struct clk *clock_upll;
struct clk *clock_h;
diff --git a/arch/arm/mach-s3c2440/s3c244x-clock.c b/arch/arm/mach-s3c2440/s3c244x-clock.c
index b3fdbdda3d5f..6d9b688c442b 100644
--- a/arch/arm/mach-s3c2440/s3c244x-clock.c
+++ b/arch/arm/mach-s3c2440/s3c244x-clock.c
@@ -72,7 +72,7 @@ static struct clk clk_arm = {
},
};
-static int s3c244x_clk_add(struct device *dev)
+static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif)
{
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
unsigned long clkdivn;
diff --git a/arch/arm/mach-s3c2440/s3c244x-irq.c b/arch/arm/mach-s3c2440/s3c244x-irq.c
index 74d3dcf46a48..5fe8e58d3afd 100644
--- a/arch/arm/mach-s3c2440/s3c244x-irq.c
+++ b/arch/arm/mach-s3c2440/s3c244x-irq.c
@@ -91,7 +91,7 @@ static struct irq_chip s3c_irq_cam = {
.irq_ack = s3c_irq_cam_ack,
};
-static int s3c244x_irq_add(struct device *dev)
+static int s3c244x_irq_add(struct device *dev, struct subsys_interface *sif)
{
unsigned int irqno;
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index de6b4a23c9ed..14224517e621 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -135,7 +135,8 @@ static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
.map_size = ARRAY_SIZE(s3c2443_dma_mappings),
};
-static int __init s3c2443_dma_add(struct device *dev)
+static int __init s3c2443_dma_add(struct device *dev,
+ struct subsys_interface *sif)
{
s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
return s3c24xx_dma_init_map(&s3c2443_dma_sel);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
index 35e4ff24fb43..ac2829f56d12 100644
--- a/arch/arm/mach-s3c2443/irq.c
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -241,7 +241,8 @@ static int __init s3c2443_add_sub(unsigned int base,
return 0;
}
-static int __init s3c2443_irq_add(struct device *dev)
+static int __init s3c2443_irq_add(struct device *dev,
+ struct subsys_interface *sif)
{
printk("S3C2443: IRQ Support\n");
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 31bb27dc4aeb..aebbcc291b4e 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -138,6 +138,11 @@ static struct clk init_clocks_off[] = {
.ctrlbit = S3C_CLKCON_PCLK_TSADC,
}, {
.name = "i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+ .devname = "s3c2440-i2c.0",
+#else
+ .devname = "s3c2440-i2c",
+#endif
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_IIC,
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 4a7394d4bd9e..bee7dcd4df7c 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -49,7 +49,7 @@
/* uart registration process */
-void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
}
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index cd3c97e2ee75..32a30f38ba0c 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -102,6 +102,7 @@ static struct wm8962_pdata wm8962_pdata __initdata = {
0x8000 | WM8962_GPIO_FN_DMICDAT,
WM8962_GPIO_FN_IRQ, /* Open drain mode */
},
+ .in4_dc_measure = true,
};
static struct wm9081_pdata wm9081_pdata __initdata = {
diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c
index 23f9b22439c9..9cba18bfe47b 100644
--- a/arch/arm/mach-s5p64x0/pm.c
+++ b/arch/arm/mach-s5p64x0/pm.c
@@ -160,7 +160,7 @@ static void s5p64x0_pm_prepare(void)
}
-static int s5p64x0_pm_add(struct device *dev)
+static int s5p64x0_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = s5p64x0_pm_prepare;
pm_cpu_sleep = s5p64x0_cpu_suspend;
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index c78dfddd77fd..b9ec0c35379f 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -175,7 +175,7 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
}
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+static int s5pv210_clk_hdmiphy_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
}
@@ -372,7 +372,7 @@ static struct clk init_clocks_off[] = {
}, {
.name = "hdmiphy",
.devname = "s5pv210-hdmi",
- .enable = exynos4_clk_hdmiphy_ctrl,
+ .enable = s5pv210_clk_hdmiphy_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "dacphy",
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 677c71c41e50..736bfb103cbc 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -133,7 +133,7 @@ static void s5pv210_pm_prepare(void)
s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
}
-static int s5pv210_pm_add(struct device *dev)
+static int s5pv210_pm_add(struct device *dev, struct subsys_interface *sif)
{
pm_cpu_prep = s5pv210_pm_prepare;
pm_cpu_sleep = s5pv210_cpu_suspend;
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index aab0a349f759..2ac08b29e278 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -745,26 +745,18 @@ fsi_set_rate_end:
return ret;
}
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
-{
- int ret;
-
- if (is_porta)
- ret = fsi_ak4642_set_rate(dev, rate, enable);
- else
- ret = fsi_hdmi_set_rate(dev, rate, enable);
-
- return ret;
-}
-
static struct sh_fsi_platform_info fsi_info = {
- .porta_flags = SH_FSI_BRS_INV,
-
- .portb_flags = SH_FSI_BRS_INV |
- SH_FSI_BRM_INV |
- SH_FSI_LRS_INV |
- SH_FSI_FMT_SPDIF,
- .set_rate = fsi_set_rate,
+ .port_a = {
+ .flags = SH_FSI_BRS_INV,
+ .set_rate = fsi_ak4642_set_rate,
+ },
+ .port_b = {
+ .flags = SH_FSI_BRS_INV |
+ SH_FSI_BRM_INV |
+ SH_FSI_LRS_INV |
+ SH_FSI_FMT_SPDIF,
+ .set_rate = fsi_hdmi_set_rate,
+ },
};
static struct resource fsi_resources[] = {
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 9b42fbd10f8e..28d6d1f9dad4 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -901,7 +901,7 @@ static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
return clk_enable(clk);
}
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
+static int fsi_b_set_rate(struct device *dev, int rate, int enable)
{
struct clk *fsib_clk;
struct clk *fdiv_clk = &sh7372_fsidivb_clk;
@@ -910,10 +910,6 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
int ackmd_bpfmd;
int ret;
- /* FSIA is slave mode. nothing to do here */
- if (is_porta)
- return 0;
-
/* clock start */
switch (rate) {
case 44100:
@@ -957,14 +953,16 @@ fsi_set_rate_end:
}
static struct sh_fsi_platform_info fsi_info = {
- .porta_flags = SH_FSI_BRS_INV,
-
- .portb_flags = SH_FSI_BRS_INV |
+ .port_a = {
+ .flags = SH_FSI_BRS_INV,
+ },
+ .port_b = {
+ .flags = SH_FSI_BRS_INV |
SH_FSI_BRM_INV |
SH_FSI_LRS_INV |
SH_FSI_FMT_SPDIF,
-
- .set_rate = fsi_set_rate,
+ .set_rate = fsi_b_set_rate,
+ }
};
static struct resource fsi_resources[] = {
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 6fcf304d3cdf..a83cf51fc099 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -662,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = {
.dmaor_is_32bit = 1,
.needs_tend_set = 1,
.no_dmars = 1,
+ .slave_only = 1,
};
static struct resource sh7372_usb_dmae0_resources[] = {
@@ -723,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = {
.dmaor_is_32bit = 1,
.needs_tend_set = 1,
.no_dmars = 1,
+ .slave_only = 1,
};
static struct resource sh7372_usb_dmae1_resources[] = {
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index fcf4f377b1dc..330afdfa2475 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -60,9 +60,9 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.uartclk = 216000000,
}, {
/* serial port on mini-pcie */
- .membase = IO_ADDRESS(TEGRA_UARTD_BASE),
- .mapbase = TEGRA_UARTD_BASE,
- .irq = INT_UARTD,
+ .membase = IO_ADDRESS(TEGRA_UARTC_BASE),
+ .mapbase = TEGRA_UARTC_BASE,
+ .irq = INT_UARTC,
.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
.type = PORT_TEGRA,
.iotype = UPIO_MEM,
@@ -174,7 +174,7 @@ static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
/* name parent rate enabled */
{ "uarta", "pll_p", 216000000, true },
- { "uartd", "pll_p", 216000000, true },
+ { "uartc", "pll_p", 216000000, true },
{ "pll_p_out4", "pll_p", 24000000, true },
{ "usbd", "clk_m", 12000000, false },
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index ffa83f580db6..3c9f8da37ea3 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -22,7 +22,7 @@
/* SDCARD */
#define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5
#define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3
+#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PV1
/* ULPI */
#define TEGRA_ULPI_RST TEGRA_GPIO_PV0
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
index d0132e8031a1..3c9339058bec 100644
--- a/arch/arm/mach-tegra/include/mach/dma.h
+++ b/arch/arm/mach-tegra/include/mach/dma.h
@@ -23,11 +23,6 @@
#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
@@ -56,6 +51,11 @@ struct tegra_dma_channel;
#define TEGRA_DMA_REQ_SEL_OWR 25
#define TEGRA_DMA_REQ_SEL_INVALID 31
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+
+struct tegra_dma_req;
+struct tegra_dma_channel;
+
enum tegra_dma_mode {
TEGRA_DMA_SHARED = 1,
TEGRA_DMA_MODE_CONTINOUS = 2,
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 07c4bc8ea0a4..7a24d39661f0 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -54,9 +54,15 @@ loop1:
and r1, r1, #7 @ mask of the bits for current cache only
cmp r1, #2 @ see what cache we have at this level
blt skip @ skip if no cache, or just i-cache
+#ifdef CONFIG_PREEMPT
+ save_and_disable_irqs r9 @ make cssr&csidr read atomic
+#endif
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
isb @ isb to sych the new cssr&csidr
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+#ifdef CONFIG_PREEMPT
+ restore_irqs_notrace r9
+#endif
and r2, r1, #7 @ extract the length of the cache lines
add r2, r2, #4 @ add 4 (line length offset)
ldr r4, =0x3ff
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index ba159370fa5f..80632e8d7538 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -225,8 +225,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
continue;
if (__phys_to_pfn(area->phys_addr) > pfn ||
- __pfn_to_phys(pfn) + offset + size-1 >
- area->phys_addr + area->size-1)
+ __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
continue;
/* we can drop the lock here as we know *area is static */
read_unlock(&vmlist_lock);
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index dcebb1230f7f..c722f9ce6918 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -88,12 +88,6 @@ config IMX_HAVE_IOMUX_V1
config ARCH_MXC_IOMUX_V3
bool
-config ARCH_MXC_AUDMUX_V1
- bool
-
-config ARCH_MXC_AUDMUX_V2
- bool
-
config IRAM_ALLOC
bool
select GENERIC_ALLOCATOR
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 076db84f3e31..e81290c27c65 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
obj-$(CONFIG_MXC_PWM) += pwm.o
obj-$(CONFIG_MXC_ULPI) += ulpi.o
obj-$(CONFIG_MXC_USE_EPIT) += epit.o
-obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
-obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/plat-mxc/audmux-v1.c b/arch/arm/plat-mxc/audmux-v1.c
deleted file mode 100644
index 1180bef7664b..000000000000
--- a/arch/arm/plat-mxc/audmux-v1.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
- *
- * Initial development of this code was funded by
- * Phytec Messtechnik GmbH, http://www.phytec.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.
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <mach/audmux.h>
-#include <mach/hardware.h>
-
-static void __iomem *audmux_base;
-
-static unsigned char port_mapping[] = {
- 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
-};
-
-int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
-{
- if (!audmux_base) {
- printk("%s: not configured\n", __func__);
- return -ENOSYS;
- }
-
- if (port >= ARRAY_SIZE(port_mapping))
- return -EINVAL;
-
- writel(pcr, audmux_base + port_mapping[port]);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port);
-
-static int mxc_audmux_v1_init(void)
-{
-#ifdef CONFIG_MACH_MX21
- if (cpu_is_mx21())
- audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR);
- else
-#endif
-#ifdef CONFIG_MACH_MX27
- if (cpu_is_mx27())
- audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR);
- else
-#endif
- (void)0;
-
- return 0;
-}
-
-postcore_initcall(mxc_audmux_v1_init);
diff --git a/arch/arm/plat-mxc/include/mach/audmux.h b/arch/arm/plat-mxc/include/mach/audmux.h
deleted file mode 100644
index 6fda788ed0e9..000000000000
--- a/arch/arm/plat-mxc/include/mach/audmux.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __MACH_AUDMUX_H
-#define __MACH_AUDMUX_H
-
-#define MX27_AUDMUX_HPCR1_SSI0 0
-#define MX27_AUDMUX_HPCR2_SSI1 1
-#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
-#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
-#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
-#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
-
-#define MX31_AUDMUX_PORT1_SSI0 0
-#define MX31_AUDMUX_PORT2_SSI1 1
-#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
-#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
-#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
-#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
-
-#define MX51_AUDMUX_PORT1_SSI0 0
-#define MX51_AUDMUX_PORT2_SSI1 1
-#define MX51_AUDMUX_PORT3 2
-#define MX51_AUDMUX_PORT4 3
-#define MX51_AUDMUX_PORT5 4
-#define MX51_AUDMUX_PORT6 5
-#define MX51_AUDMUX_PORT7 6
-
-/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
-#define MXC_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
-#define MXC_AUDMUX_V1_PCR_INMEN (1 << 8)
-#define MXC_AUDMUX_V1_PCR_TXRXEN (1 << 10)
-#define MXC_AUDMUX_V1_PCR_SYN (1 << 12)
-#define MXC_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
-#define MXC_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
-#define MXC_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
-#define MXC_AUDMUX_V1_PCR_RFSDIR (1 << 25)
-#define MXC_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
-#define MXC_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
-#define MXC_AUDMUX_V1_PCR_TFSDIR (1 << 31)
-
-/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
-#define MXC_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
-#define MXC_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
-#define MXC_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
-#define MXC_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
-#define MXC_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
-#define MXC_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
-#define MXC_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
-#define MXC_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
-#define MXC_AUDMUX_V2_PTCR_SYN (1 << 11)
-
-#define MXC_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
-#define MXC_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
-#define MXC_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
-#define MXC_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
-
-int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
-
-int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
- unsigned int pdcr);
-
-#endif /* __MACH_AUDMUX_H */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index aa59f4247dc5..8f81503a4df7 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -110,14 +110,6 @@ config OMAP_MUX_WARNINGS
to change the pin multiplexing setup. When there are no warnings
printed, it's safe to deselect OMAP_MUX for your product.
-config OMAP_MCBSP
- bool "McBSP support"
- depends on ARCH_OMAP
- default y
- help
- Say Y here if you want support for the OMAP Multichannel
- Buffered Serial Port.
-
config OMAP_MBOX_FWK
tristate "Mailbox framework support"
depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9a584614e7e6..c0fe2757b695 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -17,8 +17,6 @@ obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
-
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 8fa74e2c9d6e..18814127809a 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -27,271 +27,10 @@
#include <linux/spinlock.h>
#include <linux/clk.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 = port_nr - 1, \
-}
-
#define MCBSP_CONFIG_TYPE2 0x2
#define MCBSP_CONFIG_TYPE3 0x3
#define MCBSP_CONFIG_TYPE4 0x4
-/* McBSP register numbers. Register address offset = num * reg_step */
-enum {
- /* Common registers */
- OMAP_MCBSP_REG_SPCR2 = 4,
- OMAP_MCBSP_REG_SPCR1,
- OMAP_MCBSP_REG_RCR2,
- OMAP_MCBSP_REG_RCR1,
- OMAP_MCBSP_REG_XCR2,
- OMAP_MCBSP_REG_XCR1,
- OMAP_MCBSP_REG_SRGR2,
- OMAP_MCBSP_REG_SRGR1,
- OMAP_MCBSP_REG_MCR2,
- OMAP_MCBSP_REG_MCR1,
- OMAP_MCBSP_REG_RCERA,
- OMAP_MCBSP_REG_RCERB,
- OMAP_MCBSP_REG_XCERA,
- OMAP_MCBSP_REG_XCERB,
- OMAP_MCBSP_REG_PCR0,
- OMAP_MCBSP_REG_RCERC,
- OMAP_MCBSP_REG_RCERD,
- OMAP_MCBSP_REG_XCERC,
- OMAP_MCBSP_REG_XCERD,
- OMAP_MCBSP_REG_RCERE,
- OMAP_MCBSP_REG_RCERF,
- OMAP_MCBSP_REG_XCERE,
- OMAP_MCBSP_REG_XCERF,
- OMAP_MCBSP_REG_RCERG,
- OMAP_MCBSP_REG_RCERH,
- OMAP_MCBSP_REG_XCERG,
- OMAP_MCBSP_REG_XCERH,
-
- /* OMAP1-OMAP2420 registers */
- OMAP_MCBSP_REG_DRR2 = 0,
- OMAP_MCBSP_REG_DRR1,
- OMAP_MCBSP_REG_DXR2,
- OMAP_MCBSP_REG_DXR1,
-
- /* OMAP2430 and onwards */
- OMAP_MCBSP_REG_DRR = 0,
- OMAP_MCBSP_REG_DXR = 2,
- OMAP_MCBSP_REG_SYSCON = 35,
- OMAP_MCBSP_REG_THRSH2,
- OMAP_MCBSP_REG_THRSH1,
- OMAP_MCBSP_REG_IRQST = 40,
- OMAP_MCBSP_REG_IRQEN,
- OMAP_MCBSP_REG_WAKEUPEN,
- OMAP_MCBSP_REG_XCCR,
- OMAP_MCBSP_REG_RCCR,
- OMAP_MCBSP_REG_XBUFFSTAT,
- OMAP_MCBSP_REG_RBUFFSTAT,
- OMAP_MCBSP_REG_SSELCR,
-};
-
-/* OMAP3 sidetone control registers */
-#define OMAP_ST_REG_REV 0x00
-#define OMAP_ST_REG_SYSCONFIG 0x10
-#define OMAP_ST_REG_IRQSTATUS 0x18
-#define OMAP_ST_REG_IRQENABLE 0x1C
-#define OMAP_ST_REG_SGAINCR 0x24
-#define OMAP_ST_REG_SFIRCR 0x28
-#define OMAP_ST_REG_SSELCR 0x2C
-
-/************************** McBSP SPCR1 bit definitions ***********************/
-#define RRST 0x0001
-#define RRDY 0x0002
-#define RFULL 0x0004
-#define RSYNC_ERR 0x0008
-#define RINTM(value) ((value)<<4) /* bits 4:5 */
-#define ABIS 0x0040
-#define DXENA 0x0080
-#define CLKSTP(value) ((value)<<11) /* bits 11:12 */
-#define RJUST(value) ((value)<<13) /* bits 13:14 */
-#define ALB 0x8000
-#define DLB 0x8000
-
-/************************** McBSP SPCR2 bit definitions ***********************/
-#define XRST 0x0001
-#define XRDY 0x0002
-#define XEMPTY 0x0004
-#define XSYNC_ERR 0x0008
-#define XINTM(value) ((value)<<4) /* bits 4:5 */
-#define GRST 0x0040
-#define FRST 0x0080
-#define SOFT 0x0100
-#define FREE 0x0200
-
-/************************** McBSP PCR bit definitions *************************/
-#define CLKRP 0x0001
-#define CLKXP 0x0002
-#define FSRP 0x0004
-#define FSXP 0x0008
-#define DR_STAT 0x0010
-#define DX_STAT 0x0020
-#define CLKS_STAT 0x0040
-#define SCLKME 0x0080
-#define CLKRM 0x0100
-#define CLKXM 0x0200
-#define FSRM 0x0400
-#define FSXM 0x0800
-#define RIOEN 0x1000
-#define XIOEN 0x2000
-#define IDLE_EN 0x4000
-
-/************************** McBSP RCR1 bit definitions ************************/
-#define RWDLEN1(value) ((value)<<5) /* Bits 5:7 */
-#define RFRLEN1(value) ((value)<<8) /* Bits 8:14 */
-
-/************************** McBSP XCR1 bit definitions ************************/
-#define XWDLEN1(value) ((value)<<5) /* Bits 5:7 */
-#define XFRLEN1(value) ((value)<<8) /* Bits 8:14 */
-
-/*************************** McBSP RCR2 bit definitions ***********************/
-#define RDATDLY(value) (value) /* Bits 0:1 */
-#define RFIG 0x0004
-#define RCOMPAND(value) ((value)<<3) /* Bits 3:4 */
-#define RWDLEN2(value) ((value)<<5) /* Bits 5:7 */
-#define RFRLEN2(value) ((value)<<8) /* Bits 8:14 */
-#define RPHASE 0x8000
-
-/*************************** McBSP XCR2 bit definitions ***********************/
-#define XDATDLY(value) (value) /* Bits 0:1 */
-#define XFIG 0x0004
-#define XCOMPAND(value) ((value)<<3) /* Bits 3:4 */
-#define XWDLEN2(value) ((value)<<5) /* Bits 5:7 */
-#define XFRLEN2(value) ((value)<<8) /* Bits 8:14 */
-#define XPHASE 0x8000
-
-/************************* McBSP SRGR1 bit definitions ************************/
-#define CLKGDV(value) (value) /* Bits 0:7 */
-#define FWID(value) ((value)<<8) /* Bits 8:15 */
-
-/************************* McBSP SRGR2 bit definitions ************************/
-#define FPER(value) (value) /* Bits 0:11 */
-#define FSGM 0x1000
-#define CLKSM 0x2000
-#define CLKSP 0x4000
-#define GSYNC 0x8000
-
-/************************* McBSP MCR1 bit definitions *************************/
-#define RMCM 0x0001
-#define RCBLK(value) ((value)<<2) /* Bits 2:4 */
-#define RPABLK(value) ((value)<<5) /* Bits 5:6 */
-#define RPBBLK(value) ((value)<<7) /* Bits 7:8 */
-
-/************************* McBSP MCR2 bit definitions *************************/
-#define XMCM(value) (value) /* Bits 0:1 */
-#define XCBLK(value) ((value)<<2) /* Bits 2:4 */
-#define XPABLK(value) ((value)<<5) /* Bits 5:6 */
-#define XPBBLK(value) ((value)<<7) /* Bits 7:8 */
-
-/*********************** McBSP XCCR bit definitions *************************/
-#define EXTCLKGATE 0x8000
-#define PPCONNECT 0x4000
-#define DXENDLY(value) ((value)<<12) /* Bits 12:13 */
-#define XFULL_CYCLE 0x0800
-#define DILB 0x0020
-#define XDMAEN 0x0008
-#define XDISABLE 0x0001
-
-/********************** McBSP RCCR bit definitions *************************/
-#define RFULL_CYCLE 0x0800
-#define RDMAEN 0x0008
-#define RDISABLE 0x0001
-
-/********************** McBSP SYSCONFIG bit definitions ********************/
-#define CLOCKACTIVITY(value) ((value)<<8)
-#define SIDLEMODE(value) ((value)<<3)
-#define ENAWAKEUP 0x0004
-#define SOFTRST 0x0002
-
-/********************** McBSP SSELCR bit definitions ***********************/
-#define SIDETONEEN 0x0400
-
-/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
-#define ST_AUTOIDLE 0x0001
-
-/********************** McBSP Sidetone SGAINCR bit definitions *************/
-#define ST_CH1GAIN(value) ((value<<16)) /* Bits 16:31 */
-#define ST_CH0GAIN(value) (value) /* Bits 0:15 */
-
-/********************** McBSP Sidetone SFIRCR bit definitions **************/
-#define ST_FIRCOEFF(value) (value) /* Bits 0:15 */
-
-/********************** McBSP Sidetone SSELCR bit definitions **************/
-#define ST_COEFFWRDONE 0x0004
-#define ST_COEFFWREN 0x0002
-#define ST_SIDETONEEN 0x0001
-
-/********************** McBSP DMA operating modes **************************/
-#define MCBSP_DMA_MODE_ELEMENT 0
-#define MCBSP_DMA_MODE_THRESHOLD 1
-#define MCBSP_DMA_MODE_FRAME 2
-
-/********************** McBSP WAKEUPEN bit definitions *********************/
-#define XEMPTYEOFEN 0x4000
-#define XRDYEN 0x0400
-#define XEOFEN 0x0200
-#define XFSXEN 0x0100
-#define XSYNCERREN 0x0080
-#define RRDYEN 0x0008
-#define REOFEN 0x0004
-#define RFSREN 0x0002
-#define RSYNCERREN 0x0001
-
-/* 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;
- u16 spcr1;
- u16 rcr2;
- u16 rcr1;
- u16 xcr2;
- u16 xcr1;
- u16 srgr2;
- u16 srgr1;
- u16 mcr2;
- u16 mcr1;
- u16 pcr0;
- u16 rcerc;
- u16 rcerd;
- u16 xcerc;
- u16 xcerd;
- u16 rcere;
- u16 rcerf;
- u16 xcere;
- u16 xcerf;
- u16 rcerg;
- u16 rcerh;
- u16 xcerg;
- u16 xcerh;
- u16 xccr;
- u16 rccr;
-};
-
-typedef enum {
- OMAP_MCBSP_WORD_8 = 0,
- OMAP_MCBSP_WORD_12,
- OMAP_MCBSP_WORD_16,
- OMAP_MCBSP_WORD_20,
- OMAP_MCBSP_WORD_24,
- OMAP_MCBSP_WORD_32,
-} omap_mcbsp_word_length;
-
/* Platform specific configuration */
struct omap_mcbsp_ops {
void (*request)(unsigned int);
@@ -312,43 +51,6 @@ struct omap_mcbsp_platform_data {
int (*mux_signal)(struct device *dev, const char *signal, const char *src);
};
-struct omap_mcbsp_st_data {
- void __iomem *io_base_st;
- bool running;
- bool enabled;
- s16 taps[128]; /* Sidetone filter coefficients */
- int nr_taps; /* Number of filter coefficients in use */
- s16 ch0gain;
- s16 ch1gain;
-};
-
-struct omap_mcbsp {
- struct device *dev;
- unsigned long phys_base;
- unsigned long phys_dma_base;
- void __iomem *io_base;
- u8 id;
- u8 free;
-
- int rx_irq;
- int tx_irq;
-
- /* DMA stuff */
- u8 dma_rx_sync;
- u8 dma_tx_sync;
-
- /* Protect the field .free, while checking if the mcbsp is in use */
- spinlock_t lock;
- struct omap_mcbsp_platform_data *pdata;
- struct clk *fclk;
- struct omap_mcbsp_st_data *st_data;
- int dma_op_mode;
- u16 max_tx_thres;
- u16 max_rx_thres;
- void *reg_cache;
- int reg_cache_size;
-};
-
/**
* omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
* @sidetone: name of the sidetone device
@@ -357,39 +59,4 @@ struct omap_mcbsp_dev_attr {
const char *sidetone;
};
-extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count;
-
-int omap_mcbsp_init(void);
-void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
-void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
-void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
-u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
-u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
-u16 omap_mcbsp_get_fifo_size(unsigned int id);
-u16 omap_mcbsp_get_tx_delay(unsigned int id);
-u16 omap_mcbsp_get_rx_delay(unsigned int id);
-int omap_mcbsp_get_dma_op_mode(unsigned int id);
-int omap_mcbsp_request(unsigned int id);
-void omap_mcbsp_free(unsigned int id);
-void omap_mcbsp_start(unsigned int id, int tx, int rx);
-void omap_mcbsp_stop(unsigned int id, int tx, int rx);
-
-/* McBSP functional clock source changing function */
-extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
-
-/* McBSP signal muxing API */
-void omap2_mcbsp1_mux_clkr_src(u8 mux);
-void omap2_mcbsp1_mux_fsr_src(u8 mux);
-
-int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
-int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
-
-/* Sidetone specific API */
-int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
-int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
-int omap_st_enable(unsigned int id);
-int omap_st_disable(unsigned int id);
-int omap_st_is_enabled(unsigned int id);
-
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap-secure.h b/arch/arm/plat-omap/include/plat/omap-secure.h
index 64f9d1c7f1bb..3047ff923a63 100644
--- a/arch/arm/plat-omap/include/plat/omap-secure.h
+++ b/arch/arm/plat-omap/include/plat/omap-secure.h
@@ -3,7 +3,7 @@
#include <linux/types.h>
-#ifdef CONFIG_ARCH_OMAP2PLUS
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
extern int omap_secure_ram_reserve_memblock(void);
#else
static inline void omap_secure_ram_reserve_memblock(void)
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index e5a2fde29b19..089899a7db72 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -789,10 +789,7 @@ void __init orion_xor1_init(unsigned long mapbase_low,
/*****************************************************************************
* EHCI
****************************************************************************/
-static struct orion_ehci_data orion_ehci_data = {
- .phy_version = EHCI_PHY_NA,
-};
-
+static struct orion_ehci_data orion_ehci_data;
static u64 ehci_dmamask = DMA_BIT_MASK(32);
@@ -812,8 +809,10 @@ static struct platform_device orion_ehci = {
};
void __init orion_ehci_init(unsigned long mapbase,
- unsigned long irq)
+ unsigned long irq,
+ enum orion_ehci_phy_ver phy_version)
{
+ orion_ehci_data.phy_version = phy_version;
fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
irq);
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index 0fe08d77e835..a7fa005a5a0e 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -89,7 +89,8 @@ void __init orion_xor1_init(unsigned long mapbase_low,
unsigned long irq_1);
void __init orion_ehci_init(unsigned long mapbase,
- unsigned long irq);
+ unsigned long irq,
+ enum orion_ehci_phy_ver phy_version);
void __init orion_ehci_1_init(unsigned long mapbase,
unsigned long irq);
diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c
index 91553432711d..3b1e17bd3d17 100644
--- a/arch/arm/plat-orion/mpp.c
+++ b/arch/arm/plat-orion/mpp.c
@@ -64,8 +64,7 @@ void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
gpio_mode |= GPIO_INPUT_OK;
if (*mpp_list & MPP_OUTPUT_MASK)
gpio_mode |= GPIO_OUTPUT_OK;
- if (sel != 0)
- gpio_mode = 0;
+
orion_gpio_set_valid(num, gpio_mode);
}
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 32a6e394db24..f10768e988d4 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -468,8 +468,10 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
{
struct s3c2410_platform_i2c *npd;
- if (!pd)
+ if (!pd) {
pd = &default_i2c_data;
+ pd->bus_num = 0;
+ }
npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
&s3c_device_i2c0);
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 197e96f70405..3dea7231f637 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -8,6 +8,7 @@ config AVR32
select HAVE_KPROBES
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_PROBE
+ select GENERIC_ATOMIC64
select HARDIRQS_SW_RESEND
select GENERIC_IRQ_SHOW
select ARCH_HAVE_NMI_SAFE_CMPXCHG
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index d4fc1a971779..604cd9dd1333 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -26,7 +26,6 @@
#include <linux/cache.h>
#include <linux/of_platform.h>
#include <linux/dma-mapping.h>
-#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/entry.h>
#include <asm/cpuinfo.h>
@@ -227,23 +226,5 @@ static int __init setup_bus_notifier(void)
return 0;
}
-arch_initcall(setup_bus_notifier);
-
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
-static int __init topology_init(void)
-{
- int i, ret;
-
- for_each_present_cpu(i) {
- struct cpu *c = &per_cpu(cpu_devices, i);
- ret = register_cpu(c, i);
- if (ret)
- printk(KERN_WARNING "topology_init: register_cpu %d "
- "failed (%d)\n", i, ret);
- }
-
- return 0;
-}
-subsys_initcall(topology_init);
+arch_initcall(setup_bus_notifier);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c4c1312473fb..5ab6e89603c5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2356,6 +2356,7 @@ config PCI
depends on HW_HAS_PCI
select PCI_DOMAINS
select GENERIC_PCI_IOMAP
+ select NO_GENERIC_PCI_IOPORT_MAP
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 639e3ce6c264..9a91fe9de696 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -418,6 +418,11 @@ static struct platform_device qi_lb60_charger_device = {
},
};
+/* audio */
+static struct platform_device qi_lb60_audio_device = {
+ .name = "qi-lb60-audio",
+ .id = -1,
+};
static struct platform_device *jz_platform_devices[] __initdata = {
&jz4740_udc_device,
@@ -434,6 +439,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
&qi_lb60_gpio_keys,
&qi_lb60_pwm_beeper,
&qi_lb60_charger_device,
+ &qi_lb60_audio_device,
};
static void __init board_gpio_setup(void)
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
index 2635b1a96333..fd35daa45314 100644
--- a/arch/mips/lib/iomap-pci.c
+++ b/arch/mips/lib/iomap-pci.c
@@ -10,8 +10,8 @@
#include <linux/module.h>
#include <asm/io.h>
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
- unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+ unsigned long port, unsigned int nr)
{
struct pci_controller *ctrl = dev->bus->sysdata;
unsigned long base = ctrl->io_map_base;
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 2156e077859b..1acf65026773 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -24,10 +24,6 @@ CONFIG_PPC_SPLPAR=y
CONFIG_SCANLOG=m
CONFIG_PPC_SMLPAR=y
CONFIG_DTL=y
-CONFIG_PPC_ISERIES=y
-CONFIG_VIODASD=y
-CONFIG_VIOCD=m
-CONFIG_VIOTAPE=m
CONFIG_PPC_MAPLE=y
CONFIG_PPC_PASEMI=y
CONFIG_PPC_PASEMI_IOMMU=y
@@ -259,7 +255,6 @@ CONFIG_PASEMI_MAC=y
CONFIG_MLX4_EN=m
CONFIG_QLGE=m
CONFIG_BE2NET=m
-CONFIG_ISERIES_VETH=m
CONFIG_PPP=m
CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 43268f15004e..6d422979ebaf 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -142,6 +142,11 @@ static inline const char *eeh_pci_name(struct pci_dev *pdev)
return pdev ? pci_name(pdev) : "<null>";
}
+static inline const char *eeh_driver_name(struct pci_dev *pdev)
+{
+ return (pdev && pdev->driver) ? pdev->driver->name : "<null>";
+}
+
#endif /* CONFIG_EEH */
#else /* CONFIG_PCI */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 78a205162fd7..84cc7840cd18 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -83,8 +83,18 @@ struct pt_regs {
#ifndef __ASSEMBLY__
-#define instruction_pointer(regs) ((regs)->nip)
-#define user_stack_pointer(regs) ((regs)->gpr[1])
+#define GET_IP(regs) ((regs)->nip)
+#define GET_USP(regs) ((regs)->gpr[1])
+#define GET_FP(regs) (0)
+#define SET_FP(regs, val)
+
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#define profile_pc profile_pc
+#endif
+
+#include <asm-generic/ptrace.h>
+
#define kernel_stack_pointer(regs) ((regs)->gpr[1])
static inline int is_syscall_success(struct pt_regs *regs)
{
@@ -99,12 +109,6 @@ static inline long regs_return_value(struct pt_regs *regs)
return -regs->gpr[3];
}
-#ifdef CONFIG_SMP
-extern unsigned long profile_pc(struct pt_regs *regs);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
-
#ifdef __powerpc64__
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#else
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index d4be7bb3dbdf..3844ca7c5099 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -775,7 +775,7 @@ program_check_common:
EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
- ENABLE_INTS
+ DISABLE_INTS
bl .program_check_exception
b .ret_from_except
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 701d4aceb4f4..01e2877e8e04 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -118,10 +118,14 @@ static inline notrace void set_soft_enabled(unsigned long enable)
static inline notrace void decrementer_check_overflow(void)
{
u64 now = get_tb_or_rtc();
- u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
+ u64 *next_tb;
+
+ preempt_disable();
+ next_tb = &__get_cpu_var(decrementers_next_tb);
if (now >= *next_tb)
set_dec(1);
+ preempt_enable();
}
notrace void arch_local_irq_restore(unsigned long en)
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 10a140f82cb8..64483fde95c6 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -865,6 +865,7 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
{
unsigned long flags;
s64 left;
+ unsigned long val;
if (!event->hw.idx || !event->hw.sample_period)
return;
@@ -880,7 +881,12 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
event->hw.state = 0;
left = local64_read(&event->hw.period_left);
- write_pmc(event->hw.idx, left);
+
+ val = 0;
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+
+ write_pmc(event->hw.idx, val);
perf_event_update_userpage(event);
perf_pmu_enable(event->pmu);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index ebe5766781aa..d817ab018486 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -566,12 +566,12 @@ static void show_instructions(struct pt_regs *regs)
*/
if (!__kernel_text_address(pc) ||
__get_user(instr, (unsigned int __user *)pc)) {
- printk("XXXXXXXX ");
+ printk(KERN_CONT "XXXXXXXX ");
} else {
if (regs->nip == pc)
- printk("<%08x> ", instr);
+ printk(KERN_CONT "<%08x> ", instr);
else
- printk("%08x ", instr);
+ printk(KERN_CONT "%08x ", instr);
}
pc += sizeof(int);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 517b1d8f455b..9f843cdfee9e 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -716,7 +716,6 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w
int cpu;
slb_set_size(SLB_MIN_SIZE);
- stop_topology_update();
printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id());
while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) &&
@@ -732,7 +731,6 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w
rc = atomic_read(&data->error);
atomic_set(&data->error, rc);
- start_topology_update();
pSeries_coalesce_init();
if (wake_when_done) {
@@ -846,6 +844,7 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
atomic_set(&data.error, 0);
data.token = rtas_token("ibm,suspend-me");
data.complete = &done;
+ stop_topology_update();
/* Call function on all CPUs. One of us will make the
* rtas call
@@ -858,6 +857,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
if (atomic_read(&data.error) != 0)
printk(KERN_ERR "Error doing global join\n");
+ start_topology_update();
+
return atomic_read(&data.error);
}
#else /* CONFIG_PPC_PSERIES */
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index a70bc1e385eb..f92b9ef7340e 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -52,32 +52,38 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
{
- unsigned int id;
+ unsigned long flags;
+ unsigned int id, rc;
+
+ spin_lock_irqsave(&phb->lock, flags);
- spin_lock(&phb->lock);
id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
if (id >= phb->msi_count && phb->msi_next)
id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
if (id >= phb->msi_count) {
- spin_unlock(&phb->lock);
- return 0;
+ rc = 0;
+ goto out;
}
__set_bit(id, phb->msi_map);
- spin_unlock(&phb->lock);
- return id + phb->msi_base;
+ rc = id + phb->msi_base;
+out:
+ spin_unlock_irqrestore(&phb->lock, flags);
+ return rc;
}
static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
{
+ unsigned long flags;
unsigned int id;
if (WARN_ON(hwirq < phb->msi_base ||
hwirq >= (phb->msi_base + phb->msi_count)))
return;
id = hwirq - phb->msi_base;
- spin_lock(&phb->lock);
+
+ spin_lock_irqsave(&phb->lock, flags);
__clear_bit(id, phb->msi_map);
- spin_unlock(&phb->lock);
+ spin_unlock_irqrestore(&phb->lock, flags);
}
static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 565869022e3d..c0b40af4ce4f 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -551,9 +551,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
printk (KERN_ERR "EEH: %d reads ignored for recovering device at "
"location=%s driver=%s pci addr=%s\n",
pdn->eeh_check_count, location,
- dev->driver->name, eeh_pci_name(dev));
+ eeh_driver_name(dev), eeh_pci_name(dev));
printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",
- dev->driver->name);
+ eeh_driver_name(dev));
dump_stack();
}
goto dn_unlock;
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
index b84a8b2238dd..47226e04126d 100644
--- a/arch/powerpc/platforms/pseries/suspend.c
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -24,6 +24,7 @@
#include <asm/machdep.h>
#include <asm/mmu.h>
#include <asm/rtas.h>
+#include <asm/topology.h>
static u64 stream_id;
static struct device suspend_dev;
@@ -138,8 +139,11 @@ static ssize_t store_hibernate(struct device *dev,
ssleep(1);
} while (rc == -EAGAIN);
- if (!rc)
+ if (!rc) {
+ stop_topology_update();
rc = pm_suspend(PM_SUSPEND_MEM);
+ start_topology_update();
+ }
stream_id = 0;
diff --git a/arch/powerpc/platforms/wsp/ics.c b/arch/powerpc/platforms/wsp/ics.c
index 576874392543..97fe82ee8633 100644
--- a/arch/powerpc/platforms/wsp/ics.c
+++ b/arch/powerpc/platforms/wsp/ics.c
@@ -346,7 +346,7 @@ static int wsp_chip_set_affinity(struct irq_data *d,
* For the moment only implement delivery to all cpus or one cpu.
* Get current irq_server for the given irq
*/
- ret = cache_hwirq_map(ics, d->irq, cpumask);
+ ret = cache_hwirq_map(ics, hw_irq, cpumask);
if (ret == -1) {
char cpulist[128];
cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c
index e0262cd0e2d3..d24b3acf858e 100644
--- a/arch/powerpc/platforms/wsp/wsp_pci.c
+++ b/arch/powerpc/platforms/wsp/wsp_pci.c
@@ -468,15 +468,15 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
#define DUMP_REG(x) \
pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
-#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
- /* WSP DD1 has a bogus class code by default in the PCI-E
- * root complex's built-in P2P bridge */
+ /*
+ * Some WSP variants has a bogus class code by default in the PCI-E
+ * root complex's built-in P2P bridge
+ */
val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
(val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
-#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
/* XXX Disable TCE caching, it doesn't work on DD1 */
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 30eb17ecad49..6073288fed29 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -385,26 +385,36 @@ static void __init setup_pci_cmd(struct pci_controller *hose)
void fsl_pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_controller *hose = pci_bus_to_host(bus);
- int i;
-
- if ((bus->parent == hose->bus) &&
- ((fsl_pcie_bus_fixup &&
- early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) ||
- (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)))
- {
- for (i = 0; i < 4; ++i) {
+ int i, is_pcie = 0, no_link;
+
+ /* The root complex bridge comes up with bogus resources,
+ * we copy the PHB ones in.
+ *
+ * With the current generic PCI code, the PHB bus no longer
+ * has bus->resource[0..4] set, so things are a bit more
+ * tricky.
+ */
+
+ if (fsl_pcie_bus_fixup)
+ is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+ no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK);
+
+ if (bus->parent == hose->bus && (is_pcie || no_link)) {
+ for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) {
struct resource *res = bus->resource[i];
- struct resource *par = bus->parent->resource[i];
- if (res) {
- res->start = 0;
- res->end = 0;
- res->flags = 0;
- }
- if (res && par) {
- res->start = par->start;
- res->end = par->end;
- res->flags = par->flags;
- }
+ struct resource *par;
+
+ if (!res)
+ continue;
+ if (i == 0)
+ par = &hose->io_resource;
+ else if (i < 4)
+ par = &hose->mem_resources[i-1];
+ else par = NULL;
+
+ res->start = par ? par->start : 0;
+ res->end = par ? par->end : 0;
+ res->flags = par ? par->flags : 0;
}
}
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3c8db65c89e5..713fb58ca507 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -859,6 +859,7 @@ config PCI
depends on SYS_SUPPORTS_PCI
select PCI_DOMAINS
select GENERIC_PCI_IOMAP
+ select NO_GENERIC_PCI_IOPORT_MAP
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 033ef2ba621f..1e146fcdb8a0 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -767,7 +767,9 @@ static struct platform_device camera_devices[] = {
/* FSI */
static struct sh_fsi_platform_info fsi_info = {
- .portb_flags = SH_FSI_BRS_INV,
+ .port_b = {
+ .flags = SH_FSI_BRS_INV,
+ },
};
static struct resource fsi_resources[] = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 036fe1adaef1..1fc5d47a5687 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -277,7 +277,9 @@ static struct platform_device ceu1_device = {
/* FSI */
/* change J20, J21, J22 pin to 1-2 connection to use slave mode */
static struct sh_fsi_platform_info fsi_info = {
- .porta_flags = SH_FSI_BRS_INV,
+ .port_a = {
+ .flags = SH_FSI_BRS_INV,
+ },
};
static struct resource fsi_resources[] = {
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 8f18dd090a66..1e7b0e2e764d 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -356,8 +356,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
#ifndef CONFIG_GENERIC_IOMAP
-static void __iomem *ioport_map_pci(struct pci_dev *dev,
- unsigned long port, unsigned int nr)
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+ unsigned long port, unsigned int nr)
{
struct pci_channel *chan = dev->sysdata;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 96657992a72e..ca5580e4d813 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -33,6 +33,7 @@ config SPARC
config SPARC32
def_bool !64BIT
select GENERIC_ATOMIC64
+ select CLZ_TAB
config SPARC64
def_bool 64BIT
diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S
index 681b3683da9e..d74bc0925f2d 100644
--- a/arch/sparc/lib/divdi3.S
+++ b/arch/sparc/lib/divdi3.S
@@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
- .data
- .align 8
- .globl __clz_tab
-__clz_tab:
- .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
- .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .size __clz_tab,256
- .global .udiv
-
.text
.align 4
+ .global .udiv
.globl __divdi3
__divdi3:
save %sp,-104,%sp
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index 0c9fa2745f13..b3b733262909 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -145,13 +145,13 @@ extern void __add_wrong_size(void)
#ifdef __HAVE_ARCH_CMPXCHG
#define cmpxchg(ptr, old, new) \
- __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
#endif
/*
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 6919e936345b..a850b4d8d14d 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -29,8 +29,8 @@ extern unsigned int sig_xstate_size;
extern void fpu_init(void);
extern void mxcsr_feature_mask_init(void);
extern int init_fpu(struct task_struct *child);
-extern asmlinkage void math_state_restore(void);
-extern void __math_state_restore(void);
+extern void __math_state_restore(struct task_struct *);
+extern void math_state_restore(void);
extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
extern user_regset_active_fn fpregs_active, xfpregs_active;
@@ -212,19 +212,11 @@ static inline void fpu_fxsave(struct fpu *fpu)
#endif /* CONFIG_X86_64 */
-/* We need a safe address that is cheap to find and that is already
- in L1 during context switch. The best choices are unfortunately
- different for UP and SMP */
-#ifdef CONFIG_SMP
-#define safe_address (__per_cpu_offset[0])
-#else
-#define safe_address (__get_cpu_var(kernel_cpustat).cpustat[CPUTIME_USER])
-#endif
-
/*
- * These must be called with preempt disabled
+ * These must be called with preempt disabled. Returns
+ * 'true' if the FPU state is still intact.
*/
-static inline void fpu_save_init(struct fpu *fpu)
+static inline int fpu_save_init(struct fpu *fpu)
{
if (use_xsave()) {
fpu_xsave(fpu);
@@ -233,33 +225,33 @@ static inline void fpu_save_init(struct fpu *fpu)
* xsave header may indicate the init state of the FP.
*/
if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
- return;
+ return 1;
} else if (use_fxsr()) {
fpu_fxsave(fpu);
} else {
asm volatile("fnsave %[fx]; fwait"
: [fx] "=m" (fpu->state->fsave));
- return;
+ return 0;
}
- if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+ /*
+ * If exceptions are pending, we need to clear them so
+ * that we don't randomly get exceptions later.
+ *
+ * FIXME! Is this perhaps only true for the old-style
+ * irq13 case? Maybe we could leave the x87 state
+ * intact otherwise?
+ */
+ if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) {
asm volatile("fnclex");
-
- /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
- is pending. Clear the x87 state here by setting it to fixed
- values. safe_address is a random variable that should be in L1 */
- alternative_input(
- ASM_NOP8 ASM_NOP2,
- "emms\n\t" /* clear stack tags */
- "fildl %P[addr]", /* set F?P to defined value */
- X86_FEATURE_FXSAVE_LEAK,
- [addr] "m" (safe_address));
+ return 0;
+ }
+ return 1;
}
-static inline void __save_init_fpu(struct task_struct *tsk)
+static inline int __save_init_fpu(struct task_struct *tsk)
{
- fpu_save_init(&tsk->thread.fpu);
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ return fpu_save_init(&tsk->thread.fpu);
}
static inline int fpu_fxrstor_checking(struct fpu *fpu)
@@ -281,39 +273,185 @@ static inline int restore_fpu_checking(struct task_struct *tsk)
}
/*
- * Signal frame handlers...
+ * Software FPU state helpers. Careful: these need to
+ * be preemption protection *and* they need to be
+ * properly paired with the CR0.TS changes!
*/
-extern int save_i387_xstate(void __user *buf);
-extern int restore_i387_xstate(void __user *buf);
+static inline int __thread_has_fpu(struct task_struct *tsk)
+{
+ return tsk->thread.has_fpu;
+}
-static inline void __unlazy_fpu(struct task_struct *tsk)
+/* Must be paired with an 'stts' after! */
+static inline void __thread_clear_has_fpu(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
- __save_init_fpu(tsk);
- stts();
- } else
- tsk->fpu_counter = 0;
+ tsk->thread.has_fpu = 0;
+}
+
+/* Must be paired with a 'clts' before! */
+static inline void __thread_set_has_fpu(struct task_struct *tsk)
+{
+ tsk->thread.has_fpu = 1;
}
+/*
+ * Encapsulate the CR0.TS handling together with the
+ * software flag.
+ *
+ * These generally need preemption protection to work,
+ * do try to avoid using these on their own.
+ */
+static inline void __thread_fpu_end(struct task_struct *tsk)
+{
+ __thread_clear_has_fpu(tsk);
+ stts();
+}
+
+static inline void __thread_fpu_begin(struct task_struct *tsk)
+{
+ clts();
+ __thread_set_has_fpu(tsk);
+}
+
+/*
+ * FPU state switching for scheduling.
+ *
+ * This is a two-stage process:
+ *
+ * - switch_fpu_prepare() saves the old state and
+ * sets the new state of the CR0.TS bit. This is
+ * done within the context of the old process.
+ *
+ * - switch_fpu_finish() restores the new state as
+ * necessary.
+ */
+typedef struct { int preload; } fpu_switch_t;
+
+/*
+ * FIXME! We could do a totally lazy restore, but we need to
+ * add a per-cpu "this was the task that last touched the FPU
+ * on this CPU" variable, and the task needs to have a "I last
+ * touched the FPU on this CPU" and check them.
+ *
+ * We don't do that yet, so "fpu_lazy_restore()" always returns
+ * false, but some day..
+ */
+#define fpu_lazy_restore(tsk) (0)
+#define fpu_lazy_state_intact(tsk) do { } while (0)
+
+static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new)
+{
+ fpu_switch_t fpu;
+
+ fpu.preload = tsk_used_math(new) && new->fpu_counter > 5;
+ if (__thread_has_fpu(old)) {
+ if (__save_init_fpu(old))
+ fpu_lazy_state_intact(old);
+ __thread_clear_has_fpu(old);
+ old->fpu_counter++;
+
+ /* Don't change CR0.TS if we just switch! */
+ if (fpu.preload) {
+ __thread_set_has_fpu(new);
+ prefetch(new->thread.fpu.state);
+ } else
+ stts();
+ } else {
+ old->fpu_counter = 0;
+ if (fpu.preload) {
+ if (fpu_lazy_restore(new))
+ fpu.preload = 0;
+ else
+ prefetch(new->thread.fpu.state);
+ __thread_fpu_begin(new);
+ }
+ }
+ return fpu;
+}
+
+/*
+ * By the time this gets called, we've already cleared CR0.TS and
+ * given the process the FPU if we are going to preload the FPU
+ * state - all we need to do is to conditionally restore the register
+ * state itself.
+ */
+static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
+{
+ if (fpu.preload)
+ __math_state_restore(new);
+}
+
+/*
+ * Signal frame handlers...
+ */
+extern int save_i387_xstate(void __user *buf);
+extern int restore_i387_xstate(void __user *buf);
+
static inline void __clear_fpu(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
+ if (__thread_has_fpu(tsk)) {
/* Ignore delayed exceptions from user space */
asm volatile("1: fwait\n"
"2:\n"
_ASM_EXTABLE(1b, 2b));
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
- stts();
+ __thread_fpu_end(tsk);
}
}
+/*
+ * Were we in an interrupt that interrupted kernel mode?
+ *
+ * We can do a kernel_fpu_begin/end() pair *ONLY* if that
+ * pair does nothing at all: the thread must not have fpu (so
+ * that we don't try to save the FPU state), and TS must
+ * be set (so that the clts/stts pair does nothing that is
+ * visible in the interrupted kernel thread).
+ */
+static inline bool interrupted_kernel_fpu_idle(void)
+{
+ return !__thread_has_fpu(current) &&
+ (read_cr0() & X86_CR0_TS);
+}
+
+/*
+ * Were we in user mode (or vm86 mode) when we were
+ * interrupted?
+ *
+ * Doing kernel_fpu_begin/end() is ok if we are running
+ * in an interrupt context from user mode - we'll just
+ * save the FPU state as required.
+ */
+static inline bool interrupted_user_mode(void)
+{
+ struct pt_regs *regs = get_irq_regs();
+ return regs && user_mode_vm(regs);
+}
+
+/*
+ * Can we use the FPU in kernel mode with the
+ * whole "kernel_fpu_begin/end()" sequence?
+ *
+ * It's always ok in process context (ie "not interrupt")
+ * but it is sometimes ok even from an irq.
+ */
+static inline bool irq_fpu_usable(void)
+{
+ return !in_interrupt() ||
+ interrupted_user_mode() ||
+ interrupted_kernel_fpu_idle();
+}
+
static inline void kernel_fpu_begin(void)
{
- struct thread_info *me = current_thread_info();
+ struct task_struct *me = current;
+
+ WARN_ON_ONCE(!irq_fpu_usable());
preempt_disable();
- if (me->status & TS_USEDFPU)
- __save_init_fpu(me->task);
- else
+ if (__thread_has_fpu(me)) {
+ __save_init_fpu(me);
+ __thread_clear_has_fpu(me);
+ /* We do 'stts()' in kernel_fpu_end() */
+ } else
clts();
}
@@ -323,14 +461,6 @@ static inline void kernel_fpu_end(void)
preempt_enable();
}
-static inline bool irq_fpu_usable(void)
-{
- struct pt_regs *regs;
-
- return !in_interrupt() || !(regs = get_irq_regs()) || \
- user_mode(regs) || (read_cr0() & X86_CR0_TS);
-}
-
/*
* Some instructions like VIA's padlock instructions generate a spurious
* DNA fault but don't modify SSE registers. And these instructions
@@ -363,20 +493,64 @@ static inline void irq_ts_restore(int TS_state)
}
/*
+ * The question "does this thread have fpu access?"
+ * is slightly racy, since preemption could come in
+ * and revoke it immediately after the test.
+ *
+ * However, even in that very unlikely scenario,
+ * we can just assume we have FPU access - typically
+ * to save the FP state - we'll just take a #NM
+ * fault and get the FPU access back.
+ *
+ * The actual user_fpu_begin/end() functions
+ * need to be preemption-safe, though.
+ *
+ * NOTE! user_fpu_end() must be used only after you
+ * have saved the FP state, and user_fpu_begin() must
+ * be used only immediately before restoring it.
+ * These functions do not do any save/restore on
+ * their own.
+ */
+static inline int user_has_fpu(void)
+{
+ return __thread_has_fpu(current);
+}
+
+static inline void user_fpu_end(void)
+{
+ preempt_disable();
+ __thread_fpu_end(current);
+ preempt_enable();
+}
+
+static inline void user_fpu_begin(void)
+{
+ preempt_disable();
+ if (!user_has_fpu())
+ __thread_fpu_begin(current);
+ preempt_enable();
+}
+
+/*
* These disable preemption on their own and are safe
*/
static inline void save_init_fpu(struct task_struct *tsk)
{
+ WARN_ON_ONCE(!__thread_has_fpu(tsk));
preempt_disable();
__save_init_fpu(tsk);
- stts();
+ __thread_fpu_end(tsk);
preempt_enable();
}
static inline void unlazy_fpu(struct task_struct *tsk)
{
preempt_disable();
- __unlazy_fpu(tsk);
+ if (__thread_has_fpu(tsk)) {
+ __save_init_fpu(tsk);
+ __thread_fpu_end(tsk);
+ } else
+ tsk->fpu_counter = 0;
preempt_enable();
}
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index ab4092e3214e..7b9cfc4878af 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -190,6 +190,9 @@ struct x86_emulate_ops {
int (*intercept)(struct x86_emulate_ctxt *ctxt,
struct x86_instruction_info *info,
enum x86_intercept_stage stage);
+
+ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
};
typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -298,6 +301,19 @@ struct x86_emulate_ctxt {
#define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
X86EMUL_MODE_PROT64)
+/* CPUID vendors */
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
+
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
+
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
+
enum x86_intercept_stage {
X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */
X86_ICPT_PRE_EXCEPT,
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index aa9088c26931..f7c89e231c6c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -454,6 +454,7 @@ struct thread_struct {
unsigned long trap_no;
unsigned long error_code;
/* floating point and extended processor state */
+ unsigned long has_fpu;
struct fpu fpu;
#ifdef CONFIG_X86_32
/* Virtual 86 mode info */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index bc817cd8b443..cfd8144d5527 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -247,8 +247,6 @@ static inline struct thread_info *current_thread_info(void)
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
-#define TS_USEDFPU 0x0001 /* FPU was used by this task
- this quantum (SMP) */
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
#define TS_POLLING 0x0004 /* idle task polling need_resched,
skip sending interrupt */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 73da6b64f5b7..d6bd49faa40c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -439,7 +439,6 @@ void intel_pmu_pebs_enable(struct perf_event *event)
hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
cpuc->pebs_enabled |= 1ULL << hwc->idx;
- WARN_ON_ONCE(cpuc->enabled);
if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1)
intel_pmu_lbr_enable(event);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 3fab3de3ce96..47a7e63bfe54 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -72,8 +72,6 @@ void intel_pmu_lbr_enable(struct perf_event *event)
if (!x86_pmu.lbr_nr)
return;
- WARN_ON_ONCE(cpuc->enabled);
-
/*
* Reset the LBR stack if we changed task context to
* avoid data leaks.
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 1aae78f775fc..4025fe4f928f 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
unsigned short ss;
unsigned long sp;
#endif
- printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ printk(KERN_DEFAULT
+ "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
#endif
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 6d728d9284bd..17107bd6e1f0 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
if (!stack) {
if (regs)
stack = (unsigned long *)regs->sp;
- else if (task && task != current)
+ else if (task != current)
stack = (unsigned long *)task->thread.sp;
else
stack = &dummy;
@@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs)
unsigned char c;
u8 *ip;
- printk(KERN_EMERG "Stack:\n");
+ printk(KERN_DEFAULT "Stack:\n");
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
- 0, KERN_EMERG);
+ 0, KERN_DEFAULT);
- printk(KERN_EMERG "Code: ");
+ printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 485204f58cda..80bfe1ab0031 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -299,22 +299,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
*next = &next_p->thread;
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
- bool preload_fpu;
+ fpu_switch_t fpu;
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
- /*
- * If the task has used fpu the last 5 timeslices, just do a full
- * restore of the math state immediately to avoid the trap; the
- * chances of needing FPU soon are obviously high now
- */
- preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
- __unlazy_fpu(prev_p);
-
- /* we're going to use this soon, after a few expensive things */
- if (preload_fpu)
- prefetch(next->fpu.state);
+ fpu = switch_fpu_prepare(prev_p, next_p);
/*
* Reload esp0.
@@ -354,11 +343,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
__switch_to_xtra(prev_p, next_p, tss);
- /* If we're going to preload the fpu context, make sure clts
- is run while we're batching the cpu state updates. */
- if (preload_fpu)
- clts();
-
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
@@ -368,15 +352,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
*/
arch_end_context_switch(next_p);
- if (preload_fpu)
- __math_state_restore();
-
/*
* Restore %gs if needed (which is common)
*/
if (prev->gs | next->gs)
lazy_load_gs(next->gs);
+ switch_fpu_finish(next_p, fpu);
+
percpu_write(current_task, next_p);
return prev_p;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9b9fe4a85c87..1fd94bc4279d 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -386,18 +386,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
unsigned fsindex, gsindex;
- bool preload_fpu;
+ fpu_switch_t fpu;
- /*
- * If the task has used fpu the last 5 timeslices, just do a full
- * restore of the math state immediately to avoid the trap; the
- * chances of needing FPU soon are obviously high now
- */
- preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
- /* we're going to use this soon, after a few expensive things */
- if (preload_fpu)
- prefetch(next->fpu.state);
+ fpu = switch_fpu_prepare(prev_p, next_p);
/*
* Reload esp0, LDT and the page table pointer:
@@ -427,13 +418,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
load_TLS(next, cpu);
- /* Must be after DS reload */
- __unlazy_fpu(prev_p);
-
- /* Make sure cpu is ready for new context */
- if (preload_fpu)
- clts();
-
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
@@ -474,6 +458,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
prev->gsindex = gsindex;
+ switch_fpu_finish(next_p, fpu);
+
/*
* Switch the PDA and FPU contexts.
*/
@@ -492,13 +478,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
__switch_to_xtra(prev_p, next_p, tss);
- /*
- * Preload the FPU context, now that we've determined that the
- * task is likely to be using it.
- */
- if (preload_fpu)
- __math_state_restore();
-
return prev_p;
}
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 37a458b521a6..d840e69a853c 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -39,6 +39,14 @@ static int reboot_mode;
enum reboot_type reboot_type = BOOT_ACPI;
int reboot_force;
+/* This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line). This is needed so that we can
+ * suppress DMI scanning for reboot quirks. Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+static int reboot_default = 1;
+
#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
static int reboot_cpu = -1;
#endif
@@ -67,6 +75,12 @@ bool port_cf9_safe = false;
static int __init reboot_setup(char *str)
{
for (;;) {
+ /* Having anything passed on the command line via
+ * reboot= will cause us to disable DMI checking
+ * below.
+ */
+ reboot_default = 0;
+
switch (*str) {
case 'w':
reboot_mode = 0x1234;
@@ -295,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
},
},
- { /* Handle problems with rebooting on VersaLogic Menlow boards */
- .callback = set_bios_reboot,
- .ident = "VersaLogic Menlow based board",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
- },
- },
{ /* Handle reboot issue on Acer Aspire one */
.callback = set_kbd_reboot,
.ident = "Acer Aspire One A110",
@@ -316,7 +322,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
static int __init reboot_init(void)
{
- dmi_check_system(reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(reboot_dmi_table);
+ }
return 0;
}
core_initcall(reboot_init);
@@ -465,7 +476,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
static int __init pci_reboot_init(void)
{
- dmi_check_system(pci_reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(pci_reboot_dmi_table);
+ }
return 0;
}
core_initcall(pci_reboot_init);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 482ec3af2067..77da5b475ad2 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -571,25 +571,34 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
}
/*
- * __math_state_restore assumes that cr0.TS is already clear and the
- * fpu state is all ready for use. Used during context switch.
+ * This gets called with the process already owning the
+ * FPU state, and with CR0.TS cleared. It just needs to
+ * restore the FPU register state.
*/
-void __math_state_restore(void)
+void __math_state_restore(struct task_struct *tsk)
{
- struct thread_info *thread = current_thread_info();
- struct task_struct *tsk = thread->task;
+ /* We need a safe address that is cheap to find and that is already
+ in L1. We've just brought in "tsk->thread.has_fpu", so use that */
+#define safe_address (tsk->thread.has_fpu)
+
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. safe_address is a random variable that should be in L1 */
+ alternative_input(
+ ASM_NOP8 ASM_NOP2,
+ "emms\n\t" /* clear stack tags */
+ "fildl %P[addr]", /* set F?P to defined value */
+ X86_FEATURE_FXSAVE_LEAK,
+ [addr] "m" (safe_address));
/*
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
*/
if (unlikely(restore_fpu_checking(tsk))) {
- stts();
+ __thread_fpu_end(tsk);
force_sig(SIGSEGV, tsk);
return;
}
-
- thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
- tsk->fpu_counter++;
}
/*
@@ -599,13 +608,12 @@ void __math_state_restore(void)
* Careful.. There are problems with IBM-designed IRQ13 behaviour.
* Don't touch unless you *really* know how it works.
*
- * Must be called with kernel preemption disabled (in this case,
- * local interrupts are disabled at the call-site in entry.S).
+ * Must be called with kernel preemption disabled (eg with local
+ * local interrupts as in the case of do_device_not_available).
*/
-asmlinkage void math_state_restore(void)
+void math_state_restore(void)
{
- struct thread_info *thread = current_thread_info();
- struct task_struct *tsk = thread->task;
+ struct task_struct *tsk = current;
if (!tsk_used_math(tsk)) {
local_irq_enable();
@@ -622,9 +630,10 @@ asmlinkage void math_state_restore(void)
local_irq_disable();
}
- clts(); /* Allow maths ops (or we recurse) */
+ __thread_fpu_begin(tsk);
+ __math_state_restore(tsk);
- __math_state_restore();
+ tsk->fpu_counter++;
}
EXPORT_SYMBOL_GPL(math_state_restore);
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index a3911343976b..711091114119 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk)
if (!fx)
return;
- BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU);
+ BUG_ON(__thread_has_fpu(tsk));
xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
@@ -168,7 +168,7 @@ int save_i387_xstate(void __user *buf)
if (!used_math())
return 0;
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
+ if (user_has_fpu()) {
if (use_xsave())
err = xsave_user(buf);
else
@@ -176,8 +176,7 @@ int save_i387_xstate(void __user *buf)
if (err)
return err;
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
- stts();
+ user_fpu_end();
} else {
sanitize_i387_state(tsk);
if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
@@ -292,10 +291,7 @@ int restore_i387_xstate(void __user *buf)
return err;
}
- if (!(task_thread_info(current)->status & TS_USEDFPU)) {
- clts();
- task_thread_info(current)->status |= TS_USEDFPU;
- }
+ user_fpu_begin();
if (use_xsave())
err = restore_user_xstate(buf);
else
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 05a562b85025..0982507b962a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
ss->p = 1;
}
+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
+{
+ struct x86_emulate_ops *ops = ctxt->ops;
+ u32 eax, ebx, ecx, edx;
+
+ /*
+ * syscall should always be enabled in longmode - so only become
+ * vendor specific (cpuid) if other modes are active...
+ */
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
+ return true;
+
+ eax = 0x00000000;
+ ecx = 0x00000000;
+ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
+ /*
+ * Intel ("GenuineIntel")
+ * remark: Intel CPUs only support "syscall" in 64bit
+ * longmode. Also an 64bit guest with a
+ * 32bit compat-app running will #UD !! While this
+ * behaviour can be fixed (by emulating) into AMD
+ * response - CPUs of AMD can't behave like Intel.
+ */
+ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
+ return false;
+
+ /* AMD ("AuthenticAMD") */
+ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
+ return true;
+
+ /* AMD ("AMDisbetter!") */
+ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
+ return true;
+ }
+
+ /* default: (not Intel, not AMD), apply Intel's stricter rules... */
+ return false;
+}
+
static int em_syscall(struct x86_emulate_ctxt *ctxt)
{
struct x86_emulate_ops *ops = ctxt->ops;
@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
ctxt->mode == X86EMUL_MODE_VM86)
return emulate_ud(ctxt);
+ if (!(em_syscall_is_enabled(ctxt)))
+ return emulate_ud(ctxt);
+
ops->get_msr(ctxt, MSR_EFER, &efer);
setup_syscalls_segments(ctxt, &cs, &ss);
+ if (!(efer & EFER_SCE))
+ return emulate_ud(ctxt);
+
ops->get_msr(ctxt, MSR_STAR, &msr_data);
msr_data >>= 32;
cs_sel = (u16)(msr_data & 0xfffc);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d29216c462b3..3b4c8d8ad906 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1457,7 +1457,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
#ifdef CONFIG_X86_64
wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
#endif
- if (current_thread_info()->status & TS_USEDFPU)
+ if (__thread_has_fpu(current))
clts();
load_gdt(&__get_cpu_var(host_gdt));
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 14d6cadc4ba6..9cbfc0698118 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
+ bool pr = false;
+
switch (msr) {
case MSR_EFER:
return set_efer(vcpu, data);
@@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
pr_unimpl(vcpu, "unimplemented perfctr wrmsr: "
"0x%x data 0x%llx\n", msr, data);
break;
+ case MSR_P6_PERFCTR0:
+ case MSR_P6_PERFCTR1:
+ pr = true;
+ case MSR_P6_EVNTSEL0:
+ case MSR_P6_EVNTSEL1:
+ if (kvm_pmu_msr(vcpu, msr))
+ return kvm_pmu_set_msr(vcpu, msr, data);
+
+ if (pr || data != 0)
+ pr_unimpl(vcpu, "disabled perfctr wrmsr: "
+ "0x%x data 0x%llx\n", msr, data);
+ break;
case MSR_K7_CLK_CTL:
/*
* Ignore all writes to this no longer documented MSR.
@@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case MSR_FAM10H_MMIO_CONF_BASE:
data = 0;
break;
+ case MSR_P6_PERFCTR0:
+ case MSR_P6_PERFCTR1:
+ case MSR_P6_EVNTSEL0:
+ case MSR_P6_EVNTSEL1:
+ if (kvm_pmu_msr(vcpu, msr))
+ return kvm_pmu_get_msr(vcpu, msr, pdata);
+ data = 0;
+ break;
case MSR_IA32_UCODE_REV:
data = 0x100000000ULL;
break;
@@ -4180,6 +4202,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
}
+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+ struct kvm_cpuid_entry2 *cpuid = NULL;
+
+ if (eax && ecx)
+ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
+ *eax, *ecx);
+
+ if (cpuid) {
+ *eax = cpuid->eax;
+ *ecx = cpuid->ecx;
+ if (ebx)
+ *ebx = cpuid->ebx;
+ if (edx)
+ *edx = cpuid->edx;
+ return true;
+ }
+
+ return false;
+}
+
static struct x86_emulate_ops emulate_ops = {
.read_std = kvm_read_guest_virt_system,
.write_std = kvm_write_guest_virt_system,
@@ -4211,6 +4255,7 @@ static struct x86_emulate_ops emulate_ops = {
.get_fpu = emulator_get_fpu,
.put_fpu = emulator_put_fpu,
.intercept = emulator_intercept,
+ .get_cpuid = emulator_get_cpuid,
};
static void cache_all_regs(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 9d74824a708d..f0b4caf85c1a 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
stackend = end_of_stack(tsk);
if (tsk != &init_task && *stackend != STACK_END_MAGIC)
- printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
tsk->thread.cr2 = address;
tsk->thread.trap_no = 14;
@@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
sig = 0;
/* Executive summary in case the body of the oops scrolled away */
- printk(KERN_EMERG "CR2: %016lx\n", address);
+ printk(KERN_DEFAULT "CR2: %016lx\n", address);
oops_end(flags, regs, sig);
}
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 492ade8c978e..d99346ea8fdb 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -374,7 +374,7 @@ int __init pci_xen_init(void)
int __init pci_xen_hvm_init(void)
{
- if (!xen_feature(XENFEAT_hvm_pirqs))
+ if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
return 0;
#ifdef CONFIG_ACPI
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 041d4fe9dfe4..501d4e0244ba 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -409,6 +409,13 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
play_dead_common();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
cpu_bringup();
+ /*
+ * Balance out the preempt calls - as we are running in cpu_idle
+ * loop which has been called at bootup from cpu_bringup_and_idle.
+ * The cpucpu_bringup_and_idle called cpu_bringup which made a
+ * preempt_disable() So this preempt_enable will balance it out.
+ */
+ preempt_enable();
}
#else /* !CONFIG_HOTPLUG_CPU */
diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h
index 5fb8c27cbef5..405a8c49ff2c 100644
--- a/arch/xtensa/include/asm/string.h
+++ b/arch/xtensa/include/asm/string.h
@@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
/* Don't build bcopy at all ... */
#define __HAVE_ARCH_BCOPY
-#define __HAVE_ARCH_MEMSCAN
-#define memscan memchr
-
#endif /* _XTENSA_STRING_H */
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index fa8f26309444..75642a352a8f 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1659,7 +1659,7 @@ static void blkiocg_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
if (ioc) {
ioc_cgroup_changed(ioc);
- put_io_context(ioc, NULL);
+ put_io_context(ioc);
}
}
}
diff --git a/block/blk-core.c b/block/blk-core.c
index e6c05a97ee2b..3a78b00edd71 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -642,7 +642,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq)
if (rq->cmd_flags & REQ_ELVPRIV) {
elv_put_request(q, rq);
if (rq->elv.icq)
- put_io_context(rq->elv.icq->ioc, q);
+ put_io_context(rq->elv.icq->ioc);
}
mempool_free(rq, q->rq.rq_pool);
@@ -872,13 +872,15 @@ retry:
spin_unlock_irq(q->queue_lock);
/* create icq if missing */
- if (unlikely(et->icq_cache && !icq))
+ if ((rw_flags & REQ_ELVPRIV) && unlikely(et->icq_cache && !icq)) {
icq = ioc_create_icq(q, gfp_mask);
+ if (!icq)
+ goto fail_icq;
+ }
- /* rqs are guaranteed to have icq on elv_set_request() if requested */
- if (likely(!et->icq_cache || icq))
- rq = blk_alloc_request(q, icq, rw_flags, gfp_mask);
+ rq = blk_alloc_request(q, icq, rw_flags, gfp_mask);
+fail_icq:
if (unlikely(!rq)) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -1210,7 +1212,6 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
drive_stat_acct(req, 0);
- elv_bio_merged(q, req, bio);
return true;
}
@@ -1241,7 +1242,6 @@ static bool bio_attempt_front_merge(struct request_queue *q,
req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
drive_stat_acct(req, 0);
- elv_bio_merged(q, req, bio);
return true;
}
@@ -1255,13 +1255,12 @@ static bool bio_attempt_front_merge(struct request_queue *q,
* on %current's plugged list. Returns %true if merge was successful,
* otherwise %false.
*
- * This function is called without @q->queue_lock; however, elevator is
- * accessed iff there already are requests on the plugged list which in
- * turn guarantees validity of the elevator.
- *
- * Note that, on successful merge, elevator operation
- * elevator_bio_merged_fn() will be called without queue lock. Elevator
- * must be ready for this.
+ * Plugging coalesces IOs from the same issuer for the same purpose without
+ * going through @q->queue_lock. As such it's more of an issuing mechanism
+ * than scheduling, and the request, while may have elvpriv data, is not
+ * added on the elevator at this point. In addition, we don't have
+ * reliable access to the elevator outside queue lock. Only check basic
+ * merging parameters without querying the elevator.
*/
static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
unsigned int *request_count)
@@ -1280,10 +1279,10 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
(*request_count)++;
- if (rq->q != q)
+ if (rq->q != q || !blk_rq_merge_ok(rq, bio))
continue;
- el_ret = elv_try_merge(rq, bio);
+ el_ret = blk_try_merge(rq, bio);
if (el_ret == ELEVATOR_BACK_MERGE) {
ret = bio_attempt_back_merge(q, rq, bio);
if (ret)
@@ -1345,12 +1344,14 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio)
el_ret = elv_merge(q, &req, bio);
if (el_ret == ELEVATOR_BACK_MERGE) {
if (bio_attempt_back_merge(q, req, bio)) {
+ elv_bio_merged(q, req, bio);
if (!attempt_back_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out_unlock;
}
} else if (el_ret == ELEVATOR_FRONT_MERGE) {
if (bio_attempt_front_merge(q, req, bio)) {
+ elv_bio_merged(q, req, bio);
if (!attempt_front_merge(q, req))
elv_merged_request(q, req, el_ret);
goto out_unlock;
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 27a06e00eaec..8b782a63c297 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -29,21 +29,6 @@ void get_io_context(struct io_context *ioc)
}
EXPORT_SYMBOL(get_io_context);
-/*
- * Releasing ioc may nest into another put_io_context() leading to nested
- * fast path release. As the ioc's can't be the same, this is okay but
- * makes lockdep whine. Keep track of nesting and use it as subclass.
- */
-#ifdef CONFIG_LOCKDEP
-#define ioc_release_depth(q) ((q) ? (q)->ioc_release_depth : 0)
-#define ioc_release_depth_inc(q) (q)->ioc_release_depth++
-#define ioc_release_depth_dec(q) (q)->ioc_release_depth--
-#else
-#define ioc_release_depth(q) 0
-#define ioc_release_depth_inc(q) do { } while (0)
-#define ioc_release_depth_dec(q) do { } while (0)
-#endif
-
static void icq_free_icq_rcu(struct rcu_head *head)
{
struct io_cq *icq = container_of(head, struct io_cq, __rcu_head);
@@ -75,11 +60,8 @@ static void ioc_exit_icq(struct io_cq *icq)
if (rcu_dereference_raw(ioc->icq_hint) == icq)
rcu_assign_pointer(ioc->icq_hint, NULL);
- if (et->ops.elevator_exit_icq_fn) {
- ioc_release_depth_inc(q);
+ if (et->ops.elevator_exit_icq_fn)
et->ops.elevator_exit_icq_fn(icq);
- ioc_release_depth_dec(q);
- }
/*
* @icq->q might have gone away by the time RCU callback runs
@@ -98,8 +80,15 @@ static void ioc_release_fn(struct work_struct *work)
struct io_context *ioc = container_of(work, struct io_context,
release_work);
struct request_queue *last_q = NULL;
+ unsigned long flags;
- spin_lock_irq(&ioc->lock);
+ /*
+ * Exiting icq may call into put_io_context() through elevator
+ * which will trigger lockdep warning. The ioc's are guaranteed to
+ * be different, use a different locking subclass here. Use
+ * irqsave variant as there's no spin_lock_irq_nested().
+ */
+ spin_lock_irqsave_nested(&ioc->lock, flags, 1);
while (!hlist_empty(&ioc->icq_list)) {
struct io_cq *icq = hlist_entry(ioc->icq_list.first,
@@ -121,15 +110,15 @@ static void ioc_release_fn(struct work_struct *work)
*/
if (last_q) {
spin_unlock(last_q->queue_lock);
- spin_unlock_irq(&ioc->lock);
+ spin_unlock_irqrestore(&ioc->lock, flags);
blk_put_queue(last_q);
} else {
- spin_unlock_irq(&ioc->lock);
+ spin_unlock_irqrestore(&ioc->lock, flags);
}
last_q = this_q;
- spin_lock_irq(this_q->queue_lock);
- spin_lock(&ioc->lock);
+ spin_lock_irqsave(this_q->queue_lock, flags);
+ spin_lock_nested(&ioc->lock, 1);
continue;
}
ioc_exit_icq(icq);
@@ -137,10 +126,10 @@ static void ioc_release_fn(struct work_struct *work)
if (last_q) {
spin_unlock(last_q->queue_lock);
- spin_unlock_irq(&ioc->lock);
+ spin_unlock_irqrestore(&ioc->lock, flags);
blk_put_queue(last_q);
} else {
- spin_unlock_irq(&ioc->lock);
+ spin_unlock_irqrestore(&ioc->lock, flags);
}
kmem_cache_free(iocontext_cachep, ioc);
@@ -149,79 +138,29 @@ static void ioc_release_fn(struct work_struct *work)
/**
* put_io_context - put a reference of io_context
* @ioc: io_context to put
- * @locked_q: request_queue the caller is holding queue_lock of (hint)
*
* Decrement reference count of @ioc and release it if the count reaches
- * zero. If the caller is holding queue_lock of a queue, it can indicate
- * that with @locked_q. This is an optimization hint and the caller is
- * allowed to pass in %NULL even when it's holding a queue_lock.
+ * zero.
*/
-void put_io_context(struct io_context *ioc, struct request_queue *locked_q)
+void put_io_context(struct io_context *ioc)
{
- struct request_queue *last_q = locked_q;
unsigned long flags;
if (ioc == NULL)
return;
BUG_ON(atomic_long_read(&ioc->refcount) <= 0);
- if (locked_q)
- lockdep_assert_held(locked_q->queue_lock);
-
- if (!atomic_long_dec_and_test(&ioc->refcount))
- return;
/*
- * Destroy @ioc. This is a bit messy because icq's are chained
- * from both ioc and queue, and ioc->lock nests inside queue_lock.
- * The inner ioc->lock should be held to walk our icq_list and then
- * for each icq the outer matching queue_lock should be grabbed.
- * ie. We need to do reverse-order double lock dancing.
- *
- * Another twist is that we are often called with one of the
- * matching queue_locks held as indicated by @locked_q, which
- * prevents performing double-lock dance for other queues.
- *
- * So, we do it in two stages. The fast path uses the queue_lock
- * the caller is holding and, if other queues need to be accessed,
- * uses trylock to avoid introducing locking dependency. This can
- * handle most cases, especially if @ioc was performing IO on only
- * single device.
- *
- * If trylock doesn't cut it, we defer to @ioc->release_work which
- * can do all the double-locking dancing.
+ * Releasing ioc requires reverse order double locking and we may
+ * already be holding a queue_lock. Do it asynchronously from wq.
*/
- spin_lock_irqsave_nested(&ioc->lock, flags,
- ioc_release_depth(locked_q));
-
- while (!hlist_empty(&ioc->icq_list)) {
- struct io_cq *icq = hlist_entry(ioc->icq_list.first,
- struct io_cq, ioc_node);
- struct request_queue *this_q = icq->q;
-
- if (this_q != last_q) {
- if (last_q && last_q != locked_q)
- spin_unlock(last_q->queue_lock);
- last_q = NULL;
-
- if (!spin_trylock(this_q->queue_lock))
- break;
- last_q = this_q;
- continue;
- }
- ioc_exit_icq(icq);
+ if (atomic_long_dec_and_test(&ioc->refcount)) {
+ spin_lock_irqsave(&ioc->lock, flags);
+ if (!hlist_empty(&ioc->icq_list))
+ schedule_work(&ioc->release_work);
+ spin_unlock_irqrestore(&ioc->lock, flags);
}
-
- if (last_q && last_q != locked_q)
- spin_unlock(last_q->queue_lock);
-
- spin_unlock_irqrestore(&ioc->lock, flags);
-
- /* if no icq is left, we're done; otherwise, kick release_work */
- if (hlist_empty(&ioc->icq_list))
- kmem_cache_free(iocontext_cachep, ioc);
- else
- schedule_work(&ioc->release_work);
}
EXPORT_SYMBOL(put_io_context);
@@ -236,7 +175,7 @@ void exit_io_context(struct task_struct *task)
task_unlock(task);
atomic_dec(&ioc->nr_tasks);
- put_io_context(ioc, NULL);
+ put_io_context(ioc);
}
/**
diff --git a/block/blk-merge.c b/block/blk-merge.c
index cfcc37cb222b..160035f54882 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -471,3 +471,40 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
{
return attempt_merge(q, rq, next);
}
+
+bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
+{
+ if (!rq_mergeable(rq))
+ return false;
+
+ /* don't merge file system requests and discard requests */
+ if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
+ return false;
+
+ /* don't merge discard requests and secure discard requests */
+ if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
+ return false;
+
+ /* different data direction or already started, don't merge */
+ if (bio_data_dir(bio) != rq_data_dir(rq))
+ return false;
+
+ /* must be same device and not a special request */
+ if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
+ return false;
+
+ /* only merge integrity protected bio into ditto rq */
+ if (bio_integrity(bio) != blk_integrity_rq(rq))
+ return false;
+
+ return true;
+}
+
+int blk_try_merge(struct request *rq, struct bio *bio)
+{
+ if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector)
+ return ELEVATOR_BACK_MERGE;
+ else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector)
+ return ELEVATOR_FRONT_MERGE;
+ return ELEVATOR_NO_MERGE;
+}
diff --git a/block/blk.h b/block/blk.h
index 7efd772336de..9c12f80882b0 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -137,6 +137,8 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
struct request *next);
void blk_recalc_rq_segments(struct request *rq);
void blk_rq_set_mixed_merge(struct request *rq);
+bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
+int blk_try_merge(struct request *rq, struct bio *bio);
void blk_queue_congestion_threshold(struct request_queue *q);
diff --git a/block/bsg.c b/block/bsg.c
index 4cf703fd98bb..ff64ae3bacee 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q)
mutex_lock(&bsg_mutex);
idr_remove(&bsg_minor_idr, bcd->minor);
- sysfs_remove_link(&q->kobj, "bsg");
+ if (q->kobj.sd)
+ sysfs_remove_link(&q->kobj, "bsg");
device_unregister(bcd->class_dev);
bcd->class_dev = NULL;
kref_put(&bcd->ref, bsg_kref_release_function);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ee55019066a1..d0ba50533668 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1699,18 +1699,11 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
/*
* Lookup the cfqq that this bio will be queued with and allow
- * merge only if rq is queued there. This function can be called
- * from plug merge without queue_lock. In such cases, ioc of @rq
- * and %current are guaranteed to be equal. Avoid lookup which
- * requires queue_lock by using @rq's cic.
+ * merge only if rq is queued there.
*/
- if (current->io_context == RQ_CIC(rq)->icq.ioc) {
- cic = RQ_CIC(rq);
- } else {
- cic = cfq_cic_lookup(cfqd, current->io_context);
- if (!cic)
- return false;
- }
+ cic = cfq_cic_lookup(cfqd, current->io_context);
+ if (!cic)
+ return false;
cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
return cfqq == RQ_CFQQ(rq);
@@ -1794,7 +1787,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cfqd->active_queue = NULL;
if (cfqd->active_cic) {
- put_io_context(cfqd->active_cic->icq.ioc, cfqd->queue);
+ put_io_context(cfqd->active_cic->icq.ioc);
cfqd->active_cic = NULL;
}
}
@@ -3117,17 +3110,18 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
*/
static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
+ enum wl_type_t old_type = cfqq_type(cfqd->active_queue);
+
cfq_log_cfqq(cfqd, cfqq, "preempt");
+ cfq_slice_expired(cfqd, 1);
/*
* workload type is changed, don't save slice, otherwise preempt
* doesn't happen
*/
- if (cfqq_type(cfqd->active_queue) != cfqq_type(cfqq))
+ if (old_type != cfqq_type(cfqq))
cfqq->cfqg->saved_workload_slice = 0;
- cfq_slice_expired(cfqd, 1);
-
/*
* Put the new queue at the front of the of the current list,
* so we know that it will be selected next.
diff --git a/block/elevator.c b/block/elevator.c
index 91e18f8af9be..f016855a46b0 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -70,39 +70,9 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
/*
* can we safely merge with this request?
*/
-int elv_rq_merge_ok(struct request *rq, struct bio *bio)
+bool elv_rq_merge_ok(struct request *rq, struct bio *bio)
{
- if (!rq_mergeable(rq))
- return 0;
-
- /*
- * Don't merge file system requests and discard requests
- */
- if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
- return 0;
-
- /*
- * Don't merge discard requests and secure discard requests
- */
- if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
- return 0;
-
- /*
- * different data direction or already started, don't merge
- */
- if (bio_data_dir(bio) != rq_data_dir(rq))
- return 0;
-
- /*
- * must be same device and not a special request
- */
- if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
- return 0;
-
- /*
- * only merge integrity protected bio into ditto rq
- */
- if (bio_integrity(bio) != blk_integrity_rq(rq))
+ if (!blk_rq_merge_ok(rq, bio))
return 0;
if (!elv_iosched_allow_merge(rq, bio))
@@ -112,23 +82,6 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_rq_merge_ok);
-int elv_try_merge(struct request *__rq, struct bio *bio)
-{
- int ret = ELEVATOR_NO_MERGE;
-
- /*
- * we can merge and sequence is ok, check if it's possible
- */
- if (elv_rq_merge_ok(__rq, bio)) {
- if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector)
- ret = ELEVATOR_BACK_MERGE;
- else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector)
- ret = ELEVATOR_FRONT_MERGE;
- }
-
- return ret;
-}
-
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e;
@@ -478,8 +431,8 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
/*
* First try one-hit cache.
*/
- if (q->last_merge) {
- ret = elv_try_merge(q->last_merge, bio);
+ if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) {
+ ret = blk_try_merge(q->last_merge, bio);
if (ret != ELEVATOR_NO_MERGE) {
*req = q->last_merge;
return ret;
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 88f160b77b1f..107f6f7be5e1 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -31,11 +31,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z)
return (x & y) | (z & (x | y));
}
-static inline u64 RORu64(u64 x, u64 y)
-{
- return (x >> y) | (x << (64 - y));
-}
-
static const u64 sha512_K[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
@@ -66,10 +61,10 @@ static const u64 sha512_K[80] = {
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
};
-#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
-#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
-#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
-#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
+#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
+#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
+#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
@@ -78,7 +73,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input)
static inline void BLEND_OP(int I, u64 *W)
{
- W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]);
+ W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
}
static void
@@ -89,46 +84,42 @@ sha512_transform(u64 *state, const u8 *input)
int i;
u64 W[16];
- /* load the input */
- for (i = 0; i < 16; i++)
- LOAD_OP(i, W, input);
-
/* load the state into our registers */
a=state[0]; b=state[1]; c=state[2]; d=state[3];
e=state[4]; f=state[5]; g=state[6]; h=state[7];
-#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \
- t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \
- t2 = e0(a) + Maj(a, b, c); \
- d += t1; \
- h = t1 + t2
-
-#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \
- BLEND_OP(i, W); \
- t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \
- t2 = e0(a) + Maj(a, b, c); \
- d += t1; \
- h = t1 + t2
-
- for (i = 0; i < 16; i += 8) {
- SHA512_0_15(i, a, b, c, d, e, f, g, h);
- SHA512_0_15(i + 1, h, a, b, c, d, e, f, g);
- SHA512_0_15(i + 2, g, h, a, b, c, d, e, f);
- SHA512_0_15(i + 3, f, g, h, a, b, c, d, e);
- SHA512_0_15(i + 4, e, f, g, h, a, b, c, d);
- SHA512_0_15(i + 5, d, e, f, g, h, a, b, c);
- SHA512_0_15(i + 6, c, d, e, f, g, h, a, b);
- SHA512_0_15(i + 7, b, c, d, e, f, g, h, a);
- }
- for (i = 16; i < 80; i += 8) {
- SHA512_16_79(i, a, b, c, d, e, f, g, h);
- SHA512_16_79(i + 1, h, a, b, c, d, e, f, g);
- SHA512_16_79(i + 2, g, h, a, b, c, d, e, f);
- SHA512_16_79(i + 3, f, g, h, a, b, c, d, e);
- SHA512_16_79(i + 4, e, f, g, h, a, b, c, d);
- SHA512_16_79(i + 5, d, e, f, g, h, a, b, c);
- SHA512_16_79(i + 6, c, d, e, f, g, h, a, b);
- SHA512_16_79(i + 7, b, c, d, e, f, g, h, a);
+ /* now iterate */
+ for (i=0; i<80; i+=8) {
+ if (!(i & 8)) {
+ int j;
+
+ if (i < 16) {
+ /* load the input */
+ for (j = 0; j < 16; j++)
+ LOAD_OP(i + j, W, input);
+ } else {
+ for (j = 0; j < 16; j++) {
+ BLEND_OP(i + j, W);
+ }
+ }
+ }
+
+ t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
}
state[0] += a; state[1] += b; state[2] += c; state[3] += d;
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 2b805d7ef317..8ae05ce18500 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -586,13 +586,6 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
if (pr->flags.need_hotplug_init)
return 0;
- /*
- * Do not start hotplugged CPUs now, but when they
- * are onlined the first time
- */
- if (pr->flags.need_hotplug_init)
- return 0;
-
result = acpi_processor_start(pr);
if (result)
goto err_remove_sysfs;
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index a7d91a72ee35..53d3770a0b1b 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -207,11 +207,11 @@ static void set_smc_timing(struct device *dev, struct ata_device *adev,
{
int ret = 0;
int use_iordy;
+ struct sam9_smc_config smc;
unsigned int t6z; /* data tristate time in ns */
unsigned int cycle; /* SMC Cycle width in MCK ticks */
unsigned int setup; /* SMC Setup width in MCK ticks */
unsigned int pulse; /* CFIOR and CFIOW pulse width in MCK ticks */
- unsigned int cs_setup = 0;/* CS4 or CS5 setup width in MCK ticks */
unsigned int cs_pulse; /* CS4 or CS5 pulse width in MCK ticks*/
unsigned int tdf_cycles; /* SMC TDF MCK ticks */
unsigned long mck_hz; /* MCK frequency in Hz */
@@ -244,26 +244,20 @@ static void set_smc_timing(struct device *dev, struct ata_device *adev,
}
dev_dbg(dev, "Use IORDY=%u, TDF Cycles=%u\n", use_iordy, tdf_cycles);
- info->mode |= AT91_SMC_TDF_(tdf_cycles);
-
- /* write SMC Setup Register */
- at91_sys_write(AT91_SMC_SETUP(info->cs),
- AT91_SMC_NWESETUP_(setup) |
- AT91_SMC_NRDSETUP_(setup) |
- AT91_SMC_NCS_WRSETUP_(cs_setup) |
- AT91_SMC_NCS_RDSETUP_(cs_setup));
- /* write SMC Pulse Register */
- at91_sys_write(AT91_SMC_PULSE(info->cs),
- AT91_SMC_NWEPULSE_(pulse) |
- AT91_SMC_NRDPULSE_(pulse) |
- AT91_SMC_NCS_WRPULSE_(cs_pulse) |
- AT91_SMC_NCS_RDPULSE_(cs_pulse));
- /* write SMC Cycle Register */
- at91_sys_write(AT91_SMC_CYCLE(info->cs),
- AT91_SMC_NWECYCLE_(cycle) |
- AT91_SMC_NRDCYCLE_(cycle));
- /* write SMC Mode Register*/
- at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
+
+ /* SMC Setup Register */
+ smc.nwe_setup = smc.nrd_setup = setup;
+ smc.ncs_write_setup = smc.ncs_read_setup = 0;
+ /* SMC Pulse Register */
+ smc.nwe_pulse = smc.nrd_pulse = pulse;
+ smc.ncs_write_pulse = smc.ncs_read_pulse = cs_pulse;
+ /* SMC Cycle Register */
+ smc.write_cycle = smc.read_cycle = cycle;
+ /* SMC Mode Register*/
+ smc.tdf_cycles = tdf_cycles;
+ smc.mode = info->mode;
+
+ sam9_smc_configure(0, info->cs, &smc);
}
static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -288,20 +282,20 @@ static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev,
struct at91_ide_info *info = dev->link->ap->host->private_data;
unsigned int consumed;
unsigned long flags;
- unsigned int mode;
+ struct sam9_smc_config smc;
local_irq_save(flags);
- mode = at91_sys_read(AT91_SMC_MODE(info->cs));
+ sam9_smc_read_mode(0, info->cs, &smc);
/* set 16bit mode before writing data */
- at91_sys_write(AT91_SMC_MODE(info->cs),
- (mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16);
+ smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16;
+ sam9_smc_write_mode(0, info->cs, &smc);
consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
/* restore 8bit mode after data is written */
- at91_sys_write(AT91_SMC_MODE(info->cs),
- (mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8);
+ smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8;
+ sam9_smc_write_mode(0, info->cs, &smc);
local_irq_restore(flags);
return consumed;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index db87e78d7459..4dabf5077c48 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -208,6 +208,25 @@ static ssize_t print_cpus_offline(struct device *dev,
}
static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
+static void cpu_device_release(struct device *dev)
+{
+ /*
+ * This is an empty function to prevent the driver core from spitting a
+ * warning at us. Yes, I know this is directly opposite of what the
+ * documentation for the driver core and kobjects say, and the author
+ * of this code has already been publically ridiculed for doing
+ * something as foolish as this. However, at this point in time, it is
+ * the only way to handle the issue of statically allocated cpu
+ * devices. The different architectures will have their cpu device
+ * code reworked to properly handle this in the near future, so this
+ * function will then be changed to correctly free up the memory held
+ * by the cpu device.
+ *
+ * Never copy this way of doing things, or you too will be made fun of
+ * on the linux-kerenl list, you have been warned.
+ */
+}
+
/*
* register_cpu - Setup a sysfs device for a CPU.
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -221,8 +240,10 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
int error;
cpu->node_id = cpu_to_node(num);
+ memset(&cpu->dev, 0x00, sizeof(struct device));
cpu->dev.id = num;
cpu->dev.bus = &cpu_subsys;
+ cpu->dev.release = cpu_device_release;
error = device_register(&cpu->dev);
if (!error && cpu->hotpluggable)
register_cpu_control(cpu);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index ed5de58c340f..9e60dbe9fd94 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -572,19 +572,36 @@ static int init_memory_block(struct memory_block **memory,
}
static int add_memory_section(int nid, struct mem_section *section,
+ struct memory_block **mem_p,
unsigned long state, enum mem_add_context context)
{
- struct memory_block *mem;
+ struct memory_block *mem = NULL;
+ int scn_nr = __section_nr(section);
int ret = 0;
mutex_lock(&mem_sysfs_mutex);
- mem = find_memory_block(section);
+ if (context == BOOT) {
+ /* same memory block ? */
+ if (mem_p && *mem_p)
+ if (scn_nr >= (*mem_p)->start_section_nr &&
+ scn_nr <= (*mem_p)->end_section_nr) {
+ mem = *mem_p;
+ kobject_get(&mem->dev.kobj);
+ }
+ } else
+ mem = find_memory_block(section);
+
if (mem) {
mem->section_count++;
kobject_put(&mem->dev.kobj);
- } else
+ } else {
ret = init_memory_block(&mem, section, state);
+ /* store memory_block pointer for next loop */
+ if (!ret && context == BOOT)
+ if (mem_p)
+ *mem_p = mem;
+ }
if (!ret) {
if (context == HOTPLUG &&
@@ -627,7 +644,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
*/
int register_new_memory(int nid, struct mem_section *section)
{
- return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
+ return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);
}
int unregister_memory_section(struct mem_section *section)
@@ -647,6 +664,7 @@ int __init memory_dev_init(void)
int ret;
int err;
unsigned long block_sz;
+ struct memory_block *mem = NULL;
ret = subsys_system_register(&memory_subsys, NULL);
if (ret)
@@ -662,7 +680,10 @@ int __init memory_dev_init(void)
for (i = 0; i < NR_MEM_SECTIONS; i++) {
if (!present_section_nr(i))
continue;
- err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+ /* don't need to reuse memory_block if only one per block */
+ err = add_memory_section(0, __nr_to_section(i),
+ (sections_per_block == 1) ? NULL : &mem,
+ MEM_ONLINE,
BOOT);
if (!ret)
ret = err;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 44f427a66117..90aa2a11a933 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -456,7 +456,15 @@ static int link_mem_sections(int nid)
if (!present_section_nr(section_nr))
continue;
mem_sect = __nr_to_section(section_nr);
+
+ /* same memblock ? */
+ if (mem_blk)
+ if ((section_nr >= mem_blk->start_section_nr) &&
+ (section_nr <= mem_blk->end_section_nr))
+ continue;
+
mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
+
ret = register_mem_sect_under_node(mem_blk, nid);
if (!err)
err = ret;
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 1a02b7537c8b..d141b80479b5 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -75,6 +75,9 @@ struct regmap {
const void *reg_defaults_raw;
void *cache;
bool cache_dirty;
+
+ struct reg_default *patch;
+ int patch_regs;
};
struct regcache_ops {
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 1ead66186b7c..5cd2a37e7688 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -53,7 +53,7 @@ static int regcache_hw_init(struct regmap *map)
for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
- if (!val)
+ if (regmap_volatile(map, i))
continue;
count++;
}
@@ -70,7 +70,7 @@ static int regcache_hw_init(struct regmap *map)
for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
- if (!val)
+ if (regmap_volatile(map, i))
continue;
map->reg_defaults[j].reg = i;
map->reg_defaults[j].def = val;
@@ -268,6 +268,17 @@ int regcache_sync(struct regmap *map)
map->cache_ops->name);
name = map->cache_ops->name;
trace_regcache_sync(map->dev, name, "start");
+
+ /* Apply any patch first */
+ for (i = 0; i < map->patch_regs; i++) {
+ ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
+ if (ret != 0) {
+ dev_err(map->dev, "Failed to write %x = %x: %d\n",
+ map->patch[i].reg, map->patch[i].def, ret);
+ goto out;
+ }
+ }
+
if (!map->cache_dirty)
goto out;
if (map->cache_ops->sync) {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 65558034318f..7ac234f0b1c5 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -672,6 +672,79 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
}
EXPORT_SYMBOL_GPL(regmap_update_bits_check);
+/**
+ * regmap_register_patch: Register and apply register updates to be applied
+ * on device initialistion
+ *
+ * @map: Register map to apply updates to.
+ * @regs: Values to update.
+ * @num_regs: Number of entries in regs.
+ *
+ * Register a set of register updates to be applied to the device
+ * whenever the device registers are synchronised with the cache and
+ * apply them immediately. Typically this is used to apply
+ * corrections to be applied to the device defaults on startup, such
+ * as the updates some vendors provide to undocumented registers.
+ */
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+ int num_regs)
+{
+ int i, ret;
+ bool bypass;
+
+ /* If needed the implementation can be extended to support this */
+ if (map->patch)
+ return -EBUSY;
+
+ mutex_lock(&map->lock);
+
+ bypass = map->cache_bypass;
+
+ map->cache_bypass = true;
+
+ /* Write out first; it's useful to apply even if we fail later. */
+ for (i = 0; i < num_regs; i++) {
+ ret = _regmap_write(map, regs[i].reg, regs[i].def);
+ if (ret != 0) {
+ dev_err(map->dev, "Failed to write %x = %x: %d\n",
+ regs[i].reg, regs[i].def, ret);
+ goto out;
+ }
+ }
+
+ map->patch = kcalloc(sizeof(struct reg_default), num_regs, GFP_KERNEL);
+ if (map->patch != NULL) {
+ memcpy(map->patch, regs,
+ num_regs * sizeof(struct reg_default));
+ map->patch_regs = num_regs;
+ } else {
+ ret = -ENOMEM;
+ }
+
+out:
+ map->cache_bypass = bypass;
+
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_register_patch);
+
+/*
+ * regmap_get_val_bytes(): Report the size of a register value
+ *
+ * Report the size of a register value, mainly intended to for use by
+ * generic infrastructure built on top of regmap.
+ */
+int regmap_get_val_bytes(struct regmap *map)
+{
+ if (map->format.format_write)
+ return -EINVAL;
+
+ return map->format.val_bytes;
+}
+EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
+
static int __init regmap_initcall(void)
{
regmap_debugfs_initcall();
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index febbc0a1222a..ec31f7dd5549 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus)
err = bcma_sprom_get(bus);
if (err == -ENOENT) {
pr_err("No SPROM available\n");
- } else if (err) {
+ } else if (err)
pr_err("Failed to get SPROM: %d\n", err);
- return -ENOENT;
- }
/* Register found cores */
bcma_register_cores(bus);
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index cad994857683..3a2f672db9ad 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus)
core->bus = bus;
err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
- if (err == -ENODEV) {
- core_num++;
- continue;
- } else if (err == -ENXIO)
- continue;
- else if (err == -ESPIPE)
- break;
- else if (err < 0)
+ if (err < 0) {
+ kfree(core);
+ if (err == -ENODEV) {
+ core_num++;
+ continue;
+ } else if (err == -ENXIO) {
+ continue;
+ } else if (err == -ESPIPE) {
+ break;
+ }
return err;
+ }
core->core_index = core_num++;
bus->nr_cores++;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 510fb10ec45a..9baf11e86362 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4368,8 +4368,14 @@ out_unreg_blkdev:
out_put_disk:
while (dr--) {
del_timer_sync(&motor_off_timer[dr]);
- if (disks[dr]->queue)
+ if (disks[dr]->queue) {
blk_cleanup_queue(disks[dr]->queue);
+ /*
+ * put_disk() is not paired with add_disk() and
+ * will put queue reference one extra time. fix it.
+ */
+ disks[dr]->queue = NULL;
+ }
put_disk(disks[dr]);
}
return err;
@@ -4579,6 +4585,15 @@ static void __exit floppy_module_exit(void)
platform_device_unregister(&floppy_device[drive]);
}
blk_cleanup_queue(disks[drive]->queue);
+
+ /*
+ * These disks have not called add_disk(). Don't put down
+ * queue reference in put_disk().
+ */
+ if (!(allowed_drive_mask & (1 << drive)) ||
+ fdc_state[FDC(drive)].version == FDC_NONE)
+ disks[drive]->queue = NULL;
+
put_disk(disks[drive]);
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f00257782fcc..cd504353b278 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
return __splice_from_pipe(pipe, sd, lo_splice_actor);
}
-static int
+static ssize_t
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
struct splice_desc sd;
struct file *file;
- long retval;
+ ssize_t retval;
cookie.lo = lo;
cookie.page = bvec->bv_page;
@@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo,
file = lo->lo_backing_file;
retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
- if (retval < 0)
- return retval;
- if (retval != bvec->bv_len)
- return -EIO;
- return 0;
+ return retval;
}
static int
lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
{
struct bio_vec *bvec;
- int i, ret = 0;
+ ssize_t s;
+ int i;
bio_for_each_segment(bvec, bio, i) {
- ret = do_lo_receive(lo, bvec, bsize, pos);
- if (ret < 0)
+ s = do_lo_receive(lo, bvec, bsize, pos);
+ if (s < 0)
+ return s;
+
+ if (s != bvec->bv_len) {
+ zero_fill_bio(bio);
break;
+ }
pos += bvec->bv_len;
}
- return ret;
+ return 0;
}
static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index b74eab70c3d0..8eb81c96608f 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2068,8 +2068,6 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
* when the read completes.
* @data Callback data passed to the callback function
* when the read completes.
- * @barrier If non-zero, this command must be completed before
- * issuing any other commands.
* @dir Direction (read or write)
*
* return value
@@ -2077,7 +2075,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
*/
static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
int nsect, int nents, int tag, void *callback,
- void *data, int barrier, int dir)
+ void *data, int dir)
{
struct host_to_dev_fis *fis;
struct mtip_port *port = dd->port;
@@ -2108,8 +2106,6 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
*((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
*((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
fis->device = 1 << 6;
- if (barrier)
- fis->device |= FUA_BIT;
fis->features = nsect & 0xFF;
fis->features_ex = (nsect >> 8) & 0xFF;
fis->sect_count = ((tag << 3) | (tag >> 5));
@@ -3087,7 +3083,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
tag,
bio_endio,
bio,
- bio->bi_rw & REQ_FUA,
bio_data_dir(bio));
} else
bio_io_error(bio);
@@ -3187,6 +3182,10 @@ skip_create_disk:
blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
blk_queue_physical_block_size(dd->queue, 4096);
blk_queue_io_min(dd->queue, 4096);
+ /*
+ * write back cache is not supported in the device. FUA depends on
+ * write back cache support, hence setting flush support to zero.
+ */
blk_queue_flush(dd->queue, 0);
/* Set the capacity of the device in 512 byte sectors. */
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 723d7c4946dc..e0554a8f2233 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -104,9 +104,6 @@
/* BAR number used to access the HBA registers. */
#define MTIP_ABAR 5
-/* Forced Unit Access Bit */
-#define FUA_BIT 0x80
-
#ifdef DEBUG
#define dbg_printk(format, arg...) \
printk(pr_fmt(format), ##arg);
@@ -415,8 +412,6 @@ struct driver_data {
atomic_t resumeflag; /* Atomic variable to track suspend/resume */
- atomic_t eh_active; /* Flag for error handling tracking */
-
struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
};
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 3fd31dec8c9c..a6278e7e61a0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
rbdc = __rbd_client_find(opt);
if (rbdc) {
ceph_destroy_options(opt);
+ kfree(rbd_opts);
/* using an existing client */
kref_get(&rbdc->kref);
@@ -406,15 +407,15 @@ done_err:
/*
* Destroy ceph client
+ *
+ * Caller must hold node_lock.
*/
static void rbd_client_release(struct kref *kref)
{
struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
dout("rbd_release_client %p\n", rbdc);
- spin_lock(&node_lock);
list_del(&rbdc->node);
- spin_unlock(&node_lock);
ceph_destroy_client(rbdc->client);
kfree(rbdc->rbd_opts);
@@ -427,7 +428,9 @@ static void rbd_client_release(struct kref *kref)
*/
static void rbd_put_client(struct rbd_device *rbd_dev)
{
+ spin_lock(&node_lock);
kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+ spin_unlock(&node_lock);
rbd_dev->rbd_client = NULL;
rbd_dev->client = NULL;
}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 55eaf474d32c..d620b4495745 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -286,8 +286,6 @@
/* used to tell the module to turn on full debugging messages */
static bool debug;
-/* used to keep tray locked at all times */
-static int keeplocked;
/* default compatibility mode */
static bool autoclose=1;
static bool autoeject;
@@ -1204,7 +1202,7 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
cdrom_dvd_rw_close_write(cdi);
- if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+ if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {
cdinfo(CD_CLOSE, "Unlocking door!\n");
cdo->lock_door(cdi, 0);
}
@@ -1371,7 +1369,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
curslot = info->hdr.curslot;
kfree(info);
- if (cdi->use_count > 1 || keeplocked) {
+ if (cdi->use_count > 1 || cdi->keeplocked) {
if (slot == CDSL_CURRENT) {
return curslot;
} else {
@@ -2119,11 +2117,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!nr)
return -ENOMEM;
- if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) {
- ret = -EFAULT;
- goto out;
- }
-
cgc.data_direction = CGC_DATA_READ;
while (nframes > 0) {
if (nr > nframes)
@@ -2132,7 +2125,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
if (ret)
break;
- if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
+ if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
ret = -EFAULT;
break;
}
@@ -2140,7 +2133,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
nframes -= nr;
lba += nr;
}
-out:
kfree(cgc.buffer);
return ret;
}
@@ -2295,7 +2287,7 @@ static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
if (!CDROM_CAN(CDC_OPEN_TRAY))
return -ENOSYS;
- if (cdi->use_count != 1 || keeplocked)
+ if (cdi->use_count != 1 || cdi->keeplocked)
return -EBUSY;
if (CDROM_CAN(CDC_LOCK)) {
int ret = cdi->ops->lock_door(cdi, 0);
@@ -2322,7 +2314,7 @@ static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
if (!CDROM_CAN(CDC_OPEN_TRAY))
return -ENOSYS;
- if (keeplocked)
+ if (cdi->keeplocked)
return -EBUSY;
cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
@@ -2453,7 +2445,7 @@ static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,
if (!CDROM_CAN(CDC_LOCK))
return -EDRIVE_CANT_DO_THIS;
- keeplocked = arg ? 1 : 0;
+ cdi->keeplocked = arg ? 1 : 0;
/*
* Don't unlock the door on multiple opens by default, but allow
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 97f87b29b9f3..f4aed5fc2cb6 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1343,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
tasklet_init(&atchan->tasklet, atc_tasklet,
(unsigned long)atchan);
- atc_enable_irq(atchan);
+ atc_enable_chan_irq(atdma, i);
}
/* set base routines */
@@ -1410,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)
struct at_dma_chan *atchan = to_at_dma_chan(chan);
/* Disable interrupts */
- atc_disable_irq(atchan);
+ atc_disable_chan_irq(atdma, chan->chan_id);
tasklet_disable(&atchan->tasklet);
tasklet_kill(&atchan->tasklet);
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index dcaedfc181cf..a8d3277d60b5 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -327,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
}
-static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
{
- struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
- u32 ebci;
+ u32 ebci;
/* enable interrupts on buffer transfer completion & error */
- ebci = AT_DMA_BTC(atchan->chan_common.chan_id)
- | AT_DMA_ERR(atchan->chan_common.chan_id);
+ ebci = AT_DMA_BTC(chan_id)
+ | AT_DMA_ERR(chan_id);
if (on)
dma_writel(atdma, EBCIER, ebci);
else
dma_writel(atdma, EBCIDR, ebci);
}
-static inline void atc_enable_irq(struct at_dma_chan *atchan)
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 1);
+ atc_setup_irq(atdma, chan_id, 1);
}
-static inline void atc_disable_irq(struct at_dma_chan *atchan)
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 0);
+ atc_setup_irq(atdma, chan_id, 0);
}
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 2b8661b54eaf..24225f0fdcd8 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan)
}
if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
cnt = dmatest_add_threads(dtc, DMA_PQ);
- thread_count += cnt > 0 ?: 0;
+ thread_count += cnt > 0 ? cnt : 0;
}
pr_info("dmatest: Started %u threads using %s\n",
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index a8af379680c1..8bc5acf36ee5 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1102,11 +1102,13 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
case DMA_SLAVE_CONFIG:
if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
sdmac->per_address = dmaengine_cfg->src_addr;
- sdmac->watermark_level = dmaengine_cfg->src_maxburst;
+ sdmac->watermark_level = dmaengine_cfg->src_maxburst *
+ dmaengine_cfg->src_addr_width;
sdmac->word_size = dmaengine_cfg->src_addr_width;
} else {
sdmac->per_address = dmaengine_cfg->dst_addr;
- sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
+ sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
+ dmaengine_cfg->dst_addr_width;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
}
sdmac->direction = dmaengine_cfg->direction;
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 54043cd831c8..812fd76e9c18 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1262,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&shdev->common.channels);
- dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+ if (!pdata->slave_only)
+ dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
if (pdata->slave && pdata->slave_num)
dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 6628feaa7622..7f5f0da726da 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
static char ohci_driver_name[] = KBUILD_MODNAME;
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
@@ -289,6 +290,9 @@ static const struct {
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+ QUIRK_RESET_PACKET},
+
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
QUIRK_NO_MSI},
@@ -299,7 +303,7 @@ static const struct {
QUIRK_NO_MSI},
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_CYCLE_TIMER},
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 5b6948081f8f..ddfacc5ce56d 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
};
static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
- "gpi000", "gpio01", "gpio02", "gpio03",
+ "gpio00", "gpio01", "gpio02", "gpio03",
"gpio04", "gpio05"
};
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 03d6dd5dcb77..f0febe5b8221 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
chip->reg = chip->base;
chip->ch = i;
mutex_init(&chip->lock);
+ spin_lock_init(&chip->spinlock);
ioh_gpio_setup(chip, num_ports[i]);
ret = gpiochip_add(&chip->gpio);
if (ret) {
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 68fa55e86eb1..e8729cc2ba2b 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
+ spin_lock_init(&chip->spinlock);
pch_gpio_setup(chip);
ret = gpiochip_add(&chip->gpio);
if (ret) {
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a7661773c052..0a79a1167a25 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
};
#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
-static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags)
+static int exynos4_gpio_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
{
- const __be32 *gpio = gpio_spec;
- const u32 n = be32_to_cpup(gpio);
- unsigned int pin = gc->base + be32_to_cpu(gpio[0]);
+ unsigned int pin;
if (WARN_ON(gc->of_gpio_n_cells < 4))
return -EINVAL;
- if (n > gc->ngpio)
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
- if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1]))))
+ if (gpiospec->args[0] > gc->ngpio)
+ return -EINVAL;
+
+ pin = gc->base + gpiospec->args[0];
+
+ if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
pr_warn("gpio_xlate: failed to set pin function\n");
- if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2])))
+ if (s3c_gpio_setpull(pin, gpiospec->args[2]))
pr_warn("gpio_xlate: failed to set pin pull up/down\n");
- if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3])))
+ if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
pr_warn("gpio_xlate: failed to set pin drive strength\n");
- return n;
+ return gpiospec->args[0];
}
static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index ddd70db45f76..637fcc3766c7 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -315,7 +315,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
if (err)
return err;
- if (__get_user(c32.auth, &client->auth)
+ if (__get_user(c32.idx, &client->idx)
+ || __get_user(c32.auth, &client->auth)
|| __get_user(c32.pid, &client->pid)
|| __get_user(c32.uid, &client->uid)
|| __get_user(c32.magic, &client->magic)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b3b51c43dad0..00fbff5ddd81 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1872,7 +1872,7 @@ static void intel_update_fbc(struct drm_device *dev)
if (enable_fbc < 0) {
DRM_DEBUG_KMS("fbc set to per-chip default\n");
enable_fbc = 1;
- if (INTEL_INFO(dev)->gen <= 5)
+ if (INTEL_INFO(dev)->gen <= 6)
enable_fbc = 0;
}
if (!enable_fbc) {
@@ -5307,6 +5307,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
}
}
+ pipeconf &= ~PIPECONF_INTERLACE_MASK;
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
/* the chip adds 2 halflines automatically */
@@ -5317,7 +5318,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
adjusted_mode->crtc_vsync_end -= 1;
adjusted_mode->crtc_vsync_start -= 1;
} else
- pipeconf &= ~PIPECONF_INTERLACE_MASK; /* progressive */
+ pipeconf |= PIPECONF_PROGRESSIVE;
I915_WRITE(HTOTAL(pipe),
(adjusted_mode->crtc_hdisplay - 1) |
@@ -5902,6 +5903,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
}
}
+ pipeconf &= ~PIPECONF_INTERLACE_MASK;
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
/* the chip adds 2 halflines automatically */
@@ -5912,7 +5914,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
adjusted_mode->crtc_vsync_end -= 1;
adjusted_mode->crtc_vsync_start -= 1;
} else
- pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+ pipeconf |= PIPECONF_PROGRESSIVE;
I915_WRITE(HTOTAL(pipe),
(adjusted_mode->crtc_hdisplay - 1) |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index db3b461ad412..94f860cce3f7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -208,17 +208,8 @@ intel_dp_link_clock(uint8_t link_bw)
*/
static int
-intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
+intel_dp_link_required(int pixel_clock, int bpp)
{
- struct drm_crtc *crtc = intel_dp->base.base.crtc;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int bpp = 24;
-
- if (check_bpp)
- bpp = check_bpp;
- else if (intel_crtc)
- bpp = intel_crtc->bpp;
-
return (pixel_clock * bpp + 9) / 10;
}
@@ -245,12 +236,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
return MODE_PANEL;
}
- mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
+ mode_rate = intel_dp_link_required(mode->clock, 24);
max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
if (mode_rate > max_rate) {
- mode_rate = intel_dp_link_required(intel_dp,
- mode->clock, 18);
+ mode_rate = intel_dp_link_required(mode->clock, 18);
if (mode_rate > max_rate)
return MODE_CLOCK_HIGH;
else
@@ -683,7 +673,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
int lane_count, clock;
int max_lane_count = intel_dp_max_lane_count(intel_dp);
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
- int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
+ int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
@@ -701,7 +691,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
- if (intel_dp_link_required(intel_dp, mode->clock, bpp)
+ if (intel_dp_link_required(mode->clock, bpp)
<= link_avail) {
intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 798f6e1aa544..aa84832b0e1a 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -694,6 +694,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
},
{
.callback = intel_no_lvds_dmi_callback,
+ .ident = "AOpen i45GMx-I",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+ DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
.ident = "Aopen i945GTt-VFA",
.matches = {
DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 1e382ad5a2b8..a37c31e358aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -54,9 +54,10 @@ struct bit_entry {
int bit_table(struct drm_device *, u8 id, struct bit_entry *);
enum dcb_gpio_tag {
- DCB_GPIO_TVDAC0 = 0xc,
+ DCB_GPIO_PANEL_POWER = 0x01,
+ DCB_GPIO_TVDAC0 = 0x0c,
DCB_GPIO_TVDAC1 = 0x2d,
- DCB_GPIO_PWM_FAN = 0x9,
+ DCB_GPIO_PWM_FAN = 0x09,
DCB_GPIO_FAN_SENSE = 0x3d,
DCB_GPIO_UNUSED = 0xff
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 3cb52bc52b21..795a9e3c990a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev)
if (ret)
return ret;
+ /* power on internal panel if it's not already. the init tables of
+ * some vbios default this to off for some reason, causing the
+ * panel to not work after resume
+ */
+ if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
+ nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
+ msleep(300);
+ }
+
+ /* enable polling for external displays */
drm_kms_helper_poll_enable(dev);
/* enable hotplug interrupts */
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index e4a7cfe7898d..81d7962e7252 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
int nouveau_ctxfw;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
-MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
+MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");
int nouveau_mxmdcb = 1;
module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 5f0bc57fdaab..7ce3fde40743 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -380,6 +380,25 @@ retry:
}
static int
+validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
+{
+ struct nouveau_fence *fence = NULL;
+ int ret = 0;
+
+ spin_lock(&nvbo->bo.bdev->fence_lock);
+ if (nvbo->bo.sync_obj)
+ fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+ spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+ if (fence) {
+ ret = nouveau_fence_sync(fence, chan);
+ nouveau_fence_unref(&fence);
+ }
+
+ return ret;
+}
+
+static int
validate_list(struct nouveau_channel *chan, struct list_head *list,
struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
{
@@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
list_for_each_entry(nvbo, list, entry) {
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail pre-validate sync\n");
return ret;
@@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret;
}
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail post-validate sync\n");
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c
index 8bccddf4eff0..e5a64f0f4cb7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mxm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c
@@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev)
if (mxm_shadow(dev, mxm[0])) {
MXM_MSG(dev, "failed to locate valid SIS\n");
+#if 0
+ /* we should, perhaps, fall back to some kind of limited
+ * mode here if the x86 vbios hasn't already done the
+ * work for us (so we prevent loading with completely
+ * whacked vbios tables).
+ */
return -EINVAL;
+#else
+ return 0;
+#endif
}
MXM_MSG(dev, "MXMS Version %d.%d\n",
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 03937212e9d8..ec5481dfcd82 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nv50_pm_state *info;
struct pll_lims pll;
- int ret = -EINVAL;
+ int clk, ret = -EINVAL;
int N, M, P1, P2;
- u32 clk, out;
+ u32 out;
if (dev_priv->chipset == 0xaa ||
dev_priv->chipset == 0xac)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 891935271d34..742f17f009a9 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1184,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1353,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index a71557ce01dc..552b436451fd 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -564,9 +564,21 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
ENCODER_OBJECT_ID_NUTMEG)
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
- ENCODER_OBJECT_ID_TRAVIS)
- panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
- else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+ ENCODER_OBJECT_ID_TRAVIS) {
+ u8 id[6];
+ int i;
+ for (i = 0; i < 6; i++)
+ id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
+ if (id[0] == 0x73 &&
+ id[1] == 0x69 &&
+ id[2] == 0x76 &&
+ id[3] == 0x61 &&
+ id[4] == 0x72 &&
+ id[5] == 0x54)
+ panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+ else
+ panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+ } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index ae09fe82afbc..9be353b894cc 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3191,6 +3191,7 @@ static int evergreen_startup(struct radeon_device *rdev)
if (r) {
DRM_ERROR("radeon: failed testing IB (%d).\n", r);
rdev->accel_working = false;
+ return r;
}
r = r600_audio_init(rdev);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index bfd36ab643a6..18cd84fae99c 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -789,9 +789,7 @@ int r100_irq_process(struct radeon_device *rdev)
WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
break;
default:
- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
- WREG32(RADEON_MSI_REARM_EN, msi_rearm);
- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
break;
}
}
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index d996f4381130..accc032c103f 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)
radeon_ring_write(ring, sq_stack_resource_mgmt_2);
}
+#define I2F_MAX_BITS 15
+#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1)
+#define I2F_SHIFT (24 - I2F_MAX_BITS)
+
+/*
+ * Converts unsigned integer into 32-bit IEEE floating point representation.
+ * Conversion is not universal and only works for the range from 0
+ * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
+ * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
+ * I2F_MAX_BITS can be increased, but that will add to the loop iterations
+ * and slow us down. Conversion is done by shifting the input and counting
+ * down until the first 1 reaches bit position 23. The resulting counter
+ * and the shifted input are, respectively, the exponent and the fraction.
+ * The sign is always zero.
+ */
static uint32_t i2f(uint32_t input)
{
u32 result, i, exponent, fraction;
- if ((input & 0x3fff) == 0)
- result = 0; /* 0 is a special case */
+ WARN_ON_ONCE(input > I2F_MAX_INPUT);
+
+ if ((input & I2F_MAX_INPUT) == 0)
+ result = 0;
else {
- exponent = 140; /* exponent biased by 127; */
- fraction = (input & 0x3fff) << 10; /* cheat and only
- handle numbers below 2^^15 */
- for (i = 0; i < 14; i++) {
+ exponent = 126 + I2F_MAX_BITS;
+ fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
+
+ for (i = 0; i < I2F_MAX_BITS; i++) {
if (fraction & 0x800000)
break;
else {
- fraction = fraction << 1; /* keep
- shifting left until top bit = 1 */
+ fraction = fraction << 1;
exponent = exponent - 1;
}
}
- result = exponent << 23 | (fraction & 0x7fffff); /* mask
- off top bit; assumed 1 */
+ result = exponent << 23 | (fraction & 0x7fffff);
}
return result;
}
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 5082d17d14dc..9e72daeeddc6 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -2931,6 +2931,20 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
}
}
+ if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) &&
+ (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) {
+ if (connected) {
+ DRM_DEBUG_KMS("DFP6 connected\n");
+ bios_0_scratch |= ATOM_S0_DFP6;
+ bios_3_scratch |= ATOM_S3_DFP6_ACTIVE;
+ bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6;
+ } else {
+ DRM_DEBUG_KMS("DFP6 disconnected\n");
+ bios_0_scratch &= ~ATOM_S0_DFP6;
+ bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE;
+ bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6;
+ }
+ }
if (rdev->family >= CHIP_R600) {
WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
@@ -2951,6 +2965,9 @@ radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
uint32_t bios_3_scratch;
+ if (ASIC_IS_DCE4(rdev))
+ return;
+
if (rdev->family >= CHIP_R600)
bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
else
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 13ac63ba6075..98724fcb0088 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -59,8 +59,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
obj = (union acpi_object *)buffer.pointer;
memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+ len = obj->buffer.length;
kfree(buffer.pointer);
- return obj->buffer.length;
+ return len;
}
bool radeon_atrm_supported(struct pci_dev *pdev)
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index cec51a5b69dd..49f7cb7e226b 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
+ drm_kms_helper_poll_disable(dev);
+
/* turn off display hw */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
@@ -972,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}
+
+ drm_kms_helper_poll_enable(dev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 64ea3dd9e6ff..4bd36a354fbe 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -364,8 +364,10 @@ int radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
int not_processed = 0;
read_lock_irqsave(&rdev->fence_lock, irq_flags);
- if (!rdev->fence_drv[ring].initialized)
+ if (!rdev->fence_drv[ring].initialized) {
+ read_unlock_irqrestore(&rdev->fence_lock, irq_flags);
return 0;
+ }
if (!list_empty(&rdev->fence_drv[ring].emitted)) {
struct list_head *ptr;
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index e2a393ff0c44..98a8ad680109 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -958,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
+ i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
"Radeon aux bus %s", name);
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index ec46eb45e34c..c05865e5521f 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -684,9 +684,7 @@ int rs600_irq_process(struct radeon_device *rdev)
WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
break;
default:
- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
- WREG32(RADEON_MSI_REARM_EN, msi_rearm);
- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
break;
}
}
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 0c33ae9cf0f0..406632472c1b 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev)
struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
vmbus_close(dev->channel);
+ hid_hw_stop(input_dev->hid_device);
hid_destroy_device(input_dev->hid_device);
mousevsc_free_device(input_dev);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index b47e58b52d9f..acab74cde727 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
- power_supply_powers(&wdata->battery, &hdev->dev);
ret = power_supply_register(&hdev->dev, &wdata->battery);
if (ret) {
@@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev,
goto err_battery;
}
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
wdata->ac.properties = wacom_ac_props;
wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
wdata->ac.get_property = wacom_ac_get_property;
@@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev,
wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
wdata->ac.use_for_apm = 0;
- power_supply_powers(&wdata->battery, &hdev->dev);
-
ret = power_supply_register(&hdev->dev, &wdata->ac);
if (ret) {
hid_warn(hdev,
"can't create ac battery attribute, err: %d\n", ret);
goto err_ac;
}
+
+ power_supply_powers(&wdata->ac, &hdev->dev);
#endif
return 0;
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index fc253b472f9d..cac3589b1ed5 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
- power_supply_powers(&wdata->battery, &hdev->dev);
-
ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
if (ret) {
hid_err(hdev, "Cannot register battery device\n");
goto err_battery;
}
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = wiimote_leds_create(wdata);
if (ret)
goto err_free;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 7c297d305d5d..b1ec0e2aeb57 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid)
struct hiddev *hiddev = hid->hiddev;
struct usbhid_device *usbhid = hid->driver_data;
+ usb_deregister_dev(usbhid->intf, &hiddev_class);
+
mutex_lock(&hiddev->existancelock);
hiddev->exist = 0;
- usb_deregister_dev(usbhid->intf, &hiddev_class);
-
if (hiddev->open) {
mutex_unlock(&hiddev->existancelock);
usbhid_close(hiddev->hid);
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index eedf574ab539..f609b5727ba9 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -172,7 +172,7 @@ static inline void f75375_write8(struct i2c_client *client, u8 reg,
static inline void f75375_write16(struct i2c_client *client, u8 reg,
u16 value)
{
- int err = i2c_smbus_write_byte_data(client, reg, (value << 8));
+ int err = i2c_smbus_write_byte_data(client, reg, (value >> 8));
if (err)
return;
i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF));
@@ -200,9 +200,6 @@ static struct f75375_data *f75375_update_device(struct device *dev)
f75375_read16(client, F75375_REG_FAN_MIN(nr));
data->fan_target[nr] =
f75375_read16(client, F75375_REG_FAN_EXP(nr));
- data->pwm[nr] = f75375_read8(client,
- F75375_REG_FAN_PWM_DUTY(nr));
-
}
for (nr = 0; nr < 4; nr++) {
data->in_max[nr] =
@@ -218,6 +215,8 @@ static struct f75375_data *f75375_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated + 2 * HZ)
|| !data->valid) {
for (nr = 0; nr < 2; nr++) {
+ data->pwm[nr] = f75375_read8(client,
+ F75375_REG_FAN_PWM_DUTY(nr));
/* assign MSB, therefore shift it by 8 bits */
data->temp11[nr] =
f75375_read8(client, F75375_REG_TEMP(nr)) << 8;
@@ -369,7 +368,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
fanmode |= (3 << FAN_CTRL_MODE(nr));
break;
case 2: /* AUTOMATIC*/
- fanmode |= (2 << FAN_CTRL_MODE(nr));
+ fanmode |= (1 << FAN_CTRL_MODE(nr));
break;
case 3: /* fan speed */
break;
@@ -723,7 +722,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
if (data->kind == f75387) {
bool manu, duty;
- if (!(conf & (1 << F75387_FAN_CTRL_LINEAR(nr))))
+ if (!(mode & (1 << F75387_FAN_CTRL_LINEAR(nr))))
data->pwm_mode[nr] = 1;
manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 2dfae7d7cc5b..5276d1933dbc 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1920,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
fan4min = 0;
fan5pin = 0;
} else if (sio_data->kind == nct6776) {
- fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
- fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
- fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+ bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+ superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+ regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+ if (regval & 0x80)
+ fan3pin = gpok;
+ else
+ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+ if (regval & 0x40)
+ fan4pin = gpok;
+ else
+ fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+
+ if (regval & 0x20)
+ fan5pin = gpok;
+ else
+ fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+
fan4min = fan4pin;
} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
fan3pin = 1;
@@ -2337,11 +2354,6 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
for (i = 0; i < data->pwm_num; i++)
data->pwm_enable_orig[i] = data->pwm_enable[i];
- /* Read pwm data to save original values */
- w83627ehf_update_pwm_common(dev, data);
- for (i = 0; i < data->pwm_num; i++)
- data->pwm_enable_orig[i] = data->pwm_enable[i];
-
/* Register sysfs hooks */
for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) {
err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index f713eac55047..801df6000e9b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1018,7 +1018,7 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_release_region;
}
- match = of_match_device(omap_i2c_of_match, &pdev->dev);
+ match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
if (match) {
u32 freq = 100000; /* default to 100000 Hz */
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6381604696d3..0ab4a9548745 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -755,7 +755,7 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
- .remove = tegra_i2c_remove,
+ .remove = __devexit_p(tegra_i2c_remove),
#ifdef CONFIG_PM
.suspend = tegra_i2c_suspend,
.resume = tegra_i2c_resume,
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 7f879b2397b0..af8d016c37ea 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -116,4 +116,3 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o
obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o
-obj-$(CONFIG_BLK_DEV_IDE_AT91) += at91_ide.o
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
deleted file mode 100644
index 41d415529479..000000000000
--- a/drivers/ide/at91_ide.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller
- * with Compact Flash True IDE logic
- *
- * Copyright (c) 2008, 2009 Kelvatek 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.
- *
- * 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/clk.h>
-#include <linux/err.h>
-#include <linux/ide.h>
-#include <linux/platform_device.h>
-
-#include <mach/board.h>
-#include <asm/gpio.h>
-#include <mach/at91sam9_smc.h>
-
-#define DRV_NAME "at91_ide"
-
-#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args)
-#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args)
-
-/*
- * Access to IDE device is possible through EBI Static Memory Controller
- * with Compact Flash logic. For details see EBI and SMC datasheet sections
- * of any microcontroller from AT91SAM9 family.
- *
- * Within SMC chip select address space, lines A[23:21] distinguish Compact
- * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are:
- * 0x00c0000 - True IDE
- * 0x00e0000 - Alternate True IDE (Alt Status Register)
- *
- * On True IDE mode Task File and Data Register are mapped at the same address.
- * To distinguish access between these two different bus data width is used:
- * 8Bit for Task File, 16Bit for Data I/O.
- *
- * After initialization we do 8/16 bit flipping (changes in SMC MODE register)
- * only inside IDE callback routines which are serialized by IDE layer,
- * so no additional locking needed.
- */
-
-#define TASK_FILE 0x00c00000
-#define ALT_MODE 0x00e00000
-#define REGS_SIZE 8
-
-#define enter_16bit(cs, mode) do { \
- mode = at91_sys_read(AT91_SMC_MODE(cs)); \
- at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16); \
-} while (0)
-
-#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode);
-
-static void set_smc_timings(const u8 chipselect, const u16 cycle,
- const u16 setup, const u16 pulse,
- const u16 data_float, int use_iordy)
-{
- unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
- AT91_SMC_BAT_SELECT;
-
- /* disable or enable waiting for IORDY signal */
- if (use_iordy)
- mode |= AT91_SMC_EXNWMODE_READY;
-
- /* add data float cycles if needed */
- if (data_float)
- mode |= AT91_SMC_TDF_(data_float);
-
- at91_sys_write(AT91_SMC_MODE(chipselect), mode);
-
- /* setup timings in SMC */
- at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) |
- AT91_SMC_NCS_WRSETUP_(0) |
- AT91_SMC_NRDSETUP_(setup) |
- AT91_SMC_NCS_RDSETUP_(0));
- at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) |
- AT91_SMC_NCS_WRPULSE_(cycle) |
- AT91_SMC_NRDPULSE_(pulse) |
- AT91_SMC_NCS_RDPULSE_(cycle));
- at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) |
- AT91_SMC_NRDCYCLE_(cycle));
-}
-
-static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz)
-{
- u64 tmp = ns;
-
- tmp *= mck_hz;
- tmp += 1000*1000*1000 - 1; /* round up */
- do_div(tmp, 1000*1000*1000);
- return (unsigned int) tmp;
-}
-
-static void apply_timings(const u8 chipselect, const u8 pio,
- const struct ide_timing *timing, int use_iordy)
-{
- unsigned int t0, t1, t2, t6z;
- unsigned int cycle, setup, pulse, data_float;
- unsigned int mck_hz;
- struct clk *mck;
-
- /* see table 22 of Compact Flash standard 4.1 for the meaning,
- * we do not stretch active (t2) time, so setup (t1) + hold time (th)
- * assure at least minimal recovery (t2i) time */
- t0 = timing->cyc8b;
- t1 = timing->setup;
- t2 = timing->act8b;
- t6z = (pio < 5) ? 30 : 20;
-
- pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z);
-
- mck = clk_get(NULL, "mck");
- BUG_ON(IS_ERR(mck));
- mck_hz = clk_get_rate(mck);
- pdbg("mck_hz=%u\n", mck_hz);
-
- cycle = calc_mck_cycles(t0, mck_hz);
- setup = calc_mck_cycles(t1, mck_hz);
- pulse = calc_mck_cycles(t2, mck_hz);
- data_float = calc_mck_cycles(t6z, mck_hz);
-
- pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n",
- cycle, setup, pulse, data_float);
-
- set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy);
-}
-
-static void at91_ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- u8 chipselect = hwif->select_data;
- unsigned long mode;
-
- pdbg("cs %u buf %p len %d\n", chipselect, buf, len);
-
- len++;
-
- enter_16bit(chipselect, mode);
- readsw((void __iomem *)io_ports->data_addr, buf, len / 2);
- leave_16bit(chipselect, mode);
-}
-
-static void at91_ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- u8 chipselect = hwif->select_data;
- unsigned long mode;
-
- pdbg("cs %u buf %p len %d\n", chipselect, buf, len);
-
- enter_16bit(chipselect, mode);
- writesw((void __iomem *)io_ports->data_addr, buf, len / 2);
- leave_16bit(chipselect, mode);
-}
-
-static void at91_ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
-{
- struct ide_timing *timing;
- u8 chipselect = hwif->select_data;
- int use_iordy = 0;
- const u8 pio = drive->pio_mode - XFER_PIO_0;
-
- pdbg("chipselect %u pio %u\n", chipselect, pio);
-
- timing = ide_timing_find_mode(XFER_PIO_0 + pio);
- BUG_ON(!timing);
-
- if (ide_pio_need_iordy(drive, pio))
- use_iordy = 1;
-
- apply_timings(chipselect, pio, timing, use_iordy);
-}
-
-static const struct ide_tp_ops at91_ide_tp_ops = {
- .exec_command = ide_exec_command,
- .read_status = ide_read_status,
- .read_altstatus = ide_read_altstatus,
- .write_devctl = ide_write_devctl,
-
- .dev_select = ide_dev_select,
- .tf_load = ide_tf_load,
- .tf_read = ide_tf_read,
-
- .input_data = at91_ide_input_data,
- .output_data = at91_ide_output_data,
-};
-
-static const struct ide_port_ops at91_ide_port_ops = {
- .set_pio_mode = at91_ide_set_pio_mode,
-};
-
-static const struct ide_port_info at91_ide_port_info __initdata = {
- .port_ops = &at91_ide_port_ops,
- .tp_ops = &at91_ide_tp_ops,
- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE |
- IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS,
- .pio_mask = ATA_PIO6,
- .chipset = ide_generic,
-};
-
-/*
- * If interrupt is delivered through GPIO, IRQ are triggered on falling
- * and rising edge of signal. Whereas IDE device request interrupt on high
- * level (rising edge in our case). This mean we have fake interrupts, so
- * we need to check interrupt pin and exit instantly from ISR when line
- * is on low level.
- */
-
-irqreturn_t at91_irq_handler(int irq, void *dev_id)
-{
- int ntries = 8;
- int pin_val1, pin_val2;
-
- /* additional deglitch, line can be noisy in badly designed PCB */
- do {
- pin_val1 = at91_get_gpio_value(irq);
- pin_val2 = at91_get_gpio_value(irq);
- } while (pin_val1 != pin_val2 && --ntries > 0);
-
- if (pin_val1 == 0 || ntries <= 0)
- return IRQ_HANDLED;
-
- return ide_intr(irq, dev_id);
-}
-
-static int __init at91_ide_probe(struct platform_device *pdev)
-{
- int ret;
- struct ide_hw hw, *hws[] = { &hw };
- struct ide_host *host;
- struct resource *res;
- unsigned long tf_base = 0, ctl_base = 0;
- struct at91_cf_data *board = pdev->dev.platform_data;
-
- if (!board)
- return -ENODEV;
-
- if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) {
- perr("no device detected\n");
- return -ENODEV;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- perr("can't get memory resource\n");
- return -ENODEV;
- }
-
- if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE,
- REGS_SIZE, "ide") ||
- !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE,
- REGS_SIZE, "alt")) {
- perr("memory resources in use\n");
- return -EBUSY;
- }
-
- pdbg("chipselect %u irq %u res %08lx\n", board->chipselect,
- board->irq_pin, (unsigned long) res->start);
-
- tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE,
- REGS_SIZE);
- ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE,
- REGS_SIZE);
- if (!tf_base || !ctl_base) {
- perr("can't map memory regions\n");
- return -EBUSY;
- }
-
- memset(&hw, 0, sizeof(hw));
-
- if (board->flags & AT91_IDE_SWAP_A0_A2) {
- /* workaround for stupid hardware bug */
- hw.io_ports.data_addr = tf_base + 0;
- hw.io_ports.error_addr = tf_base + 4;
- hw.io_ports.nsect_addr = tf_base + 2;
- hw.io_ports.lbal_addr = tf_base + 6;
- hw.io_ports.lbam_addr = tf_base + 1;
- hw.io_ports.lbah_addr = tf_base + 5;
- hw.io_ports.device_addr = tf_base + 3;
- hw.io_ports.command_addr = tf_base + 7;
- hw.io_ports.ctl_addr = ctl_base + 3;
- } else
- ide_std_init_ports(&hw, tf_base, ctl_base + 6);
-
- hw.irq = board->irq_pin;
- hw.dev = &pdev->dev;
-
- host = ide_host_alloc(&at91_ide_port_info, hws, 1);
- if (!host) {
- perr("failed to allocate ide host\n");
- return -ENOMEM;
- }
-
- /* setup Static Memory Controller - PIO 0 as default */
- apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0);
-
- /* with GPIO interrupt we have to do quirks in handler */
- if (gpio_is_valid(board->irq_pin))
- host->irq_handler = at91_irq_handler;
-
- host->ports[0]->select_data = board->chipselect;
-
- ret = ide_host_register(host, &at91_ide_port_info, hws);
- if (ret) {
- perr("failed to register ide host\n");
- goto err_free_host;
- }
- platform_set_drvdata(pdev, host);
- return 0;
-
-err_free_host:
- ide_host_free(host);
- return ret;
-}
-
-static int __exit at91_ide_remove(struct platform_device *pdev)
-{
- struct ide_host *host = platform_get_drvdata(pdev);
-
- ide_host_remove(host);
- return 0;
-}
-
-static struct platform_driver at91_ide_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(at91_ide_remove),
-};
-
-static int __init at91_ide_init(void)
-{
- return platform_driver_probe(&at91_ide_driver, at91_ide_probe);
-}
-
-static void __exit at91_ide_exit(void)
-{
- platform_driver_unregister(&at91_ide_driver);
-}
-
-module_init(at91_ide_init);
-module_exit(at91_ide_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>");
-
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index b37b0c02a7b9..5034a87cc72d 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
return PTR_ERR(ctx);
if (cmd.conn_param.valid) {
- ctx->uid = cmd.uid;
ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+ mutex_lock(&file->mut);
ret = rdma_accept(ctx->cm_id, &conn_param);
+ if (!ret)
+ ctx->uid = cmd.uid;
+ mutex_unlock(&file->mut);
} else
ret = rdma_accept(ctx->cm_id, NULL);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index b930da4c0c63..4d27e4c3fe34 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
+ atomic_set(&qp->usecnt, 0);
atomic_inc(&pd->usecnt);
atomic_inc(&attr.send_cq->usecnt);
if (attr.recv_cq)
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 602b1bd723a9..575b78045aaf 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
qp->uobject = NULL;
qp->qp_type = qp_init_attr->qp_type;
+ atomic_set(&qp->usecnt, 0);
if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
qp->event_handler = __ib_shared_qp_event_handler;
qp->qp_context = qp;
@@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
qp->xrcd = qp_init_attr->xrcd;
atomic_inc(&qp_init_attr->xrcd->usecnt);
INIT_LIST_HEAD(&qp->open_list);
- atomic_set(&qp->usecnt, 0);
real_qp = qp;
qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index b7d4216db3c3..a4de9d58e9b4 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode,
error = ipathfs_mknod(parent->d_inode, *dentry,
mode, fops, data);
else
- error = PTR_ERR(dentry);
+ error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
return error;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 95c94d8f0254..259b0670b51c 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
return IB_MAD_RESULT_SUCCESS;
/*
- * Don't process SMInfo queries or vendor-specific
- * MADs -- the SMA can't handle them.
+ * Don't process SMInfo queries -- the SMA can't handle them.
*/
- if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
- ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
- IB_SMP_ATTR_VENDOR_MASK))
+ if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
return IB_MAD_RESULT_SUCCESS;
} else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 ||
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 7013da5e9eda..7140199f562e 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 568b4f11380a..c438e4691b3c 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 425065b36b8c..a4972abedef1 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
u8 *start_ptr = &start_addr;
u8 **start_buff = &start_ptr;
u16 buff_len = 0;
+ struct ietf_mpa_v1 *mpa_frame;
skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
@@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
/* send an MPA reject frame */
cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+ mpa_frame = (struct ietf_mpa_v1 *)*start_buff;
+ mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;
form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
cm_node->state = NES_CM_STATE_FIN_WAIT1;
@@ -1360,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
neigh->ha, ETH_ALEN)) {
/* Mac address same as in nes_arp_table */
- ip_rt_put(rt);
- return rc;
+ goto out;
}
nes_manage_arp_cache(nesvnic->netdev,
@@ -1377,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
neigh_event_send(neigh, NULL);
}
}
+
+out:
rcu_read_unlock();
ip_rt_put(rt);
return rc;
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index bdfa1fbb35fc..4646e6666087 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h
index b4393a16099d..a69eef16d72d 100644
--- a/drivers/infiniband/hw/nes/nes_context.h
+++ b/drivers/infiniband/hw/nes/nes_context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 055f4b545df0..d42c9f435b1b 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 0b590e152c6a..d748e4b31b8d 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index b3b2a240c6e9..3ba7be369452 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h
index 8c8af254555a..4f7f701c4a81 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.h
+++ b/drivers/infiniband/hw/nes/nes_mgt.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2010 Intel-NE, Inc. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 4b3fa711a247..f3a3ecf8d09e 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h
index 71e133ab209b..4926de744488 100644
--- a/drivers/infiniband/hw/nes/nes_user.h
+++ b/drivers/infiniband/hw/nes/nes_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index 8b4c2ff54888..e98f4fc0b768 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 5095bc41c6cc..0927b5cc65d3 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -3428,6 +3428,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
ib_wr->wr.fast_reg.length);
set_wqe_32bit_value(wqe->wqe_words,
+ NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
+ set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
ib_wr->wr.fast_reg.rkey);
/* Set page size: */
@@ -3724,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
entry->opcode = IB_WC_SEND;
break;
case NES_IWARP_SQ_OP_LOCINV:
- entry->opcode = IB_WR_LOCAL_INV;
+ entry->opcode = IB_WC_LOCAL_INV;
break;
case NES_IWARP_SQ_OP_FAST_REG:
entry->opcode = IB_WC_FAST_REG_MR;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index fe6b6e92fa90..0eff7c44d76b 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 4f18e2d332df..d0c64d514813 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd)
dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
dd->rcd[0]->rcvhdrq_size,
&dd->cspec->dummy_hdrq_phys,
- GFP_KERNEL | __GFP_COMP);
+ GFP_ATOMIC | __GFP_COMP);
if (!dd->cspec->dummy_hdrq) {
qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
/* fallback to just 0'ing */
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index f695061d688e..0fde788e1100 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
* BIOS may not set PCIe bus-utilization parameters for best performance.
* Check and optionally adjust them to maximize our throughput.
*/
-static int qib_pcie_caps = 0x51;
+static int qib_pcie_caps;
module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index b3cc1e062b17..86df632ea612 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -44,6 +44,7 @@
#include <linux/mutex.h>
#include <net/neighbour.h>
+#include <net/sch_generic.h>
#include <linux/atomic.h>
@@ -117,8 +118,9 @@ struct ipoib_header {
u16 reserved;
};
-struct ipoib_pseudoheader {
- u8 hwaddr[INFINIBAND_ALEN];
+struct ipoib_cb {
+ struct qdisc_skb_cb qdisc_cb;
+ u8 hwaddr[INFINIBAND_ALEN];
};
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 3514ca05deea..3974c290b667 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -653,7 +653,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct neighbour *n, struct n
}
static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
- struct ipoib_pseudoheader *phdr)
+ struct ipoib_cb *cb)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
@@ -661,17 +661,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
spin_lock_irqsave(&priv->lock, flags);
- path = __path_find(dev, phdr->hwaddr + 4);
+ path = __path_find(dev, cb->hwaddr + 4);
if (!path || !path->valid) {
int new_path = 0;
if (!path) {
- path = path_rec_create(dev, phdr->hwaddr + 4);
+ path = path_rec_create(dev, cb->hwaddr + 4);
new_path = 1;
}
if (path) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
if (!path->query && path_rec_start(dev, path)) {
@@ -695,12 +693,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
be16_to_cpu(path->pathrec.dlid));
spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
return;
} else if ((path->query || !path_rec_start(dev, path)) &&
skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
} else {
++dev->stats.tx_dropped;
@@ -774,16 +770,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
}
} else {
- struct ipoib_pseudoheader *phdr =
- (struct ipoib_pseudoheader *) skb->data;
- skb_pull(skb, sizeof *phdr);
+ struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
- if (phdr->hwaddr[4] == 0xff) {
+ if (cb->hwaddr[4] == 0xff) {
/* Add in the P_Key for multicast*/
- phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
- phdr->hwaddr[9] = priv->pkey & 0xff;
+ cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+ cb->hwaddr[9] = priv->pkey & 0xff;
- ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
+ ipoib_mcast_send(dev, cb->hwaddr + 4, skb);
} else {
/* unicast GID -- should be ARP or RARP reply */
@@ -792,14 +786,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
skb_dst(skb) ? "neigh" : "dst",
be16_to_cpup((__be16 *) skb->data),
- IPOIB_QPN(phdr->hwaddr),
- phdr->hwaddr + 4);
+ IPOIB_QPN(cb->hwaddr),
+ cb->hwaddr + 4);
dev_kfree_skb_any(skb);
++dev->stats.tx_dropped;
goto unlock;
}
- unicast_arp_send(skb, dev, phdr);
+ unicast_arp_send(skb, dev, cb);
}
}
unlock:
@@ -825,8 +819,6 @@ static int ipoib_hard_header(struct sk_buff *skb,
const void *daddr, const void *saddr, unsigned len)
{
struct ipoib_header *header;
- struct dst_entry *dst;
- struct neighbour *n;
header = (struct ipoib_header *) skb_push(skb, sizeof *header);
@@ -834,18 +826,13 @@ static int ipoib_hard_header(struct sk_buff *skb,
header->reserved = 0;
/*
- * If we don't have a neighbour structure, stuff the
- * destination address onto the front of the skb so we can
- * figure out where to send the packet later.
+ * If we don't have a dst_entry structure, stuff the
+ * destination address into skb->cb so we can figure out where
+ * to send the packet later.
*/
- dst = skb_dst(skb);
- n = NULL;
- if (dst)
- n = dst_get_neighbour_noref_raw(dst);
- if ((!dst || !n) && daddr) {
- struct ipoib_pseudoheader *phdr =
- (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
- memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+ if (!skb_dst(skb)) {
+ struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+ memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
}
return 0;
@@ -1021,11 +1008,7 @@ static void ipoib_setup(struct net_device *dev)
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- /*
- * We add in INFINIBAND_ALEN to allow for the destination
- * address "pseudoheader" for skbs without neighbour struct.
- */
- dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
+ dev->hard_header_len = IPOIB_ENCAP_LEN;
dev->addr_len = INFINIBAND_ALEN;
dev->type = ARPHRD_INFINIBAND;
dev->tx_queue_len = ipoib_sendq_size * 2;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index f7ff9dd66cda..20ebc6fd1bb9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -262,21 +262,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
- struct dst_entry *dst = skb_dst(skb);
- struct neighbour *n = NULL;
netif_tx_unlock_bh(dev);
skb->dev = dev;
- if (dst)
- n = dst_get_neighbour_noref_raw(dst);
- if (!dst || !n) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof (struct ipoib_pseudoheader));
- }
-
if (dev_queue_xmit(skb))
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
+
netif_tx_lock_bh(dev);
}
netif_tx_unlock_bh(dev);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index cd5d05e22a77..2b73d43cd691 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -69,8 +69,8 @@ MODULE_LICENSE("Dual BSD/GPL");
*/
static u64 srpt_service_guid;
-static spinlock_t srpt_dev_lock; /* Protects srpt_dev_list. */
-static struct list_head srpt_dev_list; /* List of srpt_device structures. */
+static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */
+static LIST_HEAD(srpt_dev_list); /* List of srpt_device structures. */
static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
module_param(srp_max_req_size, int, 0444);
@@ -687,6 +687,7 @@ err:
while (--i >= 0)
srpt_free_ioctx(sdev, ring[i], dma_size, dir);
kfree(ring);
+ ring = NULL;
out:
return ring;
}
@@ -2595,7 +2596,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
}
ch->sess = transport_init_session();
- if (!ch->sess) {
+ if (IS_ERR(ch->sess)) {
rej->reason = __constant_cpu_to_be32(
SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
pr_debug("Failed to create session\n");
@@ -3264,8 +3265,7 @@ static void srpt_add_one(struct ib_device *device)
for (i = 0; i < sdev->srq_size; ++i)
srpt_post_recv(sdev, sdev->ioctx_ring[i]);
- WARN_ON(sdev->device->phys_port_cnt
- > sizeof(sdev->port)/sizeof(sdev->port[0]));
+ WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port));
for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
sport = &sdev->port[i - 1];
@@ -4010,13 +4010,10 @@ static int __init srpt_init_module(void)
goto out;
}
- spin_lock_init(&srpt_dev_lock);
- INIT_LIST_HEAD(&srpt_dev_list);
-
- ret = -ENODEV;
srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
- if (!srpt_target) {
+ if (IS_ERR(srpt_target)) {
printk(KERN_ERR "couldn't register\n");
+ ret = PTR_ERR(srpt_target);
goto out;
}
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index b4b4bbcd7f16..61e52b830816 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -35,7 +35,6 @@
#ifndef IB_SRPT_H
#define IB_SRPT_H
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/wait.h>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 76457d50bc34..afc166fcc3d9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
- int retval;
+ int retval = 0;
if (count < input_event_size())
return -EINVAL;
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
index a588578037eb..67bec14e8b96 100644
--- a/drivers/input/keyboard/twl4030_keypad.c
+++ b/drivers/input/keyboard/twl4030_keypad.c
@@ -34,7 +34,6 @@
#include <linux/i2c/twl.h>
#include <linux/slab.h>
-
/*
* The TWL4030 family chips include a keypad controller that supports
* up to an 8x8 switch matrix. The controller can issue system wakeup
@@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)
return -EIO;
- /* Set timeout period to 100 ms */
+ /* Set timeout period to 200 ms */
i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)
return -EIO;
@@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("TWL4030 Keypad Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl4030_keypad");
-
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index b4cfc6c8be89..5ec774d6c82b 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
},
},
+ {
+ /* Lenovo Ideapad U455 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 8250299fd64f..4494233d331a 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
struct serio_raw_client *client = file->private_data;
struct serio_raw *serio_raw = client->serio_raw;
char uninitialized_var(c);
- ssize_t retval = 0;
+ ssize_t read = 0;
+ int retval;
if (serio_raw->dead)
return -ENODEV;
@@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
if (serio_raw->dead)
return -ENODEV;
- while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
- if (put_user(c, buffer++))
- return -EFAULT;
- retval++;
+ while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
+ if (put_user(c, buffer++)) {
+ retval = -EFAULT;
+ break;
+ }
+ read++;
}
- return retval;
+ return read ?: retval;
}
static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index cce1f03b8895..f75e0608be5b 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2863,6 +2863,9 @@ static unsigned device_dma_ops_init(void)
for_each_pci_dev(pdev) {
if (!check_device(&pdev->dev)) {
+
+ iommu_ignore_device(&pdev->dev);
+
unhandled += 1;
continue;
}
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 08a90b88e40d..cee307e86606 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -482,23 +482,19 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
priv = domain->priv;
- if (!priv) {
- ret = -ENODEV;
+ if (!priv)
goto fail;
- }
fl_table = priv->pgtable;
if (len != SZ_16M && len != SZ_1M &&
len != SZ_64K && len != SZ_4K) {
pr_debug("Bad length: %d\n", len);
- ret = -EINVAL;
goto fail;
}
if (!fl_table) {
pr_debug("Null page table\n");
- ret = -EINVAL;
goto fail;
}
@@ -507,7 +503,6 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
if (*fl_pte == 0) {
pr_debug("First level PTE is 0\n");
- ret = -ENODEV;
goto fail;
}
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 2339d7396b9e..802ab87a78b6 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1901,7 +1901,7 @@ static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
{
isdn_net_local *lp = netdev_priv(dev);
unsigned char *p;
- ushort len = 0;
+ int len = 0;
switch (lp->p_encap) {
case ISDN_NET_ENCAP_ETHER:
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 45e6878d7374..e59c166a0ce2 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -164,8 +164,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
if (drvdata->mode == LM3530_BL_MODE_ALS) {
if (pltfm->als_vmax == 0) {
- pltfm->als_vmin = als_vmin = 0;
- pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
+ pltfm->als_vmin = 0;
+ pltfm->als_vmax = LM3530_ALS_WINDOW_mV;
}
als_vmin = pltfm->als_vmin;
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 75049e765191..b026896206ca 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -710,7 +710,7 @@ static ssize_t adb_read(struct file *file, char __user *buf,
req = NULL;
spin_lock_irqsave(&state->lock, flags);
add_wait_queue(&state->wait_queue, &wait);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
for (;;) {
req = state->completed;
@@ -734,7 +734,7 @@ static ssize_t adb_read(struct file *file, char __user *buf,
spin_lock_irqsave(&state->lock, flags);
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&state->wait_queue, &wait);
spin_unlock_irqrestore(&state->lock, flags);
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index c2907d836e4e..86cb7e5d83d5 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -56,7 +56,8 @@ struct raid_dev {
struct raid_set {
struct dm_target *ti;
- uint64_t print_flags;
+ uint32_t bitmap_loaded;
+ uint32_t print_flags;
struct mddev md;
struct raid_type *raid_type;
@@ -1085,7 +1086,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,
raid_param_cnt += 2;
}
- raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2);
+ raid_param_cnt += (hweight32(rs->print_flags & ~DMPF_REBUILD) * 2);
if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))
raid_param_cnt--;
@@ -1197,7 +1198,12 @@ static void raid_resume(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
- bitmap_load(&rs->md);
+ if (!rs->bitmap_loaded) {
+ bitmap_load(&rs->md);
+ rs->bitmap_loaded = 1;
+ } else
+ md_wakeup_thread(rs->md.thread);
+
mddev_resume(&rs->md);
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9417ae2fa0bb..ce88755baf4a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7333,7 +7333,8 @@ void md_do_sync(struct mddev *mddev)
printk(KERN_INFO
"md: checkpointing %s of %s.\n",
desc, mdname(mddev));
- mddev->recovery_cp = mddev->curr_resync;
+ mddev->recovery_cp =
+ mddev->curr_resync_completed;
}
} else
mddev->recovery_cp = MaxSector;
@@ -7351,9 +7352,9 @@ void md_do_sync(struct mddev *mddev)
rcu_read_unlock();
}
}
+ skip:
set_bit(MD_CHANGE_DEVS, &mddev->flags);
- skip:
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
/* We completed so min/max setting can be forgotten if used. */
if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index cd13e9f2f5e6..f147395bac9a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -200,7 +200,7 @@ config MENELAUS
config TWL4030_CORE
bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
- depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
+ depends on I2C=y && GENERIC_HARDIRQS
help
Say yes here if you have TWL4030 / TWL6030 family chip on your board.
This core driver provides register access and IRQ handling
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e04e04ddc15e..8ce3959c6919 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -263,7 +263,9 @@ struct twl_client {
static struct twl_client twl_modules[TWL_NUM_SLAVES];
+#ifdef CONFIG_IRQ_DOMAIN
static struct irq_domain domain;
+#endif
/* mapping the module id to slave id and base address */
struct twl_mapping {
@@ -1226,13 +1228,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
pdata->irq_base = status;
pdata->irq_end = pdata->irq_base + nr_irqs;
+#ifdef CONFIG_IRQ_DOMAIN
domain.irq_base = pdata->irq_base;
domain.nr_irq = nr_irqs;
-#ifdef CONFIG_OF_IRQ
domain.of_node = of_node_get(node);
domain.ops = &irq_domain_simple_ops;
-#endif
irq_domain_add(&domain);
+#endif
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index d905f5171153..79ca33dfacca 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -124,7 +124,7 @@ static u8 res_config_addrs[] = {
[RES_MAIN_REF] = 0x94,
};
-static int __init twl4030_write_script_byte(u8 address, u8 byte)
+static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
{
int err;
@@ -138,7 +138,7 @@ out:
return err;
}
-static int __init twl4030_write_script_ins(u8 address, u16 pmb_message,
+static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
u8 delay, u8 next)
{
int err;
@@ -158,7 +158,7 @@ out:
return err;
}
-static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
+static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,
int len)
{
int err;
@@ -183,7 +183,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
return err;
}
-static int __init twl4030_config_wakeup3_sequence(u8 address)
+static int __devinit twl4030_config_wakeup3_sequence(u8 address)
{
int err;
u8 data;
@@ -208,7 +208,7 @@ out:
return err;
}
-static int __init twl4030_config_wakeup12_sequence(u8 address)
+static int __devinit twl4030_config_wakeup12_sequence(u8 address)
{
int err = 0;
u8 data;
@@ -262,7 +262,7 @@ out:
return err;
}
-static int __init twl4030_config_sleep_sequence(u8 address)
+static int __devinit twl4030_config_sleep_sequence(u8 address)
{
int err;
@@ -276,7 +276,7 @@ static int __init twl4030_config_sleep_sequence(u8 address)
return err;
}
-static int __init twl4030_config_warmreset_sequence(u8 address)
+static int __devinit twl4030_config_warmreset_sequence(u8 address)
{
int err;
u8 rd_data;
@@ -324,7 +324,7 @@ out:
return err;
}
-static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
+static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)
{
int rconfig_addr;
int err;
@@ -416,7 +416,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
return 0;
}
-static int __init load_twl4030_script(struct twl4030_script *tscript,
+static int __devinit load_twl4030_script(struct twl4030_script *tscript,
u8 address)
{
int err;
@@ -527,7 +527,7 @@ void twl4030_power_off(void)
pr_err("TWL4030 Unable to power off\n");
}
-void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
int i;
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index dda86293dc9f..b2d8e512d3cb 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* Default PLL configuration after power up */
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
twl6040->sysclk = 19200000;
+ twl6040->mclk = 32768;
} else {
/* already powered-down */
if (!twl6040->power_count) {
@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
twl6040_power_down(twl6040);
}
twl6040->sysclk = 0;
+ twl6040->mclk = 0;
}
out:
@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+ /* Force full reconfiguration when switching between PLL */
+ if (pll_id != twl6040->pll) {
+ twl6040->sysclk = 0;
+ twl6040->mclk = 0;
+ }
+
switch (pll_id) {
case TWL6040_SYSCLK_SEL_LPPLL:
/* low-power PLL divider */
- switch (freq_out) {
- case 17640000:
- lppllctl |= TWL6040_LPLLFIN;
- break;
- case 19200000:
- lppllctl &= ~TWL6040_LPLLFIN;
- break;
- default:
- dev_err(twl6040->dev,
- "freq_out %d not supported\n", freq_out);
- ret = -EINVAL;
- goto pll_out;
+ /* Change the sysclk configuration only if it has been canged */
+ if (twl6040->sysclk != freq_out) {
+ switch (freq_out) {
+ case 17640000:
+ lppllctl |= TWL6040_LPLLFIN;
+ break;
+ case 19200000:
+ lppllctl &= ~TWL6040_LPLLFIN;
+ break;
+ default:
+ dev_err(twl6040->dev,
+ "freq_out %d not supported\n",
+ freq_out);
+ ret = -EINVAL;
+ goto pll_out;
+ }
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+ lppllctl);
}
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+ /* The PLL in use has not been change, we can exit */
+ if (twl6040->pll == pll_id)
+ break;
switch (freq_in) {
case 32768:
@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
goto pll_out;
}
- hppllctl &= ~TWL6040_MCLK_MSK;
+ if (twl6040->mclk != freq_in) {
+ hppllctl &= ~TWL6040_MCLK_MSK;
+
+ switch (freq_in) {
+ case 12000000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_12000KHZ |
+ TWL6040_HPLLENA;
+ break;
+ case 19200000:
+ /*
+ * PLL disabled
+ * (enable PLL if MCLK jitter quality
+ * doesn't meet specification)
+ */
+ hppllctl |= TWL6040_MCLK_19200KHZ;
+ break;
+ case 26000000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_26000KHZ |
+ TWL6040_HPLLENA;
+ break;
+ case 38400000:
+ /* PLL enabled, active mode */
+ hppllctl |= TWL6040_MCLK_38400KHZ |
+ TWL6040_HPLLENA;
+ break;
+ default:
+ dev_err(twl6040->dev,
+ "freq_in %d not supported\n", freq_in);
+ ret = -EINVAL;
+ goto pll_out;
+ }
- switch (freq_in) {
- case 12000000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_12000KHZ |
- TWL6040_HPLLENA;
- break;
- case 19200000:
/*
- * PLL disabled
- * (enable PLL if MCLK jitter quality
- * doesn't meet specification)
+ * enable clock slicer to ensure input waveform is
+ * square
*/
- hppllctl |= TWL6040_MCLK_19200KHZ;
- break;
- case 26000000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_26000KHZ |
- TWL6040_HPLLENA;
- break;
- case 38400000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_38400KHZ |
- TWL6040_HPLLENA;
- break;
- default:
- dev_err(twl6040->dev,
- "freq_in %d not supported\n", freq_in);
- ret = -EINVAL;
- goto pll_out;
- }
+ hppllctl |= TWL6040_HPLLSQRENA;
- /* enable clock slicer to ensure input waveform is square */
- hppllctl |= TWL6040_HPLLSQRENA;
-
- twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
- usleep_range(500, 700);
- lppllctl |= TWL6040_HPLLSEL;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+ twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+ hppllctl);
+ usleep_range(500, 700);
+ lppllctl |= TWL6040_HPLLSEL;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+ lppllctl);
+ lppllctl &= ~TWL6040_LPLLENA;
+ twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+ lppllctl);
+ }
break;
default:
dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
@@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
}
twl6040->sysclk = freq_out;
+ twl6040->mclk = freq_in;
twl6040->pll = pll_id;
pll_out:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6a1a092db146..c7795096d43b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,24 +2,14 @@
# Misc strange devices
#
-# This one has to live outside of the MISC_DEVICES conditional,
-# because it may be selected by drivers/platform/x86/hp_accel.
+menu "Misc devices"
+
config SENSORS_LIS3LV02D
tristate
depends on INPUT
select INPUT_POLLDEV
default n
-menuconfig MISC_DEVICES
- bool "Misc devices"
- ---help---
- Say Y here to get to see options for device drivers from various
- different categories. This option alone does not add any kernel code.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if MISC_DEVICES
-
config AD525X_DPOT
tristate "Analog Devices Digital Potentiometers"
depends on (I2C || SPI) && SYSFS
@@ -516,5 +506,4 @@ source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
-
-endif # MISC_DEVICES
+endmenu
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
index 778fc3fdfb9b..5484301d57d9 100644
--- a/drivers/misc/c2port/c2port-duramar2150.c
+++ b/drivers/misc/c2port/c2port-duramar2150.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/ioport.h>
#include <linux/c2port.h>
#define DATA_PORT 0x325
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index 68cd05b6d829..85cc7710193c 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -245,6 +245,7 @@ static int __devinit cb710_probe(struct pci_dev *pdev,
if (err)
return err;
+ spin_lock_init(&chip->irq_lock);
chip->pdev = pdev;
chip->iobase = pcim_iomap_table(pdev)[0];
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index bc685bfc4c33..87a390de054c 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -262,7 +262,7 @@ static void __init reset_all_timers(void)
* In other cases (such as with VSAless OpenFirmware), the system firmware
* leaves timers available for us to use.
*/
-static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
{
struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
unsigned long flags;
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 150cd7061b80..28adefe70f96 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which)
static void lkdtm_handler(void)
{
unsigned long flags;
+ bool do_it = false;
spin_lock_irqsave(&count_lock, flags);
count--;
@@ -361,10 +362,13 @@ static void lkdtm_handler(void)
cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
if (count == 0) {
- lkdtm_do_action(cptype);
+ do_it = true;
count = cpoint_count;
}
spin_unlock_irqrestore(&count_lock, flags);
+
+ if (do_it)
+ lkdtm_do_action(cptype);
}
static int lkdtm_register_cpoint(enum cname which)
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index cd41d403c9df..cb56e270da11 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -314,7 +314,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
* fear that guest will need it. Host may reject some pages, we need to
* check the return value and maybe submit a different page.
*/
-static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
+static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
unsigned int *hv_status)
{
unsigned long status, dummy;
@@ -322,17 +322,17 @@ static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
pfn32 = (u32)pfn;
if (pfn32 != pfn)
- return false;
+ return -1;
STATS_INC(b->stats.lock);
*hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);
if (vmballoon_check_status(b, status))
- return true;
+ return 0;
pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
STATS_INC(b->stats.lock_fail);
- return false;
+ return 1;
}
/*
@@ -411,7 +411,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
struct page *page;
gfp_t flags;
unsigned int hv_status;
- bool locked = false;
+ int locked;
flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
do {
@@ -431,7 +431,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
/* inform monitor */
locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
- if (!locked) {
+ if (locked > 0) {
STATS_INC(b->stats.refused_alloc);
if (hv_status == VMW_BALLOON_ERROR_RESET ||
@@ -449,7 +449,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
return -EIO;
}
- } while (!locked);
+ } while (locked != 0);
/* track allocated page */
list_add(&page->lru, &b->pages);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 0cad48a284a8..c6a383d0244d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1694,6 +1694,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
md->power_ro_lock.show = power_ro_lock_show;
md->power_ro_lock.store = power_ro_lock_store;
+ sysfs_attr_init(&md->power_ro_lock.attr);
md->power_ro_lock.attr.mode = mode;
md->power_ro_lock.attr.name =
"ro_lock_until_next_power_on";
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f545a3e6eb80..690255c7d4dc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -290,8 +290,11 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
bool is_first_req)
{
- if (host->ops->pre_req)
+ if (host->ops->pre_req) {
+ mmc_host_clk_hold(host);
host->ops->pre_req(host, mrq, is_first_req);
+ mmc_host_clk_release(host);
+ }
}
/**
@@ -306,8 +309,11 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
int err)
{
- if (host->ops->post_req)
+ if (host->ops->post_req) {
+ mmc_host_clk_hold(host);
host->ops->post_req(host, mrq, err);
+ mmc_host_clk_release(host);
+ }
}
/**
@@ -620,7 +626,9 @@ int mmc_host_enable(struct mmc_host *host)
int err;
host->en_dis_recurs = 1;
+ mmc_host_clk_hold(host);
err = host->ops->enable(host);
+ mmc_host_clk_release(host);
host->en_dis_recurs = 0;
if (err) {
@@ -640,7 +648,9 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy)
int err;
host->en_dis_recurs = 1;
+ mmc_host_clk_hold(host);
err = host->ops->disable(host, lazy);
+ mmc_host_clk_release(host);
host->en_dis_recurs = 0;
if (err < 0) {
@@ -1121,6 +1131,10 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
* might not allow this operation
*/
voltage = regulator_get_voltage(supply);
+
+ if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE)
+ min_uV = max_uV = voltage;
+
if (voltage < 0)
result = voltage;
else if (voltage < min_uV || voltage > max_uV)
@@ -1203,8 +1217,11 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
host->ios.signal_voltage = signal_voltage;
- if (host->ops->start_signal_voltage_switch)
+ if (host->ops->start_signal_voltage_switch) {
+ mmc_host_clk_hold(host);
err = host->ops->start_signal_voltage_switch(host, &host->ios);
+ mmc_host_clk_release(host);
+ }
return err;
}
@@ -1239,6 +1256,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
int err = 0;
card = host->card;
+ mmc_claim_host(host);
/*
* Send power notify command only if card
@@ -1269,6 +1287,7 @@ static void mmc_poweroff_notify(struct mmc_host *host)
/* Set the card state to no notification after the poweroff */
card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
}
+ mmc_release_host(host);
}
/*
@@ -1327,12 +1346,28 @@ static void mmc_power_up(struct mmc_host *host)
void mmc_power_off(struct mmc_host *host)
{
+ int err = 0;
mmc_host_clk_hold(host);
host->ios.clock = 0;
host->ios.vdd = 0;
- mmc_poweroff_notify(host);
+ /*
+ * For eMMC 4.5 device send AWAKE command before
+ * POWER_OFF_NOTIFY command, because in sleep state
+ * eMMC 4.5 devices respond to only RESET and AWAKE cmd
+ */
+ if (host->card && mmc_card_is_sleep(host->card) &&
+ host->bus_ops->resume) {
+ err = host->bus_ops->resume(host);
+
+ if (!err)
+ mmc_poweroff_notify(host);
+ else
+ pr_warning("%s: error %d during resume "
+ "(continue with poweroff sequence)\n",
+ mmc_hostname(host), err);
+ }
/*
* Reset ocr mask to be the highest possible voltage supported for
@@ -2386,12 +2421,6 @@ int mmc_suspend_host(struct mmc_host *host)
*/
if (mmc_try_claim_host(host)) {
if (host->bus_ops->suspend) {
- /*
- * For eMMC 4.5 device send notify command
- * before sleep, because in sleep state eMMC 4.5
- * devices respond to only RESET and AWAKE cmd
- */
- mmc_poweroff_notify(host);
err = host->bus_ops->suspend(host);
}
mmc_do_release_host(host);
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index fb8a5cd2e4a1..08a7852ade44 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -14,27 +14,6 @@
int mmc_register_host_class(void);
void mmc_unregister_host_class(void);
-
-#ifdef CONFIG_MMC_CLKGATE
-void mmc_host_clk_hold(struct mmc_host *host);
-void mmc_host_clk_release(struct mmc_host *host);
-unsigned int mmc_host_clk_rate(struct mmc_host *host);
-
-#else
-static inline void mmc_host_clk_hold(struct mmc_host *host)
-{
-}
-
-static inline void mmc_host_clk_release(struct mmc_host *host)
-{
-}
-
-static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
-{
- return host->ios.clock;
-}
-#endif
-
void mmc_host_deeper_disable(struct work_struct *work);
#endif
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 59b9ba52e66a..a48066344fa8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -376,7 +376,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
}
card->ext_csd.raw_hc_erase_gap_size =
- ext_csd[EXT_CSD_PARTITION_ATTRIBUTE];
+ ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
card->ext_csd.raw_sec_trim_mult =
ext_csd[EXT_CSD_SEC_TRIM_MULT];
card->ext_csd.raw_sec_erase_mult =
@@ -551,7 +551,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
goto out;
/* only compare read only fields */
- err = (!(card->ext_csd.raw_partition_support ==
+ err = !((card->ext_csd.raw_partition_support ==
bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
(card->ext_csd.raw_erased_mem_count ==
bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) &&
@@ -1006,7 +1006,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_hs200(card);
else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1, 0);
+ EXT_CSD_HS_TIMING, 1,
+ card->ext_csd.generic_cmd6_time);
if (err && err != -EBADMSG)
goto free_card;
@@ -1116,7 +1117,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* Activate wide bus and DDR (if supported).
*/
if (!mmc_card_hs200(card) &&
- (card->csd.mmca_vsn >= CSD_SPEC_VER_3) &&
+ (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
static unsigned ext_csd_bits[][2] = {
{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
@@ -1315,11 +1316,13 @@ static int mmc_suspend(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
- if (mmc_card_can_sleep(host))
+ if (mmc_card_can_sleep(host)) {
err = mmc_card_sleep(host);
- else if (!mmc_host_is_spi(host))
+ if (!err)
+ mmc_card_set_sleep(host->card);
+ } else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
- host->card->state &= ~MMC_STATE_HIGHSPEED;
+ host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
mmc_release_host(host);
return err;
@@ -1339,7 +1342,11 @@ static int mmc_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
- err = mmc_init_card(host, host->ocr, host->card);
+ if (mmc_card_is_sleep(host->card)) {
+ err = mmc_card_awake(host);
+ mmc_card_clr_sleep(host->card);
+ } else
+ err = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
return err;
@@ -1349,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host)
{
int ret;
- host->card->state &= ~MMC_STATE_HIGHSPEED;
+ host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+ mmc_card_clr_sleep(host->card);
mmc_claim_host(host);
ret = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c63ad03c29c7..5017f9354ce2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -451,9 +451,11 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
* information and let the hardware specific code
* return what is possible given the options
*/
+ mmc_host_clk_hold(card->host);
drive_strength = card->host->ops->select_drive_strength(
card->sw_caps.uhs_max_dtr,
host_drv_type, card_drv_type);
+ mmc_host_clk_release(card->host);
err = mmc_sd_switch(card, 1, 2, drive_strength, status);
if (err)
@@ -660,9 +662,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
goto out;
/* SPI mode doesn't define CMD19 */
- if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
+ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
+ mmc_host_clk_hold(card->host);
err = card->host->ops->execute_tuning(card->host,
MMC_SEND_TUNING_BLOCK);
+ mmc_host_clk_release(card->host);
+ }
out:
kfree(status);
@@ -850,8 +855,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
if (!reinit) {
int ro = -1;
- if (host->ops->get_ro)
+ if (host->ops->get_ro) {
+ mmc_host_clk_hold(card->host);
ro = host->ops->get_ro(host);
+ mmc_host_clk_release(card->host);
+ }
if (ro < 0) {
pr_warning("%s: host does not "
@@ -967,8 +975,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
* Since initialization is now complete, enable preset
* value registers for UHS-I cards.
*/
- if (host->ops->enable_preset_value)
+ if (host->ops->enable_preset_value) {
+ mmc_host_clk_hold(card->host);
host->ops->enable_preset_value(host, true);
+ mmc_host_clk_release(card->host);
+ }
} else {
/*
* Attempt to change to high-speed (if supported)
@@ -1151,8 +1162,11 @@ int mmc_attach_sd(struct mmc_host *host)
return err;
/* Disable preset value enable if already set since last time */
- if (host->ops->enable_preset_value)
+ if (host->ops->enable_preset_value) {
+ mmc_host_clk_hold(host);
host->ops->enable_preset_value(host, false);
+ mmc_host_clk_release(host);
+ }
err = mmc_send_app_op_cond(host, 0, &ocr);
if (err)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index bd7bacc950dc..12cde6ee17f5 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -98,10 +98,11 @@ fail:
return ret;
}
-static int sdio_read_cccr(struct mmc_card *card)
+static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
{
int ret;
int cccr_vsn;
+ int uhs = ocr & R4_18V_PRESENT;
unsigned char data;
unsigned char speed;
@@ -149,7 +150,7 @@ static int sdio_read_cccr(struct mmc_card *card)
card->scr.sda_spec3 = 0;
card->sw_caps.sd3_bus_mode = 0;
card->sw_caps.sd3_drv_type = 0;
- if (cccr_vsn >= SDIO_CCCR_REV_3_00) {
+ if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) {
card->scr.sda_spec3 = 1;
ret = mmc_io_rw_direct(card, 0, 0,
SDIO_CCCR_UHS, 0, &data);
@@ -712,7 +713,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/*
* Read the common registers.
*/
- err = sdio_read_cccr(card);
+ err = sdio_read_cccr(card, ocr);
if (err)
goto remove;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 68f81b9ee0fb..f573e7f9f740 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -146,15 +146,21 @@ static int sdio_irq_thread(void *_host)
}
set_current_state(TASK_INTERRUPTIBLE);
- if (host->caps & MMC_CAP_SDIO_IRQ)
+ if (host->caps & MMC_CAP_SDIO_IRQ) {
+ mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 1);
+ mmc_host_clk_release(host);
+ }
if (!kthread_should_stop())
schedule_timeout(period);
set_current_state(TASK_RUNNING);
} while (!kthread_should_stop());
- if (host->caps & MMC_CAP_SDIO_IRQ)
+ if (host->caps & MMC_CAP_SDIO_IRQ) {
+ mmc_host_clk_hold(host);
host->ops->enable_sdio_irq(host, 0);
+ mmc_host_clk_release(host);
+ }
pr_debug("%s: IRQ thread exiting with code %d\n",
mmc_hostname(host), ret);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index cf444b0ca2cc..00fcbed1afd2 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -477,7 +477,6 @@ config MMC_SDHI
config MMC_CB710
tristate "ENE CB710 MMC/SD Interface support"
depends on PCI
- select MISC_DEVICES
select CB710_CORE
help
This option enables support for MMC/SD part of ENE CB710/720 Flash
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index fcfe1eb5acc8..6985cdb0bb26 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -969,11 +969,14 @@ static void atmci_start_request(struct atmel_mci *host,
host->data_status = 0;
if (host->need_reset) {
+ iflags = atmci_readl(host, ATMCI_IMR);
+ iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB);
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
atmci_writel(host, ATMCI_MR, host->mode_reg);
if (host->caps.has_cfg_reg)
atmci_writel(host, ATMCI_CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_IER, iflags);
host->need_reset = false;
}
atmci_writel(host, ATMCI_SDCR, slot->sdc_reg);
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 0e342793ff14..8bec1c36b159 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -22,7 +22,6 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/scatterlist.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/stat.h>
@@ -502,8 +501,14 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
host->dir_status = DW_MCI_SEND_STATUS;
if (dw_mci_submit_data_dma(host, data)) {
+ int flags = SG_MITER_ATOMIC;
+ if (host->data->flags & MMC_DATA_READ)
+ flags |= SG_MITER_TO_SG;
+ else
+ flags |= SG_MITER_FROM_SG;
+
+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
host->sg = data->sg;
- host->pio_offset = 0;
host->part_buf_start = 0;
host->part_buf_count = 0;
@@ -972,6 +977,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
* generates a block interrupt, hence setting
* the scatter-gather pointer to NULL.
*/
+ sg_miter_stop(&host->sg_miter);
host->sg = NULL;
ctrl = mci_readl(host, CTRL);
ctrl |= SDMMC_CTRL_FIFO_RESET;
@@ -1311,54 +1317,44 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
static void dw_mci_read_data_pio(struct dw_mci *host)
{
- struct scatterlist *sg = host->sg;
- void *buf = sg_virt(sg);
- unsigned int offset = host->pio_offset;
+ struct sg_mapping_iter *sg_miter = &host->sg_miter;
+ void *buf;
+ unsigned int offset;
struct mmc_data *data = host->data;
int shift = host->data_shift;
u32 status;
unsigned int nbytes = 0, len;
+ unsigned int remain, fcnt;
do {
- len = host->part_buf_count +
- (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
- if (offset + len <= sg->length) {
+ if (!sg_miter_next(sg_miter))
+ goto done;
+
+ host->sg = sg_miter->__sg;
+ buf = sg_miter->addr;
+ remain = sg_miter->length;
+ offset = 0;
+
+ do {
+ fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS))
+ << shift) + host->part_buf_count;
+ len = min(remain, fcnt);
+ if (!len)
+ break;
dw_mci_pull_data(host, (void *)(buf + offset), len);
-
offset += len;
nbytes += len;
-
- if (offset == sg->length) {
- flush_dcache_page(sg_page(sg));
- host->sg = sg = sg_next(sg);
- if (!sg)
- goto done;
-
- offset = 0;
- buf = sg_virt(sg);
- }
- } else {
- unsigned int remaining = sg->length - offset;
- dw_mci_pull_data(host, (void *)(buf + offset),
- remaining);
- nbytes += remaining;
-
- flush_dcache_page(sg_page(sg));
- host->sg = sg = sg_next(sg);
- if (!sg)
- goto done;
-
- offset = len - remaining;
- buf = sg_virt(sg);
- dw_mci_pull_data(host, buf, offset);
- nbytes += offset;
- }
+ remain -= len;
+ } while (remain);
+ sg_miter->consumed = offset;
status = mci_readl(host, MINTSTS);
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
if (status & DW_MCI_DATA_ERROR_FLAGS) {
host->data_status = status;
data->bytes_xfered += nbytes;
+ sg_miter_stop(sg_miter);
+ host->sg = NULL;
smp_wmb();
set_bit(EVENT_DATA_ERROR, &host->pending_events);
@@ -1367,65 +1363,66 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
return;
}
} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
- host->pio_offset = offset;
data->bytes_xfered += nbytes;
+
+ if (!remain) {
+ if (!sg_miter_next(sg_miter))
+ goto done;
+ sg_miter->consumed = 0;
+ }
+ sg_miter_stop(sg_miter);
return;
done:
data->bytes_xfered += nbytes;
+ sg_miter_stop(sg_miter);
+ host->sg = NULL;
smp_wmb();
set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
}
static void dw_mci_write_data_pio(struct dw_mci *host)
{
- struct scatterlist *sg = host->sg;
- void *buf = sg_virt(sg);
- unsigned int offset = host->pio_offset;
+ struct sg_mapping_iter *sg_miter = &host->sg_miter;
+ void *buf;
+ unsigned int offset;
struct mmc_data *data = host->data;
int shift = host->data_shift;
u32 status;
unsigned int nbytes = 0, len;
+ unsigned int fifo_depth = host->fifo_depth;
+ unsigned int remain, fcnt;
do {
- len = ((host->fifo_depth -
- SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift)
- - host->part_buf_count;
- if (offset + len <= sg->length) {
+ if (!sg_miter_next(sg_miter))
+ goto done;
+
+ host->sg = sg_miter->__sg;
+ buf = sg_miter->addr;
+ remain = sg_miter->length;
+ offset = 0;
+
+ do {
+ fcnt = ((fifo_depth -
+ SDMMC_GET_FCNT(mci_readl(host, STATUS)))
+ << shift) - host->part_buf_count;
+ len = min(remain, fcnt);
+ if (!len)
+ break;
host->push_data(host, (void *)(buf + offset), len);
-
offset += len;
nbytes += len;
- if (offset == sg->length) {
- host->sg = sg = sg_next(sg);
- if (!sg)
- goto done;
-
- offset = 0;
- buf = sg_virt(sg);
- }
- } else {
- unsigned int remaining = sg->length - offset;
-
- host->push_data(host, (void *)(buf + offset),
- remaining);
- nbytes += remaining;
-
- host->sg = sg = sg_next(sg);
- if (!sg)
- goto done;
-
- offset = len - remaining;
- buf = sg_virt(sg);
- host->push_data(host, (void *)buf, offset);
- nbytes += offset;
- }
+ remain -= len;
+ } while (remain);
+ sg_miter->consumed = offset;
status = mci_readl(host, MINTSTS);
mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
if (status & DW_MCI_DATA_ERROR_FLAGS) {
host->data_status = status;
data->bytes_xfered += nbytes;
+ sg_miter_stop(sg_miter);
+ host->sg = NULL;
smp_wmb();
@@ -1435,12 +1432,20 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
return;
}
} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
- host->pio_offset = offset;
data->bytes_xfered += nbytes;
+
+ if (!remain) {
+ if (!sg_miter_next(sg_miter))
+ goto done;
+ sg_miter->consumed = 0;
+ }
+ sg_miter_stop(sg_miter);
return;
done:
data->bytes_xfered += nbytes;
+ sg_miter_stop(sg_miter);
+ host->sg = NULL;
smp_wmb();
set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
}
@@ -1643,6 +1648,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
* block interrupt, hence setting the
* scatter-gather pointer to NULL.
*/
+ sg_miter_stop(&host->sg_miter);
host->sg = NULL;
ctrl = mci_readl(host, CTRL);
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index ab66f2454dc4..1534b582c419 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -113,8 +113,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
const int j = i * 2;
u32 mask;
- mask = mmc_vddrange_to_ocrmask(voltage_ranges[j],
- voltage_ranges[j + 1]);
+ mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
+ be32_to_cpu(voltage_ranges[j + 1]));
if (!mask) {
ret = -EINVAL;
dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ff4adc018041..5d876ff86f37 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -38,6 +38,23 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
int base = reg & ~0x3;
int shift = (reg & 0x3) * 8;
u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
+
+ /*
+ * "DMA select" locates at offset 0x28 in SD specification, but on
+ * P5020 or P3041, it locates at 0x29.
+ */
+ if (reg == SDHCI_HOST_CONTROL) {
+ u32 dma_bits;
+
+ dma_bits = in_be32(host->ioaddr + reg);
+ /* DMA select is 22,23 bits in Protocol Control Register */
+ dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK;
+
+ /* fixup the result */
+ ret &= ~SDHCI_CTRL_DMA_MASK;
+ ret |= dma_bits;
+ }
+
return ret;
}
@@ -56,6 +73,21 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
{
+ /*
+ * "DMA select" location is offset 0x28 in SD specification, but on
+ * P5020 or P3041, it's located at 0x29.
+ */
+ if (reg == SDHCI_HOST_CONTROL) {
+ u32 dma_bits;
+
+ /* DMA select is 22,23 bits in Protocol Control Register */
+ dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5;
+ clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5,
+ dma_bits);
+ val &= ~SDHCI_CTRL_DMA_MASK;
+ val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK;
+ }
+
/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
if (reg == SDHCI_HOST_CONTROL)
val &= ~ESDHC_HOST_CONTROL_RES;
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 7165e6a09274..6ebdc4010e7c 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -250,7 +250,7 @@ static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot)
{
- slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD;
+ slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
return 0;
}
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 03970bcb3495..c5c2a48bdd94 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -2,7 +2,7 @@
* sdhci-pltfm.c Support for SDHCI platform devices
* Copyright (c) 2009 Intel Corporation
*
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc.
* Copyright (c) 2009 MontaVista Software, Inc.
*
* Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -71,6 +71,14 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (sdhci_of_wp_inverted(np))
host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+ if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
+ host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+
+ if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
+ of_device_is_compatible(np, "fsl,p1010-esdhc") ||
+ of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk)
pltfm_host->clock = be32_to_cpup(clk);
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index f5d8b53be333..352d4797865b 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
if (ret < 0)
goto clean_up2;
- mmc_add_host(mmc);
+ INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
}
ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
if (ret) {
- free_irq(irq[0], host);
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
- goto clean_up3;
+ goto clean_up4;
}
- INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
-
- mmc_detect_change(host->mmc, 0);
+ ret = mmc_add_host(mmc);
+ if (ret < 0)
+ goto clean_up5;
dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
dev_dbg(&pdev->dev, "chip ver H'%04x\n",
sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
return ret;
+clean_up5:
+ free_irq(irq[1], host);
+clean_up4:
+ free_irq(irq[0], host);
clean_up3:
- mmc_remove_host(mmc);
pm_runtime_suspend(&pdev->dev);
clean_up2:
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index a95e6d901726..f96c536d130a 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -20,8 +20,8 @@
#include <linux/mmc/tmio.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
-#include <linux/spinlock.h>
#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
/* Definitions for values the CTRL_SDIO_STATUS register can take. */
#define TMIO_SDIO_STAT_IOIRQ 0x0001
@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+void tmio_mmc_abort_dma(struct tmio_mmc_host *host);
#else
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{
}
+
+static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
+{
+}
#endif
#ifdef CONFIG_PM
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 7a6e6cc8f8b8..8253ec12003e 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
#endif
}
+void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
+{
+ tmio_mmc_enable_dma(host, false);
+
+ if (host->chan_rx)
+ dmaengine_terminate_all(host->chan_rx);
+ if (host->chan_tx)
+ dmaengine_terminate_all(host->chan_tx);
+
+ tmio_mmc_enable_dma(host, true);
+}
+
static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
{
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index abad01b37cfb..5f9ad74fbf80 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -41,8 +41,8 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
-#include <linux/workqueue.h>
#include <linux/spinlock.h>
+#include <linux/workqueue.h>
#include "tmio_mmc.h"
@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
/* Ready for new calls */
host->mrq = NULL;
+ tmio_mmc_abort_dma(host);
mmc_request_done(host->mmc, mrq);
}
@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
host->mrq = NULL;
spin_unlock_irqrestore(&host->lock, flags);
+ if (mrq->cmd->error || (mrq->data && mrq->data->error))
+ tmio_mmc_abort_dma(host);
+
mmc_request_done(host->mmc, mrq);
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6ae9ca01388b..9a9ce71a71fc 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)
{
struct mtd_info *mtd = dev_get_drvdata(dev);
- return mtd_suspend(mtd);
+ return mtd ? mtd_suspend(mtd) : 0;
}
static int mtd_cls_resume(struct device *dev)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4dd056e2e16a..35b4fb55dbd6 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
!!host->board->rdy_pin_active_low;
}
+/*
+ * Minimal-overhead PIO for data access.
+ */
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+}
+
+static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+}
+
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
+}
+
+static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+}
+
static void dma_complete_func(void *completion)
{
complete(completion);
@@ -235,27 +266,33 @@ err_buf:
static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
if (use_dma && len > mtd->oobsize)
/* only use DMA for bigger than oob size: better performances */
if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
return;
- /* if no DMA operation possible, use PIO */
- memcpy_fromio(buf, chip->IO_ADDR_R, len);
+ if (host->board->bus_width_16)
+ atmel_read_buf16(mtd, buf, len);
+ else
+ atmel_read_buf8(mtd, buf, len);
}
static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
if (use_dma && len > mtd->oobsize)
/* only use DMA for bigger than oob size: better performances */
if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
return;
- /* if no DMA operation possible, use PIO */
- memcpy_toio(chip->IO_ADDR_W, buf, len);
+ if (host->board->bus_width_16)
+ atmel_write_buf16(mtd, buf, len);
+ else
+ atmel_write_buf8(mtd, buf, len);
}
/*
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 7f680420bfab..7db6555ed3ba 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
* [1] enable the module.
* [2] reset the module.
*
- * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
* If you try to soft reset the BCH block, it becomes unusable until
* the next hard reset. This case occurs in the NAND boot mode. When the board
* boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
* So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
*
* To avoid this bug, just add a new parameter `just_enable` for
* the mxs_reset_block(), and rewrite it here.
*/
-int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
{
int ret;
int timeout = 0x400;
@@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)
if (ret)
goto err_out;
- ret = gpmi_reset_block(r->bch_regs, true);
+ /*
+ * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+ * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+ * On the other hand, the MX28 needs the reset, because one case has been
+ * seen where the BCH produced ECC errors constantly after 10000
+ * consecutive reboots. The latter case has not been seen on the MX23 yet,
+ * still we don't know if it could happen there as well.
+ */
+ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
if (ret)
goto err_out;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 35b4565050f1..8a393f9e6027 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
instr->state = MTD_ERASING;
while (len) {
- /* Heck if we have a bad block, we do not erase bad blocks! */
+ /* Check if we have a bad block, we do not erase bad blocks! */
if (nand_block_checkbad(mtd, ((loff_t) page) <<
chip->page_shift, 0, allowbbt)) {
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 766896747643..c30f0e6f1048 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -440,12 +440,14 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
for (i = 0; i < dlc; i++)
cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
+ /* Store echo skb before starting the transfer */
+ can_put_echo_skb(skb, dev, 0);
+
cc770_write_reg(priv, msgobj[mo].ctrl1,
RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
stats->tx_bytes += dlc;
- can_put_echo_skb(skb, dev, 0);
/*
* HM: We had some cases of repeated IRQs so make sure the
diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
index 4be5fe2c40a5..9f3a25ccd665 100644
--- a/drivers/net/can/cc770/cc770_isa.c
+++ b/drivers/net/can/cc770/cc770_isa.c
@@ -110,6 +110,11 @@ MODULE_PARM_DESC(bcr, "Bus configuration register (default=0x40 [CBY])");
#define CC770_IOSIZE 0x20
#define CC770_IOSIZE_INDIRECT 0x02
+/* Spinlock for cc770_isa_port_write_reg_indirect
+ * and cc770_isa_port_read_reg_indirect
+ */
+static DEFINE_SPINLOCK(cc770_isa_port_lock);
+
static struct platform_device *cc770_isa_devs[MAXDEV];
static u8 cc770_isa_mem_read_reg(const struct cc770_priv *priv, int reg)
@@ -138,18 +143,27 @@ static u8 cc770_isa_port_read_reg_indirect(const struct cc770_priv *priv,
int reg)
{
unsigned long base = (unsigned long)priv->reg_base;
+ unsigned long flags;
+ u8 val;
+ spin_lock_irqsave(&cc770_isa_port_lock, flags);
outb(reg, base);
- return inb(base + 1);
+ val = inb(base + 1);
+ spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
+
+ return val;
}
static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
int reg, u8 val)
{
unsigned long base = (unsigned long)priv->reg_base;
+ unsigned long flags;
+ spin_lock_irqsave(&cc770_isa_port_lock, flags);
outb(reg, base);
outb(val, base + 1);
+ spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
}
static int __devinit cc770_isa_probe(struct platform_device *pdev)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 7fd8089946fb..96d235799ec1 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -118,6 +118,9 @@
(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT)
#define FLEXCAN_ESR_ERR_ALL \
(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
+#define FLEXCAN_ESR_ALL_INT \
+ (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
+ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
/* FLEXCAN interrupt flag register (IFLAG) bits */
#define FLEXCAN_TX_BUF_ID 8
@@ -577,7 +580,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
reg_iflag1 = flexcan_read(&regs->iflag1);
reg_esr = flexcan_read(&regs->esr);
- flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
+ /* ACK all bus error and state change IRQ sources */
+ if (reg_esr & FLEXCAN_ESR_ALL_INT)
+ flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
/*
* schedule NAPI in case of:
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index d11fbb2b95ff..6edc25e0dd15 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -66,6 +66,7 @@
#define PCH_IF_CREQ_BUSY BIT(15)
#define PCH_STATUS_INT 0x8000
+#define PCH_RP 0x00008000
#define PCH_REC 0x00007f00
#define PCH_TEC 0x000000ff
@@ -527,7 +528,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)
priv->can.can_stats.error_passive++;
state = CAN_STATE_ERROR_PASSIVE;
cf->can_id |= CAN_ERR_CRTL;
- if (((errc & PCH_REC) >> 8) > 127)
+ if (errc & PCH_RP)
cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
if ((errc & PCH_TEC) > 127)
cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index 2c7f5036f570..214795945bc4 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -39,9 +39,9 @@ MODULE_LICENSE("GPL v2");
#define DRV_NAME "peak_pci"
struct peak_pci_chan {
- void __iomem *cfg_base; /* Common for all channels */
- struct net_device *next_dev; /* Chain of network devices */
- u16 icr_mask; /* Interrupt mask for fast ack */
+ void __iomem *cfg_base; /* Common for all channels */
+ struct net_device *prev_dev; /* Chain of network devices */
+ u16 icr_mask; /* Interrupt mask for fast ack */
};
#define PEAK_PCI_CAN_CLOCK (16000000 / 2)
@@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
{
struct sja1000_priv *priv;
struct peak_pci_chan *chan;
- struct net_device *dev, *dev0 = NULL;
+ struct net_device *dev;
void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr;
int i, err, channels;
@@ -196,18 +196,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
}
/* Create chain of SJA1000 devices */
- if (i == 0)
- dev0 = dev;
- else
- chan->next_dev = dev;
+ chan->prev_dev = pci_get_drvdata(pdev);
+ pci_set_drvdata(pdev, dev);
dev_info(&pdev->dev,
"%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
dev->name, priv->reg_base, chan->cfg_base, dev->irq);
}
- pci_set_drvdata(pdev, dev0);
-
/* Enable interrupts */
writew(icr, cfg_base + PITA_ICR + 2);
@@ -217,12 +213,11 @@ failure_remove_channels:
/* Disable interrupts */
writew(0x0, cfg_base + PITA_ICR + 2);
- for (dev = dev0; dev; dev = chan->next_dev) {
+ for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
unregister_sja1000dev(dev);
free_sja1000dev(dev);
priv = netdev_priv(dev);
chan = priv->priv;
- dev = chan->next_dev;
}
pci_iounmap(pdev, reg_base);
@@ -241,7 +236,7 @@ failure_disable_pci:
static void __devexit peak_pci_remove(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev); /* First device */
+ struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
struct sja1000_priv *priv = netdev_priv(dev);
struct peak_pci_chan *chan = priv->priv;
void __iomem *cfg_base = chan->cfg_base;
@@ -255,7 +250,7 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev)
dev_info(&pdev->dev, "removing device %s\n", dev->name);
unregister_sja1000dev(dev);
free_sja1000dev(dev);
- dev = chan->next_dev;
+ dev = chan->prev_dev;
if (!dev)
break;
priv = netdev_priv(dev);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index df809e3f130e..5a2e1e3588a1 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -745,9 +745,10 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
}
}
- netif_receive_skb(skb);
+ netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+
return 0;
}
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 9697c14b8dc6..7dae64d44e83 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -627,9 +627,6 @@ static int ems_usb_start(struct ems_usb *dev)
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
- if (err == -ENODEV)
- netif_device_detach(dev->netdev);
-
usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
@@ -659,9 +656,6 @@ static int ems_usb_start(struct ems_usb *dev)
err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
if (err) {
- if (err == -ENODEV)
- netif_device_detach(dev->netdev);
-
dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",
err);
@@ -692,9 +686,6 @@ static int ems_usb_start(struct ems_usb *dev)
return 0;
failed:
- if (err == -ENODEV)
- netif_device_detach(dev->netdev);
-
dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);
return err;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 8153a3e0a1a4..f9b74c0a8492 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1842,7 +1842,7 @@ vortex_timer(unsigned long data)
ok = 1;
}
- if (!netif_carrier_ok(dev))
+ if (dev->flags & IFF_SLAVE || !netif_carrier_ok(dev))
next_tick = 5*HZ;
if (vp->medialock)
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 986019b2c849..c7ca7ec065ee 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -797,7 +797,7 @@ static int bcm_enet_open(struct net_device *dev)
if (priv->has_phy) {
/* connect to PHY */
snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
- priv->mac_id ? "1" : "0", priv->phy_id);
+ priv->mii_bus->id, priv->phy_id);
phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
PHY_INTERFACE_MODE_MII);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 03f3935fd8c2..7aee46983be4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -523,7 +523,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
skb = build_skb(data);
if (likely(skb)) {
-
#ifdef BNX2X_STOP_ON_ERROR
if (pad + len > fp->rx_buf_size) {
BNX2X_ERR("skb_put is about to fail... "
@@ -557,7 +556,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return;
}
-
+ kfree(new_data);
drop:
/* drop the packet and keep the buffer in the bin */
DP(NETIF_MSG_RX_STATUS,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 1e3f978ee6da..254521319150 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -117,10 +117,6 @@ static int dropless_fc;
module_param(dropless_fc, int, 0);
MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
-static int poll;
-module_param(poll, int, 0);
-MODULE_PARM_DESC(poll, " Use polling (for debug)");
-
static int mrrs = -1;
module_param(mrrs, int, 0);
MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)");
@@ -4834,20 +4830,11 @@ void bnx2x_drv_pulse(struct bnx2x *bp)
static void bnx2x_timer(unsigned long data)
{
- u8 cos;
struct bnx2x *bp = (struct bnx2x *) data;
if (!netif_running(bp->dev))
return;
- if (poll) {
- struct bnx2x_fastpath *fp = &bp->fp[0];
-
- for_each_cos_in_tx_queue(fp, cos)
- bnx2x_tx_int(bp, &fp->txdata[cos]);
- bnx2x_rx_int(fp, 1000);
- }
-
if (!BP_NOMCP(bp)) {
int mb_idx = BP_FW_MB_IDX(bp);
u32 drv_pulse;
@@ -10063,7 +10050,6 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
static int __devinit bnx2x_init_bp(struct bnx2x *bp)
{
int func;
- int timer_interval;
int rc;
mutex_init(&bp->port.phy_mutex);
@@ -10139,8 +10125,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR;
- timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
- bp->current_interval = (poll ? poll : timer_interval);
+ bp->current_interval = CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ;
init_timer(&bp->timer);
bp->timer.expires = jiffies + bp->current_interval;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index bc0121ac291e..1adef266fcd5 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1081,17 +1081,17 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
estats->rx_stat_ifhcinbadoctets_lo);
ADD_64(fstats->total_bytes_received_hi,
- tfunc->rcv_error_bytes.hi,
+ le32_to_cpu(tfunc->rcv_error_bytes.hi),
fstats->total_bytes_received_lo,
- tfunc->rcv_error_bytes.lo);
+ le32_to_cpu(tfunc->rcv_error_bytes.lo));
memcpy(estats, &(fstats->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
ADD_64(estats->error_bytes_received_hi,
- tfunc->rcv_error_bytes.hi,
+ le32_to_cpu(tfunc->rcv_error_bytes.hi),
estats->error_bytes_received_lo,
- tfunc->rcv_error_bytes.lo);
+ le32_to_cpu(tfunc->rcv_error_bytes.lo));
ADD_64(estats->etherstatsoverrsizepkts_hi,
estats->rx_stat_dot3statsframestoolong_hi,
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 9b44ec8096ba..803ea32aa99d 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -946,7 +946,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL);
if (!flash_attr)
- return -ENOMEM;
+ return 0;
fcomp.bnad = bnad;
fcomp.comp_status = 0;
@@ -958,7 +958,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
if (ret != BFA_STATUS_OK) {
spin_unlock_irqrestore(&bnad->bna_lock, flags);
kfree(flash_attr);
- goto out_err;
+ return 0;
}
spin_unlock_irqrestore(&bnad->bna_lock, flags);
wait_for_completion(&fcomp.comp);
@@ -978,8 +978,6 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
}
kfree(flash_attr);
return flash_part;
-out_err:
- return -EINVAL;
}
static int
@@ -1006,7 +1004,7 @@ bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
/* Query the flash partition based on the offset */
flash_part = bnad_get_flash_partition_by_offset(bnad,
eeprom->offset, &base_offset);
- if (flash_part <= 0)
+ if (flash_part == 0)
return -EFAULT;
fcomp.bnad = bnad;
@@ -1048,7 +1046,7 @@ bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
/* Query the flash partition based on the offset */
flash_part = bnad_get_flash_partition_by_offset(bnad,
eeprom->offset, &base_offset);
- if (flash_part <= 0)
+ if (flash_part == 0)
return -EFAULT;
fcomp.bnad = bnad;
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 6db6b6ae5e9b..802e5ddef8a8 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -716,12 +716,8 @@ static int
be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
{
struct be_adapter *adapter = netdev_priv(netdev);
- char file_name[ETHTOOL_FLASH_MAX_FILENAME];
- file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
- strcpy(file_name, efl->data);
-
- return be_load_fw(adapter, file_name);
+ return be_load_fw(adapter, efl->data);
}
static int
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 7b25e9cf13f6..e92ef1bd732a 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -986,11 +986,11 @@ static int fec_enet_mii_probe(struct net_device *ndev)
printk(KERN_INFO
"%s: no PHY, assuming direct connection to switch\n",
ndev->name);
- strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
+ strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
phy_id = 0;
}
- snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+ snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
fep->phy_interface);
if (IS_ERR(phy_dev)) {
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 669ca3800c01..d94d64b5d695 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -4740,12 +4740,14 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
e1000_setup_rctl(adapter);
e1000_set_rx_mode(netdev);
+ rctl = er32(RCTL);
+
/* turn on all-multi mode if wake on multicast is enabled */
- if (wufc & E1000_WUFC_MC) {
- rctl = er32(RCTL);
+ if (wufc & E1000_WUFC_MC)
rctl |= E1000_RCTL_MPE;
- ew32(RCTL, rctl);
- }
+
+ /* enable receives in the hardware */
+ ew32(RCTL, rctl | E1000_RCTL_EN);
if (hw->mac_type >= e1000_82540) {
ctrl = er32(CTRL);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index e91d73c8aa4e..94be6c32fa7d 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -5012,7 +5012,8 @@ static int igb_find_enabled_vfs(struct igb_adapter *adapter)
vf_devfn = pdev->devfn + 0x80;
pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
while (pvfdev) {
- if (pvfdev->devfn == vf_devfn)
+ if (pvfdev->devfn == vf_devfn &&
+ (pvfdev->bus->number >= pdev->bus->number))
vfs_found++;
vf_devfn += vf_stride;
pvfdev = pci_get_device(hw->vendor_id,
diff --git a/drivers/net/ethernet/intel/igbvf/Makefile b/drivers/net/ethernet/intel/igbvf/Makefile
index 0fa3db3dd8b6..044b0ad5fcb9 100644
--- a/drivers/net/ethernet/intel/igbvf/Makefile
+++ b/drivers/net/ethernet/intel/igbvf/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel(R) 82576 Virtual Function Linux driver
-# Copyright(c) 2009 - 2010 Intel Corporation.
+# Copyright(c) 2009 - 2012 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h
index 79f2604673fe..33f40d3474ae 100644
--- a/drivers/net/ethernet/intel/igbvf/defines.h
+++ b/drivers/net/ethernet/intel/igbvf/defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index 2dba53446064..db7dce2351c2 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index fd4a7b780fdd..2c6d87e4d3d9 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/mbx.c b/drivers/net/ethernet/intel/igbvf/mbx.c
index 048aae248d06..b4b65bc9fc5d 100644
--- a/drivers/net/ethernet/intel/igbvf/mbx.c
+++ b/drivers/net/ethernet/intel/igbvf/mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/mbx.h b/drivers/net/ethernet/intel/igbvf/mbx.h
index c2883c45d477..24370bcb0e22 100644
--- a/drivers/net/ethernet/intel/igbvf/mbx.h
+++ b/drivers/net/ethernet/intel/igbvf/mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index a4b20c865759..4e9141cfe81d 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -53,7 +53,7 @@ const char igbvf_driver_version[] = DRV_VERSION;
static const char igbvf_driver_string[] =
"Intel(R) Gigabit Virtual Function Network Driver";
static const char igbvf_copyright[] =
- "Copyright (c) 2009 - 2011 Intel Corporation.";
+ "Copyright (c) 2009 - 2012 Intel Corporation.";
static int igbvf_poll(struct napi_struct *napi, int budget);
static void igbvf_reset(struct igbvf_adapter *);
diff --git a/drivers/net/ethernet/intel/igbvf/regs.h b/drivers/net/ethernet/intel/igbvf/regs.h
index 77e18d3d6b15..7dc6341715dc 100644
--- a/drivers/net/ethernet/intel/igbvf/regs.h
+++ b/drivers/net/ethernet/intel/igbvf/regs.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c
index af3822f9ea9a..19551977b352 100644
--- a/drivers/net/ethernet/intel/igbvf/vf.c
+++ b/drivers/net/ethernet/intel/igbvf/vf.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igbvf/vf.h b/drivers/net/ethernet/intel/igbvf/vf.h
index d7ed58fcd9bb..57db3c68dfcd 100644
--- a/drivers/net/ethernet/intel/igbvf/vf.h
+++ b/drivers/net/ethernet/intel/igbvf/vf.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 - 2010 Intel Corporation.
+ Copyright(c) 2009 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 7d7387fbdecd..7a16177a12a5 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel 10 Gigabit PCI Express Linux driver
-# Copyright(c) 1999 - 2010 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 258164d6d45a..e6aeb64105a4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index ef2afefb0cd4..b406c367b190 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 772072147bea..4e59083a3de2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index a3aa6333073f..383b9413292e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 863f9c1f145b..2c834c46bba1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -75,7 +75,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
index 318caf4bf623..8bfaaee5ac5b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
index e162775064da..24333b718166 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
index fcd0e479721f..d3695edfcb8b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
index 2f318935561a..ba835708fcac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index 32cd97bc794d..888a419dc3d9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
index a59d5dc59d04..4dec47faeb00 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index da31735311f1..79a92fe987b9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -112,6 +112,8 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
{
u8 err = 0;
+ u8 prio_tc[MAX_USER_PRIORITY] = {0};
+ int i;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
/* Fail command if not in CEE mode */
@@ -122,10 +124,15 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
return err;
- if (state > 0)
+ if (state > 0) {
err = ixgbe_setup_tc(netdev, adapter->dcb_cfg.num_tcs.pg_tcs);
- else
+ ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc);
+ } else {
err = ixgbe_setup_tc(netdev, 0);
+ }
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+ netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
return err;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index da7e580f517a..a62975480e37 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -58,7 +58,7 @@ struct ixgbe_stats {
sizeof(((struct rtnl_link_stats64 *)0)->m), \
offsetof(struct rtnl_link_stats64, m)
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_packets", IXGBE_NETDEV_STAT(rx_packets)},
{"tx_packets", IXGBE_NETDEV_STAT(tx_packets)},
{"rx_bytes", IXGBE_NETDEV_STAT(rx_bytes)},
@@ -120,19 +120,23 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
#endif /* IXGBE_FCOE */
};
-#define IXGBE_QUEUE_STATS_LEN \
- ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \
- ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \
+/* ixgbe allocates num_tx_queues and num_rx_queues symmetrically so
+ * we set the num_rx_queues to evaluate to num_tx_queues. This is
+ * used because we do not have a good way to get the max number of
+ * rx queues with CONFIG_RPS disabled.
+ */
+#define IXGBE_NUM_RX_QUEUES netdev->num_tx_queues
+
+#define IXGBE_QUEUE_STATS_LEN ( \
+ (netdev->num_tx_queues + IXGBE_NUM_RX_QUEUES) * \
(sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
#define IXGBE_PB_STATS_LEN ( \
- (((struct ixgbe_adapter *)netdev_priv(netdev))->flags & \
- IXGBE_FLAG_DCB_ENABLED) ? \
- (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
- sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
- sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
- sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
- / sizeof(u64) : 0)
+ (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
+ / sizeof(u64))
#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \
IXGBE_PB_STATS_LEN + \
IXGBE_QUEUE_STATS_LEN)
@@ -1078,8 +1082,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
data[i] = (ixgbe_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
- for (j = 0; j < adapter->num_tx_queues; j++) {
+ for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
ring = adapter->tx_ring[j];
+ if (!ring) {
+ data[i] = 0;
+ data[i+1] = 0;
+ i += 2;
+ continue;
+ }
+
do {
start = u64_stats_fetch_begin_bh(&ring->syncp);
data[i] = ring->stats.packets;
@@ -1087,8 +1098,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
i += 2;
}
- for (j = 0; j < adapter->num_rx_queues; j++) {
+ for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
ring = adapter->rx_ring[j];
+ if (!ring) {
+ data[i] = 0;
+ data[i+1] = 0;
+ i += 2;
+ continue;
+ }
+
do {
start = u64_stats_fetch_begin_bh(&ring->syncp);
data[i] = ring->stats.packets;
@@ -1096,22 +1114,20 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
i += 2;
}
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
- data[i++] = adapter->stats.pxontxc[j];
- data[i++] = adapter->stats.pxofftxc[j];
- }
- for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) {
- data[i++] = adapter->stats.pxonrxc[j];
- data[i++] = adapter->stats.pxoffrxc[j];
- }
+
+ for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) {
+ data[i++] = adapter->stats.pxontxc[j];
+ data[i++] = adapter->stats.pxofftxc[j];
+ }
+ for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) {
+ data[i++] = adapter->stats.pxonrxc[j];
+ data[i++] = adapter->stats.pxoffrxc[j];
}
}
static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
u8 *data)
{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
char *p = (char *)data;
int i;
@@ -1126,31 +1142,29 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
- for (i = 0; i < adapter->num_tx_queues; i++) {
+ for (i = 0; i < netdev->num_tx_queues; i++) {
sprintf(p, "tx_queue_%u_packets", i);
p += ETH_GSTRING_LEN;
sprintf(p, "tx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
}
- for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) {
sprintf(p, "rx_queue_%u_packets", i);
p += ETH_GSTRING_LEN;
sprintf(p, "rx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
}
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
- sprintf(p, "tx_pb_%u_pxon", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_pb_%u_pxoff", i);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) {
- sprintf(p, "rx_pb_%u_pxon", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_pb_%u_pxoff", i);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
+ sprintf(p, "tx_pb_%u_pxon", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_pb_%u_pxoff", i);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
+ sprintf(p, "rx_pb_%u_pxon", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_pb_%u_pxoff", i);
+ p += ETH_GSTRING_LEN;
}
/* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index d18d6157dd2c..4bc794249801 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
index 261fd62dda18..1dbed17c8107 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1ee5d0fbb905..3dc6cef58107 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -64,7 +64,7 @@ char ixgbe_default_device_descr[] =
__stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
- "Copyright (c) 1999-2011 Intel Corporation.";
+ "Copyright (c) 1999-2012 Intel Corporation.";
static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_82598] = &ixgbe_82598_info,
@@ -2633,22 +2633,22 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
/*
* we must limit the number of descriptors so that the
* total size of max desc * buf_len is not greater
- * than 65535
+ * than 65536
*/
if (ring_is_ps_enabled(ring)) {
-#if (MAX_SKB_FRAGS > 16)
+#if (PAGE_SIZE < 8192)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-#elif (MAX_SKB_FRAGS > 8)
+#elif (PAGE_SIZE < 16384)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-#elif (MAX_SKB_FRAGS > 4)
+#elif (PAGE_SIZE < 32768)
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
#else
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
#endif
} else {
- if (rx_buf_len < IXGBE_RXBUFFER_4K)
+ if (rx_buf_len <= IXGBE_RXBUFFER_4K)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
- else if (rx_buf_len < IXGBE_RXBUFFER_8K)
+ else if (rx_buf_len <= IXGBE_RXBUFFER_8K)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
else
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
@@ -2830,7 +2830,7 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
vf_shift = adapter->num_vfs % 32;
- reg_offset = (adapter->num_vfs > 32) ? 1 : 0;
+ reg_offset = (adapter->num_vfs >= 32) ? 1 : 0;
/* Enable only the PF's pool for Tx/Rx */
IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
@@ -4330,6 +4330,10 @@ static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
adapter->num_tx_queues = 1;
done:
+ if ((adapter->netdev->reg_state == NETREG_UNREGISTERED) ||
+ (adapter->netdev->reg_state == NETREG_UNREGISTERING))
+ return 0;
+
/* Notify the stack of the (possibly) reduced queue counts. */
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
return netif_set_real_num_rx_queues(adapter->netdev,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
index 3f725d48336d..1f3e32b576a5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index b239bdac38da..310bdd961075 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 7cf1e1f56c69..b91773551a38 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index 197bdd13106a..cc18165b4c05 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index cf6812dd1436..b01ecb4d2bb1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -67,7 +67,8 @@ static int ixgbe_find_enabled_vfs(struct ixgbe_adapter *adapter)
vf_devfn = pdev->devfn + 0x80;
pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
while (pvfdev) {
- if (pvfdev->devfn == vf_devfn)
+ if (pvfdev->devfn == vf_devfn &&
+ (pvfdev->bus->number >= pdev->bus->number))
vfs_found++;
vf_devfn += 2;
pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
@@ -646,6 +647,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
retval = ixgbe_set_vf_macvlan(adapter, vf, index,
(unsigned char *)(&msgbuf[1]));
+ if (retval == -ENOSPC)
+ e_warn(drv, "VF %d has requested a MACVLAN filter "
+ "but there is no space for it\n", vf);
break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
index e8badab03359..2ab38d5fda92 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 775602ef90e5..9b95bef60970 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 8cc5eccfd651..f838a2be8cfb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/Makefile b/drivers/net/ethernet/intel/ixgbevf/Makefile
index 1f35d229e71a..4ce4c97ef5ad 100644
--- a/drivers/net/ethernet/intel/ixgbevf/Makefile
+++ b/drivers/net/ethernet/intel/ixgbevf/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel 82599 Virtual Function driver
-# Copyright(c) 1999 - 2010 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index 2eb89cb94a0d..947b5c830735 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index c85700318147..2bfe0d1d7958 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 9075c1d61039..dfed420a1bf6 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index bed411bada21..e51d552410ae 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -60,7 +60,7 @@ static const char ixgbevf_driver_string[] =
#define DRV_VERSION "2.2.0-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
- "Copyright (c) 2009 - 2010 Intel Corporation.";
+ "Copyright (c) 2009 - 2012 Intel Corporation.";
static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
[board_82599_vf] = &ixgbevf_82599_vf_info,
@@ -935,7 +935,11 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
if (msg & IXGBE_VT_MSGTYPE_NACK)
pr_warn("Last Request of type %2.2x to PF Nacked\n",
msg & 0xFF);
- goto out;
+ /*
+ * Restore the PFSTS bit in case someone is polling for a
+ * return message from the PF
+ */
+ hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFSTS;
}
/*
@@ -945,7 +949,7 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
*/
if (got_ack)
hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
-out:
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index 13532d9ba72d..9c955900fe64 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index 9d38a94a348a..cf9131c5c115 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/regs.h b/drivers/net/ethernet/intel/ixgbevf/regs.h
index 5e4d5e5cdf38..debd8c0e1f28 100644
--- a/drivers/net/ethernet/intel/ixgbevf/regs.h
+++ b/drivers/net/ethernet/intel/ixgbevf/regs.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index d0138d7a31a1..74be7411242a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -283,6 +283,17 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
return ret_val;
}
+static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
+ u32 *msg, u16 size)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ u32 retmsg[IXGBE_VFMAILBOX_SIZE];
+ s32 retval = mbx->ops.write_posted(hw, msg, size);
+
+ if (!retval)
+ mbx->ops.read_posted(hw, retmsg, size);
+}
+
/**
* ixgbevf_update_mc_addr_list_vf - Update Multicast addresses
* @hw: pointer to the HW structure
@@ -294,7 +305,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
struct net_device *netdev)
{
struct netdev_hw_addr *ha;
- struct ixgbe_mbx_info *mbx = &hw->mbx;
u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
u16 *vector_list = (u16 *)&msgbuf[1];
u32 cnt, i;
@@ -321,7 +331,7 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
}
- mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
+ ixgbevf_write_msg_read_ack(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
return 0;
}
@@ -336,7 +346,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
bool vlan_on)
{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
msgbuf[0] = IXGBE_VF_SET_VLAN;
@@ -344,7 +353,9 @@ static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT;
- return mbx->ops.write_posted(hw, msgbuf, 2);
+ ixgbevf_write_msg_read_ack(hw, msgbuf, 2);
+
+ return 0;
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index d556619a9212..25c951daee5d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 82599 Virtual Function driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index edb9bda55d55..33947ac595c0 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -931,20 +931,17 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
}
/* Allocate and setup a new buffer for receiving */
-static int skge_rx_setup(struct pci_dev *pdev,
- struct skge_element *e,
- struct sk_buff *skb, unsigned int bufsize)
+static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
+ struct sk_buff *skb, unsigned int bufsize)
{
struct skge_rx_desc *rd = e->desc;
- dma_addr_t map;
+ u64 map;
- map = pci_map_single(pdev, skb->data, bufsize,
+ map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(pdev, map))
- goto mapping_error;
- rd->dma_lo = lower_32_bits(map);
- rd->dma_hi = upper_32_bits(map);
+ rd->dma_lo = map;
+ rd->dma_hi = map >> 32;
e->skb = skb;
rd->csum1_start = ETH_HLEN;
rd->csum2_start = ETH_HLEN;
@@ -956,13 +953,6 @@ static int skge_rx_setup(struct pci_dev *pdev,
rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, bufsize);
- return 0;
-
-mapping_error:
- if (net_ratelimit())
- dev_warn(&pdev->dev, "%s: rx mapping error\n",
- skb->dev->name);
- return -EIO;
}
/* Resume receiving using existing skb,
@@ -1024,11 +1014,7 @@ static int skge_rx_fill(struct net_device *dev)
return -ENOMEM;
skb_reserve(skb, NET_IP_ALIGN);
- if (skge_rx_setup(skge->hw->pdev, e, skb, skge->rx_buf_size)) {
- kfree_skb(skb);
- return -ENOMEM;
- }
-
+ skge_rx_setup(skge, e, skb, skge->rx_buf_size);
} while ((e = e->next) != ring->start);
ring->to_clean = ring->start;
@@ -2743,7 +2729,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
struct skge_tx_desc *td;
int i;
u32 control, len;
- dma_addr_t map;
+ u64 map;
if (skb_padto(skb, ETH_ZLEN))
return NETDEV_TX_OK;
@@ -2757,14 +2743,11 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
e->skb = skb;
len = skb_headlen(skb);
map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(hw->pdev, map))
- goto mapping_error;
-
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, len);
- td->dma_lo = lower_32_bits(map);
- td->dma_hi = upper_32_bits(map);
+ td->dma_lo = map;
+ td->dma_hi = map >> 32;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const int offset = skb_checksum_start_offset(skb);
@@ -2795,16 +2778,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
skb_frag_size(frag), DMA_TO_DEVICE);
- if (dma_mapping_error(&hw->pdev->dev, map))
- goto mapping_unwind;
e = e->next;
e->skb = skb;
tf = e->desc;
BUG_ON(tf->control & BMU_OWN);
- tf->dma_lo = lower_32_bits(map);
- tf->dma_hi = upper_32_bits(map);
+ tf->dma_lo = map;
+ tf->dma_hi = (u64) map >> 32;
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, skb_frag_size(frag));
@@ -2834,28 +2815,6 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
}
return NETDEV_TX_OK;
-
-mapping_unwind:
- /* unroll any pages that were already mapped. */
- if (e != skge->tx_ring.to_use) {
- struct skge_element *u;
-
- for (u = skge->tx_ring.to_use->next; u != e; u = u->next)
- pci_unmap_page(hw->pdev, dma_unmap_addr(u, mapaddr),
- dma_unmap_len(u, maplen),
- PCI_DMA_TODEVICE);
- e = skge->tx_ring.to_use;
- }
- /* undo the mapping for the skb header */
- pci_unmap_single(hw->pdev, dma_unmap_addr(e, mapaddr),
- dma_unmap_len(e, maplen),
- PCI_DMA_TODEVICE);
-mapping_error:
- /* mapping error causes error message and packet to be discarded. */
- if (net_ratelimit())
- dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
}
@@ -3099,17 +3058,13 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
if (!nskb)
goto resubmit;
- if (unlikely(skge_rx_setup(skge->hw->pdev, e, nskb, skge->rx_buf_size))) {
- dev_kfree_skb(nskb);
- goto resubmit;
- }
-
pci_unmap_single(skge->hw->pdev,
dma_unmap_addr(e, mapaddr),
dma_unmap_len(e, maplen),
PCI_DMA_FROMDEVICE);
skb = e->skb;
prefetch(skb->data);
+ skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
}
skb_put(skb, len);
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 405e6ac3faf6..eaf09d4f02d0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1616,12 +1616,12 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
}
kfree(priv->mfunc.master.slave_state);
- iounmap(priv->mfunc.comm);
- dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
- priv->mfunc.vhcr,
- priv->mfunc.vhcr_dma);
- priv->mfunc.vhcr = NULL;
}
+
+ iounmap(priv->mfunc.comm);
+ dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
+ priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
+ priv->mfunc.vhcr = NULL;
}
void mlx4_cmd_cleanup(struct mlx4_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 467ae5824875..149e60da0a32 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -892,7 +892,8 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv)
for (i = 0; i < priv->rx_ring_num; i++) {
if (priv->rx_ring[i].rx_info)
- mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
+ mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
+ priv->prof->rx_ring_size, priv->stride);
if (priv->rx_cq[i].buf)
mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 971d4b6b8dfe..d4ad8c226b51 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -168,8 +168,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
return 0;
err:
- while (i--)
+ while (i--) {
+ dma_addr_t dma = be64_to_cpu(rx_desc->data[i].addr);
+ pci_unmap_single(priv->mdev->pdev, dma, skb_frags[i].size,
+ PCI_DMA_FROMDEVICE);
put_page(skb_frags[i].page);
+ }
return -ENOMEM;
}
@@ -380,12 +384,12 @@ err_allocator:
}
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring)
+ struct mlx4_en_rx_ring *ring, u32 size, u16 stride)
{
struct mlx4_en_dev *mdev = priv->mdev;
mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
vfree(ring->rx_info);
ring->rx_info = NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 55d7bd4e210a..8fa41f3082cf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -815,8 +815,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
int err;
int i;
- priv->eq_table.uar_map = kcalloc(sizeof *priv->eq_table.uar_map,
- mlx4_num_eq_uar(dev), GFP_KERNEL);
+ priv->eq_table.uar_map = kcalloc(mlx4_num_eq_uar(dev),
+ sizeof *priv->eq_table.uar_map,
+ GFP_KERNEL);
if (!priv->eq_table.uar_map) {
err = -ENOMEM;
goto err_out_free;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 0785d9b2a265..ca574d850b39 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -136,7 +136,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,
u32 prot;
int err;
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
if (!new_entry)
return -ENOMEM;
@@ -220,7 +220,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
struct mlx4_promisc_qp *pqp;
struct mlx4_promisc_qp *dqp;
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
pqp = get_promisc_qp(dev, 0, steer, qpn);
if (!pqp)
@@ -265,7 +265,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
struct mlx4_steer_index *tmp_entry, *entry = NULL;
struct mlx4_promisc_qp *dqp, *tmp_dqp;
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
/* if qp is not promisc, it cannot be duplicated */
if (!get_promisc_qp(dev, 0, steer, qpn))
@@ -306,7 +306,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
bool ret = false;
int i;
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -361,7 +361,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
int err;
struct mlx4_priv *priv = mlx4_priv(dev);
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
mutex_lock(&priv->mcg_table.mutex);
@@ -466,7 +466,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
int loc, i;
int err;
- s_steer = &mlx4_priv(dev)->steer[0];
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
mutex_lock(&priv->mcg_table.mutex);
pqp = get_promisc_qp(dev, 0, steer, qpn);
@@ -1004,7 +1004,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
return 0;
if (mlx4_is_mfunc(dev))
@@ -1016,7 +1016,7 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
{
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
return 0;
if (mlx4_is_mfunc(dev))
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 35f08840813c..d60335f3c473 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -528,7 +528,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring,
u32 size, u16 stride);
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring);
+ struct mlx4_en_rx_ring *ring,
+ u32 size, u16 stride);
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index dcd819bfb2f0..bfdb7af19e49 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -73,6 +73,7 @@ struct res_gid {
struct list_head list;
u8 gid[16];
enum mlx4_protocol prot;
+ enum mlx4_steer_type steer;
};
enum res_qp_states {
@@ -374,6 +375,7 @@ static struct res_common *alloc_qp_tr(int id)
ret->com.res_id = id;
ret->com.state = RES_QP_RESERVED;
+ ret->local_qpn = id;
INIT_LIST_HEAD(&ret->mcg_list);
spin_lock_init(&ret->mcg_spl);
@@ -2479,7 +2481,8 @@ static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
}
static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
- u8 *gid, enum mlx4_protocol prot)
+ u8 *gid, enum mlx4_protocol prot,
+ enum mlx4_steer_type steer)
{
struct res_gid *res;
int err;
@@ -2495,6 +2498,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
} else {
memcpy(res->gid, gid, 16);
res->prot = prot;
+ res->steer = steer;
list_add_tail(&res->list, &rqp->mcg_list);
err = 0;
}
@@ -2504,14 +2508,15 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
}
static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
- u8 *gid, enum mlx4_protocol prot)
+ u8 *gid, enum mlx4_protocol prot,
+ enum mlx4_steer_type steer)
{
struct res_gid *res;
int err;
spin_lock_irq(&rqp->mcg_spl);
res = find_gid(dev, slave, rqp, gid);
- if (!res || res->prot != prot)
+ if (!res || res->prot != prot || res->steer != steer)
err = -EINVAL;
else {
list_del(&res->list);
@@ -2538,7 +2543,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
int attach = vhcr->op_modifier;
int block_loopback = vhcr->in_modifier >> 31;
u8 steer_type_mask = 2;
- enum mlx4_steer_type type = gid[7] & steer_type_mask;
+ enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
qpn = vhcr->in_modifier & 0xffffff;
err = get_res(dev, slave, qpn, RES_QP, &rqp);
@@ -2547,7 +2552,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
qp.qpn = qpn;
if (attach) {
- err = add_mcg_res(dev, slave, rqp, gid, prot);
+ err = add_mcg_res(dev, slave, rqp, gid, prot, type);
if (err)
goto ex_put;
@@ -2556,7 +2561,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
if (err)
goto ex_rem;
} else {
- err = rem_mcg_res(dev, slave, rqp, gid, prot);
+ err = rem_mcg_res(dev, slave, rqp, gid, prot, type);
if (err)
goto ex_put;
err = mlx4_qp_detach_common(dev, &qp, gid, prot, type);
@@ -2567,7 +2572,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
ex_rem:
/* ignore error return below, already in error */
- err1 = rem_mcg_res(dev, slave, rqp, gid, prot);
+ err1 = rem_mcg_res(dev, slave, rqp, gid, prot, type);
ex_put:
put_res(dev, slave, qpn, RES_QP);
@@ -2606,7 +2611,7 @@ static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
qp.qpn = rqp->local_qpn;
err = mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
- MLX4_MC_STEER);
+ rgid->steer);
list_del(&rgid->list);
kfree(rgid);
}
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
index 1ea811cf515b..fe42fc00d8d3 100644
--- a/drivers/net/ethernet/micrel/Kconfig
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -42,7 +42,6 @@ config KS8851
select NET_CORE
select MII
select CRC32
- select MISC_DEVICES
select EEPROM_93CX6
---help---
SPI driver for Micrel KS8851 SPI attached network chip.
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 6b35e7da9a9c..0c3e4005224d 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -583,7 +583,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
ks8851_dbg_dumpkkt(ks, rxpkt);
skb->protocol = eth_type_trans(skb, ks->netdev);
- netif_rx(skb);
+ netif_rx_ni(skb);
ks->netdev->stats.rx_packets++;
ks->netdev->stats.rx_bytes += rxlen;
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index e58e78e5c930..231176fcd2ba 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -394,7 +394,6 @@ union ks_tx_hdr {
* @msg_enable : The message flags controlling driver output (see ethtool).
* @frame_cnt : number of frames received.
* @bus_width : i/o bus width.
- * @irq : irq number assigned to this device.
* @rc_rxqcr : Cached copy of KS_RXQCR.
* @rc_txcr : Cached copy of KS_TXCR.
* @rc_ier : Cached copy of KS_IER.
@@ -441,7 +440,6 @@ struct ks_net {
u32 msg_enable;
u32 frame_cnt;
int bus_width;
- int irq;
u16 rc_rxqcr;
u16 rc_txcr;
@@ -907,10 +905,10 @@ static int ks_net_open(struct net_device *netdev)
netif_dbg(ks, ifup, ks->netdev, "%s - entry\n", __func__);
/* reset the HW */
- err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev);
+ err = request_irq(netdev->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev);
if (err) {
- pr_err("Failed to request IRQ: %d: %d\n", ks->irq, err);
+ pr_err("Failed to request IRQ: %d: %d\n", netdev->irq, err);
return err;
}
@@ -955,7 +953,7 @@ static int ks_net_stop(struct net_device *netdev)
/* set powermode to soft power down to save power */
ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
- free_irq(ks->irq, netdev);
+ free_irq(netdev->irq, netdev);
mutex_unlock(&ks->lock);
return 0;
}
@@ -1545,10 +1543,10 @@ static int __devinit ks8851_probe(struct platform_device *pdev)
if (!ks->hw_addr_cmd)
goto err_ioremap1;
- ks->irq = platform_get_irq(pdev, 0);
+ netdev->irq = platform_get_irq(pdev, 0);
- if (ks->irq < 0) {
- err = ks->irq;
+ if (netdev->irq < 0) {
+ err = netdev->irq;
goto err_get_irq;
}
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index 212f43b308a3..cd827ff4a021 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -670,7 +670,7 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
static int octeon_mgmt_init_phy(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- char phy_id[20];
+ char phy_id[MII_BUS_ID_SIZE + 3];
if (octeon_is_simulation()) {
/* No PHYs in the simulator. */
@@ -678,7 +678,7 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
return 0;
}
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port);
p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 813d41c4a845..87b650131774 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -38,6 +38,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/sh_eth.h>
#include "sh_eth.h"
@@ -817,7 +818,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
sh_eth_write(ndev, 0, TRIMD);
/* Recv frame limit set register */
- sh_eth_write(ndev, RFLR_VALUE, RFLR);
+ sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
+ RFLR);
sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 47877b13ffad..cdbd844662a7 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -575,9 +575,6 @@ enum RPADIR_BIT {
RPADIR_PADR = 0x0003f,
};
-/* RFLR */
-#define RFLR_VALUE 0x1000
-
/* FDR */
#define DEFAULT_FDR_INIT 0x00000707
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index d0b814ef0675..0319d640f728 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -67,6 +67,7 @@ struct stmmac_extra_stats {
unsigned long ipc_csum_error;
unsigned long rx_collision;
unsigned long rx_crc;
+ unsigned long dribbling_bit;
unsigned long rx_length;
unsigned long rx_mii;
unsigned long rx_multicast;
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index d87976364ec5..ad1b627f8ec2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -201,7 +201,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
if (unlikely(p->des01.erx.dribbling)) {
CHIP_DBG(KERN_ERR "GMAC RX: dribbling error\n");
- ret = discard_frame;
+ x->dribbling_bit++;
}
if (unlikely(p->des01.erx.sa_filter_fail)) {
CHIP_DBG(KERN_ERR "GMAC RX : Source Address filter fail\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index fda5d2b31d3a..25953bb45a73 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -104,7 +104,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
ret = discard_frame;
}
if (unlikely(p->des01.rx.dribbling))
- ret = discard_frame;
+ x->dribbling_bit++;
if (unlikely(p->des01.rx.length_error)) {
x->rx_length++;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 120740020e2c..b4b095fdcf29 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -21,7 +21,7 @@
*******************************************************************************/
#define STMMAC_RESOURCE_NAME "stmmaceth"
-#define DRV_MODULE_VERSION "Dec_2011"
+#define DRV_MODULE_VERSION "Feb_2012"
#include <linux/stmmac.h>
#include <linux/phy.h>
#include "common.h"
@@ -97,4 +97,5 @@ int stmmac_resume(struct net_device *ndev);
int stmmac_suspend(struct net_device *ndev);
int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
- struct plat_stmmacenet_data *plat_dat);
+ struct plat_stmmacenet_data *plat_dat,
+ void __iomem *addr);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 9573303a706b..f98e1511660f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -47,23 +47,25 @@ struct stmmac_stats {
offsetof(struct stmmac_priv, xstats.m)}
static const struct stmmac_stats stmmac_gstrings_stats[] = {
+ /* Transmit errors */
STMMAC_STAT(tx_underflow),
STMMAC_STAT(tx_carrier),
STMMAC_STAT(tx_losscarrier),
STMMAC_STAT(vlan_tag),
STMMAC_STAT(tx_deferred),
STMMAC_STAT(tx_vlan),
- STMMAC_STAT(rx_vlan),
STMMAC_STAT(tx_jabber),
STMMAC_STAT(tx_frame_flushed),
STMMAC_STAT(tx_payload_error),
STMMAC_STAT(tx_ip_header_error),
+ /* Receive errors */
STMMAC_STAT(rx_desc),
STMMAC_STAT(sa_filter_fail),
STMMAC_STAT(overflow_error),
STMMAC_STAT(ipc_csum_error),
STMMAC_STAT(rx_collision),
STMMAC_STAT(rx_crc),
+ STMMAC_STAT(dribbling_bit),
STMMAC_STAT(rx_length),
STMMAC_STAT(rx_mii),
STMMAC_STAT(rx_multicast),
@@ -73,6 +75,8 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(sa_rx_filter_fail),
STMMAC_STAT(rx_missed_cntr),
STMMAC_STAT(rx_overflow_cntr),
+ STMMAC_STAT(rx_vlan),
+ /* Tx/Rx IRQ errors */
STMMAC_STAT(tx_undeflow_irq),
STMMAC_STAT(tx_process_stopped_irq),
STMMAC_STAT(tx_jabber_irq),
@@ -82,6 +86,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(rx_watchdog_irq),
STMMAC_STAT(tx_early_irq),
STMMAC_STAT(fatal_bus_error_irq),
+ /* Extra info */
STMMAC_STAT(threshold),
STMMAC_STAT(tx_pkt_n),
STMMAC_STAT(rx_pkt_n),
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 96fa2da30763..6ee593a55a64 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -241,7 +241,7 @@ static void stmmac_adjust_link(struct net_device *dev)
case 1000:
if (likely(priv->plat->has_gmac))
ctrl &= ~priv->hw->link.port;
- stmmac_hw_fix_mac_speed(priv);
+ stmmac_hw_fix_mac_speed(priv);
break;
case 100:
case 10:
@@ -785,7 +785,7 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
u32 uid = ((hwid & 0x0000ff00) >> 8);
u32 synid = (hwid & 0x000000ff);
- pr_info("STMMAC - user ID: 0x%x, Synopsys ID: 0x%x\n",
+ pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
uid, synid);
return synid;
@@ -869,38 +869,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
return hw_cap;
}
-/**
- * stmmac_mac_device_setup
- * @dev : device pointer
- * Description: this is to attach the GMAC or MAC 10/100
- * main core structures that will be completed during the
- * open step.
- */
-static int stmmac_mac_device_setup(struct net_device *dev)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
-
- struct mac_device_info *device;
-
- if (priv->plat->has_gmac)
- device = dwmac1000_setup(priv->ioaddr);
- else
- device = dwmac100_setup(priv->ioaddr);
-
- if (!device)
- return -ENOMEM;
-
- priv->hw = device;
- priv->hw->ring = &ring_mode_ops;
-
- if (device_can_wakeup(priv->device)) {
- priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
- enable_irq_wake(priv->wol_irq);
- }
-
- return 0;
-}
-
static void stmmac_check_ether_addr(struct stmmac_priv *priv)
{
/* verify if the MAC address is valid, in case of failures it
@@ -930,20 +898,8 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- /* MAC HW device setup */
- ret = stmmac_mac_device_setup(dev);
- if (ret < 0)
- return ret;
-
stmmac_check_ether_addr(priv);
- stmmac_verify_args();
-
- /* Override with kernel parameters if supplied XXX CRS XXX
- * this needs to have multiple instances */
- if ((phyaddr >= 0) && (phyaddr <= 31))
- priv->plat->phy_addr = phyaddr;
-
/* MDIO bus Registration */
ret = stmmac_mdio_register(dev);
if (ret < 0) {
@@ -976,44 +932,6 @@ static int stmmac_open(struct net_device *dev)
goto open_error;
}
- stmmac_get_synopsys_id(priv);
-
- priv->hw_cap_support = stmmac_get_hw_features(priv);
-
- if (priv->hw_cap_support) {
- pr_info(" Support DMA HW capability register");
-
- /* We can override some gmac/dma configuration fields: e.g.
- * enh_desc, tx_coe (e.g. that are passed through the
- * platform) with the values from the HW capability
- * register (if supported).
- */
- priv->plat->enh_desc = priv->dma_cap.enh_desc;
- priv->plat->tx_coe = priv->dma_cap.tx_coe;
- priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
-
- /* By default disable wol on magic frame if not supported */
- if (!priv->dma_cap.pmt_magic_frame)
- priv->wolopts &= ~WAKE_MAGIC;
-
- } else
- pr_info(" No HW DMA feature register supported");
-
- /* Select the enhnaced/normal descriptor structures */
- stmmac_selec_desc_mode(priv);
-
- /* PMT module is not integrated in all the MAC devices. */
- if (priv->plat->pmt) {
- pr_info(" Remote wake-up capable\n");
- device_set_wakeup_capable(priv->device, 1);
- }
-
- priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
- if (priv->rx_coe)
- pr_info(" Checksum Offload Engine supported\n");
- if (priv->plat->tx_coe)
- pr_info(" Checksum insertion supported\n");
-
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -1030,14 +948,14 @@ static int stmmac_open(struct net_device *dev)
/* Copy the MAC addr into the HW */
priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+
/* If required, perform hw setup of the bus. */
if (priv->plat->bus_setup)
priv->plat->bus_setup(priv->ioaddr);
+
/* Initialize the MAC Core */
priv->hw->mac->core_init(priv->ioaddr);
- netdev_update_features(dev);
-
/* Request the IRQ lines */
ret = request_irq(dev->irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
@@ -1047,6 +965,17 @@ static int stmmac_open(struct net_device *dev)
goto open_error;
}
+ /* Request the Wake IRQ in case of another line is used for WoL */
+ if (priv->wol_irq != dev->irq) {
+ ret = request_irq(priv->wol_irq, stmmac_interrupt,
+ IRQF_SHARED, dev->name, dev);
+ if (unlikely(ret < 0)) {
+ pr_err("%s: ERROR: allocating the ext WoL IRQ %d "
+ "(error: %d)\n", __func__, priv->wol_irq, ret);
+ goto open_error_wolirq;
+ }
+ }
+
/* Enable the MAC Rx/Tx */
stmmac_set_mac(priv->ioaddr, true);
@@ -1062,7 +991,7 @@ static int stmmac_open(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
ret = stmmac_init_fs(dev);
if (ret < 0)
- pr_warning("\tFailed debugFS registration");
+ pr_warning("%s: failed debugFS registration\n", __func__);
#endif
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
@@ -1072,6 +1001,7 @@ static int stmmac_open(struct net_device *dev)
#ifdef CONFIG_STMMAC_TIMER
priv->tm->timer_start(tmrate);
#endif
+
/* Dump DMA/MAC registers */
if (netif_msg_hw(priv)) {
priv->hw->mac->dump_regs(priv->ioaddr);
@@ -1087,6 +1017,9 @@ static int stmmac_open(struct net_device *dev)
return 0;
+open_error_wolirq:
+ free_irq(dev->irq, dev);
+
open_error:
#ifdef CONFIG_STMMAC_TIMER
kfree(priv->tm);
@@ -1127,6 +1060,8 @@ static int stmmac_release(struct net_device *dev)
/* Free the IRQ lines */
free_irq(dev->irq, dev);
+ if (priv->wol_irq != dev->irq)
+ free_irq(priv->wol_irq, dev);
/* Stop TX/RX DMA and clear the descriptors */
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1789,13 +1724,77 @@ static const struct net_device_ops stmmac_netdev_ops = {
};
/**
+ * stmmac_hw_init - Init the MAC device
+ * @priv : pointer to the private device structure.
+ * Description: this function detects which MAC device
+ * (GMAC/MAC10-100) has to attached, checks the HW capability
+ * (if supported) and sets the driver's features (for example
+ * to use the ring or chaine mode or support the normal/enh
+ * descriptor structure).
+ */
+static int stmmac_hw_init(struct stmmac_priv *priv)
+{
+ int ret = 0;
+ struct mac_device_info *mac;
+
+ /* Identify the MAC HW device */
+ if (priv->plat->has_gmac)
+ mac = dwmac1000_setup(priv->ioaddr);
+ else
+ mac = dwmac100_setup(priv->ioaddr);
+ if (!mac)
+ return -ENOMEM;
+
+ priv->hw = mac;
+
+ /* To use the chained or ring mode */
+ priv->hw->ring = &ring_mode_ops;
+
+ /* Get and dump the chip ID */
+ stmmac_get_synopsys_id(priv);
+
+ /* Get the HW capability (new GMAC newer than 3.50a) */
+ priv->hw_cap_support = stmmac_get_hw_features(priv);
+ if (priv->hw_cap_support) {
+ pr_info(" DMA HW capability register supported");
+
+ /* We can override some gmac/dma configuration fields: e.g.
+ * enh_desc, tx_coe (e.g. that are passed through the
+ * platform) with the values from the HW capability
+ * register (if supported).
+ */
+ priv->plat->enh_desc = priv->dma_cap.enh_desc;
+ priv->plat->tx_coe = priv->dma_cap.tx_coe;
+ priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+ } else
+ pr_info(" No HW DMA feature register supported");
+
+ /* Select the enhnaced/normal descriptor structures */
+ stmmac_selec_desc_mode(priv);
+
+ priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+ if (priv->rx_coe)
+ pr_info(" RX Checksum Offload Engine supported\n");
+ if (priv->plat->tx_coe)
+ pr_info(" TX Checksum insertion supported\n");
+
+ if (priv->plat->pmt) {
+ pr_info(" Wake-Up On Lan supported\n");
+ device_set_wakeup_capable(priv->device, 1);
+ }
+
+ return ret;
+}
+
+/**
* stmmac_dvr_probe
* @device: device pointer
* Description: this is the main probe function used to
* call the alloc_etherdev, allocate the priv structure.
*/
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
- struct plat_stmmacenet_data *plat_dat)
+ struct plat_stmmacenet_data *plat_dat,
+ void __iomem *addr)
{
int ret = 0;
struct net_device *ndev = NULL;
@@ -1815,10 +1814,27 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
ether_setup(ndev);
- ndev->netdev_ops = &stmmac_netdev_ops;
stmmac_set_ethtool_ops(ndev);
+ priv->pause = pause;
+ priv->plat = plat_dat;
+ priv->ioaddr = addr;
+ priv->dev->base_addr = (unsigned long)addr;
+
+ /* Verify driver arguments */
+ stmmac_verify_args();
+
+ /* Override with kernel parameters if supplied XXX CRS XXX
+ * this needs to have multiple instances */
+ if ((phyaddr >= 0) && (phyaddr <= 31))
+ priv->plat->phy_addr = phyaddr;
+
+ /* Init MAC and get the capabilities */
+ stmmac_hw_init(priv);
+
+ ndev->netdev_ops = &stmmac_netdev_ops;
- ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM;
ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
@@ -1830,8 +1846,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
- priv->pause = pause;
- priv->plat = plat_dat;
netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
spin_lock_init(&priv->lock);
@@ -1839,15 +1853,10 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
ret = register_netdev(ndev);
if (ret) {
- pr_err("%s: ERROR %i registering the device\n",
- __func__, ret);
+ pr_err("%s: ERROR %i registering the device\n", __func__, ret);
goto error;
}
- DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
- ndev->name, (ndev->features & NETIF_F_SG) ? "on" : "off",
- (ndev->features & NETIF_F_IP_CSUM) ? "on" : "off");
-
return priv;
error:
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index c796de9eed72..50ad5b80cfaf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -96,13 +96,11 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
stmmac_default_data();
- priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat);
+ priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
if (!priv) {
- pr_err("%s: main drivr probe failed", __func__);
+ pr_err("%s: main driver probe failed", __func__);
goto err_out;
}
- priv->ioaddr = addr;
- priv->dev->base_addr = (unsigned long)addr;
priv->dev->irq = pdev->irq;
priv->wol_irq = pdev->irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 1ac83243649a..3aad9810237c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -59,16 +59,20 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
goto out_release_region;
}
plat_dat = pdev->dev.platform_data;
- priv = stmmac_dvr_probe(&(pdev->dev), plat_dat);
+
+ /* Custom initialisation (if needed)*/
+ if (plat_dat->init) {
+ ret = plat_dat->init(pdev);
+ if (unlikely(ret))
+ goto out_unmap;
+ }
+
+ priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
if (!priv) {
- pr_err("%s: main drivr probe failed", __func__);
+ pr_err("%s: main driver probe failed", __func__);
goto out_unmap;
}
- priv->ioaddr = addr;
- /* Set the I/O base addr */
- priv->dev->base_addr = (unsigned long)addr;
-
/* Get the MAC information */
priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
if (priv->dev->irq == -ENXIO) {
@@ -92,13 +96,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv->dev);
- /* Custom initialisation */
- if (priv->plat->init) {
- ret = priv->plat->init(pdev);
- if (unlikely(ret))
- goto out_unmap;
- }
-
pr_debug("STMMAC platform driver registration completed");
return 0;
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 4d9a28ffd3c3..cbc8df78d84b 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1122,7 +1122,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
if (external_switch || dumb_switch) {
- strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
+ strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
} else {
for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@@ -1138,7 +1138,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (phy_id == PHY_MAX_ADDR) {
dev_err(&pdev->dev, "no PHY present, falling back "
"to switch on MDIO bus 0\n");
- strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
+ strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
}
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 794ac30a577b..4fa0bcb25dfc 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1600,8 +1600,9 @@ static int emac_dev_open(struct net_device *ndev)
if (IS_ERR(priv->phydev)) {
dev_err(emac_dev, "could not connect to phy %s\n",
priv->phy_id);
+ ret = PTR_ERR(priv->phydev);
priv->phydev = NULL;
- return PTR_ERR(priv->phydev);
+ return ret;
}
priv->link = 0;
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index ef7c9c17bfff..af8b8fc39eb2 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -318,9 +318,9 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
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);
+ data->clk = NULL;
goto bail_out;
}
diff --git a/drivers/net/ethernet/toshiba/Kconfig b/drivers/net/ethernet/toshiba/Kconfig
index 051764704559..74acb5cf6099 100644
--- a/drivers/net/ethernet/toshiba/Kconfig
+++ b/drivers/net/ethernet/toshiba/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_TOSHIBA
bool "Toshiba devices"
default y
- depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3
+ depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB || MIPS) || PPC_PS3
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 4128d6b8cc28..cb35b14b73bb 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2491,9 +2491,6 @@ static int velocity_close(struct net_device *dev)
if (dev->irq != 0)
free_irq(dev->irq, dev);
- /* Power down the chip */
- pci_set_power_state(vptr->pdev, PCI_D3hot);
-
velocity_free_rings(vptr);
vptr->flags &= (~VELOCITY_FLAGS_OPENED);
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 72a854f05bb8..41a8b5a9849e 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1416,7 +1416,8 @@ static int __devinit eth_init_one(struct platform_device *pdev)
__raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
udelay(50);
- snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
+ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
+ mdio_bus->id, plat->phy);
port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
if (IS_ERR(port->phydev)) {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 1a1ca6cfc74a..466c58a7353d 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -123,7 +123,7 @@ static int netvsc_close(struct net_device *net)
struct hv_device *device_obj = net_device_ctx->device_ctx;
int ret;
- netif_stop_queue(net);
+ netif_tx_disable(net);
ret = rndis_filter_close(device_obj);
if (ret != 0)
@@ -151,10 +151,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
int ret;
unsigned int i, num_pages, npg_data;
- /* Add multipage for skb->data and additional one for RNDIS */
+ /* Add multipages for skb->data and additional 2 for RNDIS */
npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
>> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
- num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1;
+ num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;
/* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
@@ -173,8 +173,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
sizeof(struct hv_netvsc_packet) +
(num_pages * sizeof(struct hv_page_buffer));
- /* Setup the rndis header */
- packet->page_buf_cnt = num_pages;
+ /* If the rndis msg goes beyond 1 page, we will add 1 later */
+ packet->page_buf_cnt = num_pages - 1;
/* Initialize it from the skb */
packet->total_data_buflen = skb->len;
@@ -256,7 +256,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
} else {
netif_carrier_off(net);
- netif_stop_queue(net);
+ netif_tx_disable(net);
}
}
@@ -298,7 +298,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
skb->ip_summed = CHECKSUM_NONE;
net->stats.rx_packets++;
- net->stats.rx_bytes += skb->len;
+ net->stats.rx_bytes += packet->total_data_buflen;
/*
* Pass the skb back up. Network stack will deallocate the skb when it
@@ -337,7 +337,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
nvdev->start_remove = true;
cancel_delayed_work_sync(&ndevctx->dwork);
- netif_stop_queue(ndev);
+ netif_tx_disable(ndev);
rndis_filter_device_remove(hdev);
ndev->mtu = mtu;
@@ -460,7 +460,7 @@ static int netvsc_remove(struct hv_device *dev)
cancel_delayed_work_sync(&ndev_ctx->dwork);
/* Stop outbound asap */
- netif_stop_queue(net);
+ netif_tx_disable(net);
unregister_netdev(net);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index da181f9a49d1..133b7fbf8595 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -321,6 +321,25 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
pkt->total_data_buflen -= data_offset;
+
+ /*
+ * Make sure we got a valid RNDIS message, now total_data_buflen
+ * should be the data packet size plus the trailer padding size
+ */
+ if (pkt->total_data_buflen < rndis_pkt->data_len) {
+ netdev_err(dev->net_dev->ndev, "rndis message buffer "
+ "overflow detected (got %u, min %u)"
+ "...dropping this message!\n",
+ pkt->total_data_buflen, rndis_pkt->data_len);
+ return;
+ }
+
+ /*
+ * Remove the rndis trailer padding from rndis packet message
+ * rndis_pkt->data_len tell us the real data length, we only copy
+ * the data packet to the stack, without the rndis trailer padding
+ */
+ pkt->total_data_buflen = rndis_pkt->data_len;
pkt->data = (void *)((unsigned long)pkt->data + data_offset);
pkt->is_data_pkt = true;
@@ -778,6 +797,19 @@ int rndis_filter_send(struct hv_device *dev,
(unsigned long)rndisMessage & (PAGE_SIZE-1);
pkt->page_buf[0].len = rndisMessageSize;
+ /* Add one page_buf if the rndis msg goes beyond page boundary */
+ if (pkt->page_buf[0].offset + rndisMessageSize > PAGE_SIZE) {
+ int i;
+ for (i = pkt->page_buf_cnt; i > 1; i--)
+ pkt->page_buf[i] = pkt->page_buf[i-1];
+ pkt->page_buf_cnt++;
+ pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
+ pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
+ rndisMessage + pkt->page_buf[0].len)) >> PAGE_SHIFT;
+ pkt->page_buf[1].offset = 0;
+ pkt->page_buf[1].len = rndisMessageSize - pkt->page_buf[0].len;
+ }
+
/* Save the packet send completion and context */
filterPacket->completion = pkt->completion.send.send_completion;
filterPacket->completion_ctx =
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index c7e0149d1514..45550d42b368 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -7,7 +7,6 @@ menuconfig TR
bool "Token Ring driver support"
depends on NETDEVICES && !UML
depends on (PCI || ISA || MCA || CCW || PCMCIA)
- select LLC
help
Token Ring is IBM's way of communication on a local network; the
rest of the world uses Ethernet. To participate on a Token Ring
@@ -20,6 +19,10 @@ menuconfig TR
if TR
+config WANT_LLC
+ def_bool y
+ select LLC
+
config PCMCIA_IBMTR
tristate "IBM PCMCIA tokenring adapter support"
depends on IBMTR!=y && PCMCIA
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index e84662db51cc..dd78c4cbd459 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -60,6 +60,7 @@
#define USB_PRODUCT_IPHONE_3GS 0x1294
#define USB_PRODUCT_IPHONE_4 0x1297
#define USB_PRODUCT_IPHONE_4_VZW 0x129c
+#define USB_PRODUCT_IPHONE_4S 0x12a0
#define IPHETH_USBINTF_CLASS 255
#define IPHETH_USBINTF_SUBCLASS 253
@@ -103,6 +104,10 @@ static struct usb_device_id ipheth_table[] = {
USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
+ { USB_DEVICE_AND_INTERFACE_INFO(
+ USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
+ IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+ IPHETH_USBINTF_PROTO) },
{ }
};
MODULE_DEVICE_TABLE(usb, ipheth_table);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 49f4667e1fa3..4a3402898f2a 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -422,7 +422,9 @@ static void veth_dellink(struct net_device *dev, struct list_head *head)
unregister_netdevice_queue(peer, head);
}
-static const struct nla_policy veth_policy[VETH_INFO_MAX + 1];
+static const struct nla_policy veth_policy[VETH_INFO_MAX + 1] = {
+ [VETH_INFO_PEER] = { .len = sizeof(struct ifinfomsg) },
+};
static struct rtnl_link_ops veth_link_ops = {
.kind = DRV_NAME,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ee7759575050..87db1ee1c298 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
/*
* Workaround for early ACK timeouts, add an offset to match the
- * initval's 64us ack timeout value.
+ * initval's 64us ack timeout value. Use 48us for the CTS timeout.
* This was initially only meant to work around an issue with delayed
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
+ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
acktimeout += 64 - sifstime - ah->slottime;
+ ctstimeout += 48 - sifstime - ah->slottime;
+ }
+
ath9k_hw_set_sifs_time(ah, sifstime);
ath9k_hw_setslottime(ah, slottime);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index abf943557dee..53a005d288aa 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
ARRAY_SIZE(ath9k_tpt_blink));
#endif
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+ INIT_WORK(&sc->hw_check_work, ath_hw_check);
+ INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
@@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
goto error_world;
}
- INIT_WORK(&sc->hw_reset_work, ath_reset_work);
- INIT_WORK(&sc->hw_check_work, ath_hw_check);
- INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
ath_init_leds(sc);
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index b3c3798fe513..635b592ad961 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
return rate;
/* This should not happen */
- WARN_ON(1);
+ WARN_ON_ONCE(1);
rate = ath_rc_priv->valid_rate_index[0];
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0e666fbe0842..7e1a91af1497 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common,
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS));
+ /*
+ * Key miss events are only relevant for pairwise keys where the
+ * descriptor does contain a valid key index. This has been observed
+ * mostly with CCMP encryption.
+ */
+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
+ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
if (!rx_stats->rs_datalen)
return false;
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index c664c2726553..63bbc60be28e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
} else {
+ tx_cmd->tid_tspec = IWL_TID_NON_QOS;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
else
@@ -620,7 +621,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
sta_priv->max_agg_bufsize;
- IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+ IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
sta->addr, tid);
return iwl_send_lq_cmd(priv, ctx,
@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
u32 status = le16_to_cpu(tx_resp->status.status);
int i;
+ WARN_ON(tid == IWL_TID_NON_QOS);
+
if (agg->wait_for_ba)
IWL_DEBUG_TX_REPLY(priv,
"got tx response w/o block-ack\n");
@@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
}
__skb_queue_head_init(&skbs);
- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed;
- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
- next_reclaimed);
+ if (tid != IWL_TID_NON_QOS) {
+ priv->tid_data[sta_id][tid].next_reclaimed =
+ next_reclaimed;
+ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
+ next_reclaimed);
+ }
/*we can free until ssn % q.n_bd not inclusive */
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 265de39d394c..f822ac447c3b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -815,6 +815,7 @@ struct iwl_qosparam_cmd {
#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
+#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 67d6e324e26f..324d06dfb690 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1262,6 +1262,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
txq->time_stamp = jiffies;
if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
+ tid != IWL_TID_NON_QOS &&
txq_id != trans_pcie->agg_txq[sta_id][tid])) {
/*
* FIXME: this is a uCode bug which need to be addressed,
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index e05b417a3fae..1d0ec57a0143 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -382,7 +382,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
adapter->if_ops.cleanup_if(adapter);
- dev_kfree_skb_any(adapter->sleep_cfm);
+ if (adapter->sleep_cfm)
+ dev_kfree_skb_any(adapter->sleep_cfm);
}
/*
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 84be196188cc..b728f54451e4 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -822,7 +822,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
continue;
rtnl_lock();
- mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ if (priv->wdev && priv->netdev)
+ mwifiex_del_virtual_intf(priv->wdev->wiphy,
+ priv->netdev);
rtnl_unlock();
}
@@ -830,9 +832,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
if (!priv)
goto exit_remove;
- wiphy_unregister(priv->wdev->wiphy);
- wiphy_free(priv->wdev->wiphy);
- kfree(priv->wdev);
+ if (priv->wdev) {
+ wiphy_unregister(priv->wdev->wiphy);
+ wiphy_free(priv->wdev->wiphy);
+ kfree(priv->wdev);
+ }
mwifiex_terminate_workqueue(adapter);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 470ca75ec250..b0fbf5d4fea0 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
{
bool cancel_flag = false;
- int status = adapter->cmd_wait_q.status;
+ int status;
struct cmd_ctrl_node *cmd_queued;
if (!adapter->cmd_queued)
@@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
mwifiex_cancel_pending_ioctl(adapter);
dev_dbg(adapter->dev, "cmd cancel\n");
}
+
+ status = adapter->cmd_wait_q.status;
adapter->cmd_wait_q.status = 0;
return status;
@@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
if (!netif_queue_stopped(priv->netdev))
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
@@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
if (!netif_queue_stopped(priv->netdev))
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
if (!ret) {
dev_dbg(adapter->dev, "info: network found in scan"
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 22a1a8fc6e02..7bef66def10c 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
{
- int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
- int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
- int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
+ s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+ s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+ s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
u16 eeprom;
u8 offset0;
u8 offset1;
@@ -552,7 +552,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
* which gives less energy...
*/
rssi0 = max(rssi0, rssi1);
- return max(rssi0, rssi2);
+ return (int)max(rssi0, rssi2);
}
void rt2800_process_rxwi(struct queue_entry *entry,
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 39e0907a3c4e..9245d882c06a 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1501,7 +1501,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
return err;
}
- return 1;
+ return 0;
}
static int rtl_pci_start(struct ieee80211_hw *hw)
@@ -1870,7 +1870,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
}
/* Init PCI sw */
- err = !rtl_pci_init(hw, pdev);
+ err = rtl_pci_init(hw, pdev);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Failed to init PCI.\n"));
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 0a70149df3fc..98a574a4a465 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac,
ZD_ASSERT(frag_len <= 0xffff);
+ /*
+ * Firmware computes the duration itself (for all frames except PSPoll)
+ * and needs the field set to 0 at input, otherwise firmware messes up
+ * duration_id and sets bits 14 and 15 on.
+ */
+ if (!ieee80211_is_pspoll(hdr->frame_control))
+ hdr->duration_id = 0;
+
txrate = ieee80211_get_tx_rate(mac->hw, info);
cs->modulation = txrate->hw_value;
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 0321fa3b4226..0dab5ecf61bb 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -347,8 +347,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return rc;
}
- pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
-
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
@@ -466,6 +464,7 @@ found:
return -EIO;
pgsz &= ~(pgsz - 1);
+ pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 7cc9e2f0f47c..71eac9cd724d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -651,6 +651,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
secondary, subordinate, pass);
+ if (!primary && (primary != bus->number) && secondary && subordinate) {
+ dev_warn(&dev->dev, "Primary bus is hard wired to 0\n");
+ primary = bus->number;
+ }
+
/* Check if setup is sensible at all */
if (!pass &&
(primary != bus->number || secondary <= bus->number)) {
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 6def3624c688..ef8b18c48f26 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -77,6 +77,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
}
EXPORT_SYMBOL(pci_remove_bus);
+static void __pci_remove_behind_bridge(struct pci_dev *dev);
/**
* pci_remove_bus_device - remove a PCI device and any children
* @dev: the device to remove
@@ -94,7 +95,7 @@ static void __pci_remove_bus_device(struct pci_dev *dev)
if (dev->subordinate) {
struct pci_bus *b = dev->subordinate;
- pci_remove_behind_bridge(dev);
+ __pci_remove_behind_bridge(dev);
pci_remove_bus(b);
dev->subordinate = NULL;
}
@@ -107,6 +108,24 @@ void pci_remove_bus_device(struct pci_dev *dev)
__pci_remove_bus_device(dev);
}
+static void __pci_remove_behind_bridge(struct pci_dev *dev)
+{
+ struct list_head *l, *n;
+
+ if (dev->subordinate)
+ list_for_each_safe(l, n, &dev->subordinate->devices)
+ __pci_remove_bus_device(pci_dev_b(l));
+}
+
+static void pci_stop_behind_bridge(struct pci_dev *dev)
+{
+ struct list_head *l, *n;
+
+ if (dev->subordinate)
+ list_for_each_safe(l, n, &dev->subordinate->devices)
+ pci_stop_bus_device(pci_dev_b(l));
+}
+
/**
* pci_remove_behind_bridge - remove all devices behind a PCI bridge
* @dev: PCI bridge device
@@ -117,11 +136,8 @@ void pci_remove_bus_device(struct pci_dev *dev)
*/
void pci_remove_behind_bridge(struct pci_dev *dev)
{
- struct list_head *l, *n;
-
- if (dev->subordinate)
- list_for_each_safe(l, n, &dev->subordinate->devices)
- __pci_remove_bus_device(pci_dev_b(l));
+ pci_stop_behind_bridge(dev);
+ __pci_remove_behind_bridge(dev);
}
static void pci_stop_bus_devices(struct pci_bus *bus)
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 7cf3d2fcf56a..1620088a0e7e 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -189,7 +189,7 @@ static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
if (verbose_request)
dev_info(&pdev->xdev->dev,
- "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
+ "read dev=%04x:%02x:%02x.%d - offset %x size %d\n",
pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where, size);
@@ -228,7 +228,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
if (verbose_request)
dev_info(&pdev->xdev->dev,
- "write dev=%04x:%02x:%02x.%01x - "
+ "write dev=%04x:%02x:%02x.%d - "
"offset %x size %d val %x\n",
pci_domain_nr(bus), bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
@@ -432,7 +432,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
d = pci_scan_single_device(b, devfn);
if (d)
dev_info(&pdev->xdev->dev, "New device on "
- "%04x:%02x:%02x.%02x found.\n", domain, bus,
+ "%04x:%02x:%02x.%d found.\n", domain, bus,
PCI_SLOT(devfn), PCI_FUNC(devfn));
}
@@ -1041,7 +1041,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func));
if (!pci_dev) {
dev_dbg(&pdev->xdev->dev,
- "Cannot get PCI device %04x:%02x:%02x.%02x\n",
+ "Cannot get PCI device %04x:%02x:%02x.%d\n",
domain, bus, slot, func);
continue;
}
@@ -1049,7 +1049,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
pci_dev_put(pci_dev);
dev_dbg(&pdev->xdev->dev,
- "PCI device %04x:%02x:%02x.%02x removed.\n",
+ "PCI device %04x:%02x:%02x.%d removed.\n",
domain, bus, slot, func);
}
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 749c2a16012c..1932029de48d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt)
static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
{
- if (!verify_cis_cache(skt)) {
- pcmcia_put_socket(skt);
+ if (!verify_cis_cache(skt))
return 0;
- }
dev_dbg(&skt->dev, "cis mismatch - different card\n");
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 8fe15cf15ac8..894cd5e103da 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -189,7 +189,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
pindesc->pctldev = pctldev;
/* Copy basic pin info */
- if (pindesc->name) {
+ if (name) {
pindesc->name = name;
} else {
pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 98bf5676318d..1ed6ea0bad6e 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -62,11 +62,10 @@
#define BQ27500_REG_SOC 0x2C
#define BQ27500_REG_DCAP 0x3C /* Design capacity */
-#define BQ27500_FLAG_DSG BIT(0) /* Discharging */
+#define BQ27500_FLAG_DSC BIT(0)
#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
-#define BQ27500_FLAG_CHG BIT(8) /* Charging */
-#define BQ27500_FLAG_FC BIT(9) /* Fully charged */
+#define BQ27500_FLAG_FC BIT(9)
#define BQ27000_RS 20 /* Resistor sense */
@@ -312,7 +311,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
struct bq27x00_reg_cache cache = {0, };
bool is_bq27500 = di->chip == BQ27500;
- cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
+ cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
if (cache.flags >= 0) {
if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
@@ -401,14 +400,10 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
if (di->chip == BQ27500) {
if (di->cache.flags & BQ27500_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
- else if (di->cache.flags & BQ27500_FLAG_DSG)
+ else if (di->cache.flags & BQ27500_FLAG_DSC)
status = POWER_SUPPLY_STATUS_DISCHARGING;
- else if (di->cache.flags & BQ27500_FLAG_CHG)
- status = POWER_SUPPLY_STATUS_CHARGING;
- else if (power_supply_am_i_supplied(&di->bat))
- status = POWER_SUPPLY_STATUS_NOT_CHARGING;
else
- status = POWER_SUPPLY_STATUS_UNKNOWN;
+ status = POWER_SUPPLY_STATUS_CHARGING;
} else {
if (di->cache.flags & BQ27000_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 0378d019efae..88fd9710bda2 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -974,10 +974,11 @@ static int __devexit charger_manager_remove(struct platform_device *pdev)
return 0;
}
-const struct platform_device_id charger_manager_id[] = {
+static const struct platform_device_id charger_manager_id[] = {
{ "charger-manager", 0 },
{ },
};
+MODULE_DEVICE_TABLE(platform, charger_manager_id);
static int cm_suspend_prepare(struct device *dev)
{
@@ -1069,4 +1070,3 @@ module_exit(charger_manager_cleanup);
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
MODULE_DESCRIPTION("Charger Manager");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("charger-manager");
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index b15b575c070c..c53dd1292f81 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -464,6 +464,7 @@ static int __devexit lp8727_remove(struct i2c_client *cl)
static const struct i2c_device_id lp8727_ids[] = {
{"lp8727", 0},
+ { }
};
static struct i2c_driver lp8727_driver = {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e9a83f84adaf..aa5186608aec 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1320,6 +1320,40 @@ struct regulator *regulator_get(struct device *dev, const char *id)
}
EXPORT_SYMBOL_GPL(regulator_get);
+static void devm_regulator_release(struct device *dev, void *res)
+{
+ regulator_put(*(struct regulator **)res);
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+ struct regulator **ptr, *regulator;
+
+ ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ regulator = regulator_get(dev, id);
+ if (!IS_ERR(regulator)) {
+ *ptr = regulator;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return regulator;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
/**
* regulator_get_exclusive - obtain exclusive access to a regulator.
* @dev: device for regulator "consumer"
@@ -1387,6 +1421,34 @@ void regulator_put(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_put);
+static int devm_regulator_match(struct device *dev, void *res, void *data)
+{
+ struct regulator **r = res;
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+ return *r == data;
+}
+
+/**
+ * devm_regulator_put - Resource managed regulator_put()
+ * @regulator: regulator to free
+ *
+ * Deallocate a regulator allocated with devm_regulator_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_regulator_put(struct regulator *regulator)
+{
+ int rc;
+
+ rc = devres_destroy(regulator->dev, devm_regulator_release,
+ devm_regulator_match, regulator);
+ WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_put);
+
static int _regulator_can_change_status(struct regulator_dev *rdev)
{
if (!rdev->constraints)
@@ -2401,6 +2463,52 @@ err:
}
EXPORT_SYMBOL_GPL(regulator_bulk_get);
+/**
+ * devm_regulator_bulk_get - managed get multiple regulator consumers
+ *
+ * @dev: Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers: Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation with management, the regulators will
+ * automatically be freed when the device is unbound. If any of the
+ * regulators cannot be acquired then any regulators that were
+ * allocated will be freed before returning to the caller.
+ */
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < num_consumers; i++)
+ consumers[i].consumer = NULL;
+
+ for (i = 0; i < num_consumers; i++) {
+ consumers[i].consumer = devm_regulator_get(dev,
+ consumers[i].supply);
+ if (IS_ERR(consumers[i].consumer)) {
+ ret = PTR_ERR(consumers[i].consumer);
+ dev_err(dev, "Failed to get supply '%s': %d\n",
+ consumers[i].supply, ret);
+ consumers[i].consumer = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+ devm_regulator_put(consumers[i].consumer);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
{
struct regulator_bulk_data *bulk = data;
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index b06a2399587c..d0e1180ad961 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -150,7 +150,7 @@ static int max8649_enable_time(struct regulator_dev *rdev)
if (ret != 0)
return ret;
val &= MAX8649_VOL_MASK;
- voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */
+ voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */
/* get rate */
ret = regmap_read(info->regmap, MAX8649_RAMP, &val);
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 80ecafef1bc3..62dcd0a432bb 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -254,6 +254,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
return num;
}
+EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
@@ -291,6 +292,7 @@ struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
return data;
}
+EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt);
#endif
MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index a3ad957507dc..ee3c122c0599 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -307,8 +307,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
platform_set_drvdata(pdev, rtc);
- rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
- rtc->rtt += r->start;
+ rtc->rtt = ioremap(r->start, resource_size(r));
+ if (!rtc->rtt) {
+ dev_err(&pdev->dev, "failed to map registers, aborting.\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
mr = rtt_readl(rtc, MR);
@@ -326,7 +330,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
&at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtcdev)) {
ret = PTR_ERR(rtc->rtcdev);
- goto fail;
+ goto fail_register;
}
/* register irq handler after we know what name we'll use */
@@ -351,6 +355,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
return 0;
+fail_register:
+ iounmap(rtc->rtt);
fail:
platform_set_drvdata(pdev, NULL);
kfree(rtc);
@@ -371,6 +377,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
rtc_device_unregister(rtc->rtcdev);
+ iounmap(rtc->rtt);
platform_set_drvdata(pdev, NULL);
kfree(rtc);
return 0;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3f9a47ec67dc..8293658e7cf9 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -299,7 +299,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
- depends on (ARCH_S3C64XX || ARCH_S5P64X0)
+ depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
select S3C64XX_DMA if ARCH_S3C64XX
help
SPI driver for Samsung S3C64XX and newer SoCs.
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 2a6429d8c363..10182eb50068 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1720,7 +1720,7 @@ static int pch_spi_resume(struct pci_dev *pdev)
#endif
-static struct pci_driver pch_spi_pcidev = {
+static struct pci_driver pch_spi_pcidev_driver = {
.name = "pch_spi",
.id_table = pch_spi_pcidev_id,
.probe = pch_spi_probe,
@@ -1736,7 +1736,7 @@ static int __init pch_spi_init(void)
if (ret)
return ret;
- ret = pci_register_driver(&pch_spi_pcidev);
+ ret = pci_register_driver(&pch_spi_pcidev_driver);
if (ret)
return ret;
@@ -1746,7 +1746,7 @@ module_init(pch_spi_init);
static void __exit pch_spi_exit(void)
{
- pci_unregister_driver(&pch_spi_pcidev);
+ pci_unregister_driver(&pch_spi_pcidev_driver);
platform_driver_unregister(&pch_spi_pd_driver);
}
module_exit(pch_spi_exit);
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 520e8286db28..49d209173f55 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
u32 tmp;
/* We do only have one cardbus device behind the bridge. */
- if (pc->cardbusmode && (dev >= 1))
+ if (pc->cardbusmode && (dev > 1))
goto out;
if (bus == 0) {
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 21e2f4b87f14..9e6347249783 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -60,8 +60,6 @@ source "drivers/staging/rts5139/Kconfig"
source "drivers/staging/frontier/Kconfig"
-source "drivers/staging/pohmelfs/Kconfig"
-
source "drivers/staging/phison/Kconfig"
source "drivers/staging/line6/Kconfig"
@@ -120,8 +118,6 @@ source "drivers/staging/cptm1217/Kconfig"
source "drivers/staging/ste_rmi4/Kconfig"
-source "drivers/staging/gma500/Kconfig"
-
source "drivers/staging/mei/Kconfig"
source "drivers/staging/nvec/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 7c5808d7212d..943e14830753 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
obj-$(CONFIG_RTS5139) += rts5139/
obj-$(CONFIG_TRANZPORT) += frontier/
-obj-$(CONFIG_POHMELFS) += pohmelfs/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
@@ -52,7 +51,6 @@ obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
-obj-$(CONFIG_DRM_PSB) += gma500/
obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_DRM_OMAP) += omapdrm/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index becf711117ef..fef3580ce8de 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -27,6 +27,7 @@ config ANDROID_LOGGER
config ANDROID_RAM_CONSOLE
bool "Android RAM buffer console"
+ depends on !S390 && !UML
default n
config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
@@ -99,10 +100,6 @@ config ANDROID_LOW_MEMORY_KILLER
---help---
Register processes to be killed when memory is low
-config ANDROID_PMEM
- bool "Android pmem allocator"
- depends on ARM
-
source "drivers/staging/android/switch/Kconfig"
endif # if ANDROID
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index eaed1ff64f0f..5fcc24ffdd58 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -5,5 +5,4 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
-obj-$(CONFIG_ANDROID_PMEM) += pmem.o
obj-$(CONFIG_ANDROID_SWITCH) += switch/
diff --git a/drivers/staging/android/android_pmem.h b/drivers/staging/android/android_pmem.h
deleted file mode 100644
index f633621f5be3..000000000000
--- a/drivers/staging/android/android_pmem.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* include/linux/android_pmem.h
- *
- * Copyright (C) 2007 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 _ANDROID_PMEM_H_
-#define _ANDROID_PMEM_H_
-
-#define PMEM_IOCTL_MAGIC 'p'
-#define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
-#define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
-#define PMEM_GET_SIZE _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
-#define PMEM_UNMAP _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
-/* This ioctl will allocate pmem space, backing the file, it will fail
- * if the file already has an allocation, pass it the len as the argument
- * to the ioctl */
-#define PMEM_ALLOCATE _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
-/* This will connect a one pmem file to another, pass the file that is already
- * backed in memory as the argument to the ioctl
- */
-#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
-/* Returns the total size of the pmem region it is sent to as a pmem_region
- * struct (with offset set to 0).
- */
-#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
-#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
-
-struct android_pmem_platform_data
-{
- const char* name;
- /* starting physical address of memory region */
- unsigned long start;
- /* size of memory region */
- unsigned long size;
- /* set to indicate the region should not be managed with an allocator */
- unsigned no_allocator;
- /* set to indicate maps of this region should be cached, if a mix of
- * cached and uncached is desired, set this and open the device with
- * O_SYNC to get an uncached region */
- unsigned cached;
- /* The MSM7k has bits to enable a write buffer in the bus controller*/
- unsigned buffered;
-};
-
-struct pmem_region {
- unsigned long offset;
- unsigned long len;
-};
-
-#ifdef CONFIG_ANDROID_PMEM
-int is_pmem_file(struct file *file);
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
- unsigned long *end, struct file **filp);
-int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *end);
-void put_pmem_file(struct file* file);
-void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
-int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *));
-int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation);
-
-#else
-static inline int is_pmem_file(struct file *file) { return 0; }
-static inline int get_pmem_file(int fd, unsigned long *start,
- unsigned long *vstart, unsigned long *end,
- struct file **filp) { return -ENOSYS; }
-static inline int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *end) { return -ENOSYS; }
-static inline void put_pmem_file(struct file* file) { return; }
-static inline void flush_pmem_file(struct file *file, unsigned long start,
- unsigned long len) { return; }
-static inline int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *)) { return -ENOSYS; }
-
-static inline int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation) { return -ENOSYS; }
-#endif
-
-#endif //_ANDROID_PPP_H_
-
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 7491801a661c..f0b7e6605ab5 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -38,6 +38,7 @@
static DEFINE_MUTEX(binder_lock);
static DEFINE_MUTEX(binder_deferred_lock);
+static DEFINE_MUTEX(binder_mmap_lock);
static HLIST_HEAD(binder_procs);
static HLIST_HEAD(binder_deferred_list);
@@ -632,6 +633,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
if (mm) {
down_write(&mm->mmap_sem);
vma = proc->vma;
+ if (vma && mm != vma->vm_mm) {
+ pr_err("binder: %d: vma mm and task mm mismatch\n",
+ proc->pid);
+ vma = NULL;
+ }
}
if (allocate == 0)
@@ -2759,7 +2765,6 @@ static void binder_vma_open(struct vm_area_struct *vma)
proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
- dump_stack();
}
static void binder_vma_close(struct vm_area_struct *vma)
@@ -2803,6 +2808,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
}
vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
+ mutex_lock(&binder_mmap_lock);
if (proc->buffer) {
ret = -EBUSY;
failure_string = "already mapped";
@@ -2817,6 +2823,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
}
proc->buffer = area->addr;
proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
+ mutex_unlock(&binder_mmap_lock);
#ifdef CONFIG_CPU_CACHE_VIPT
if (cache_is_vipt_aliasing()) {
@@ -2849,7 +2856,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
binder_insert_free_buffer(proc, buffer);
proc->free_async_space = proc->buffer_size / 2;
barrier();
- proc->files = get_files_struct(current);
+ proc->files = get_files_struct(proc->tsk);
proc->vma = vma;
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
@@ -2860,10 +2867,12 @@ err_alloc_small_buf_failed:
kfree(proc->pages);
proc->pages = NULL;
err_alloc_pages_failed:
+ mutex_lock(&binder_mmap_lock);
vfree(proc->buffer);
proc->buffer = NULL;
err_get_vm_area_failed:
err_already_mapped:
+ mutex_unlock(&binder_mmap_lock);
err_bad_arg:
printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 2d8d2b796101..efc7dc1f4831 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -54,6 +54,7 @@ static size_t lowmem_minfree[6] = {
static int lowmem_minfree_size = 4;
static struct task_struct *lowmem_deathpending;
+static unsigned long lowmem_deathpending_timeout;
#define lowmem_print(level, x...) \
do { \
@@ -103,7 +104,8 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
* Note: Currently you need CONFIG_PROFILING
* for this to work correctly.
*/
- if (lowmem_deathpending)
+ if (lowmem_deathpending &&
+ time_before_eq(jiffies, lowmem_deathpending_timeout))
return 0;
if (lowmem_adj_size < array_size)
@@ -178,6 +180,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
*/
#ifdef CONFIG_PROFILING
lowmem_deathpending = selected;
+ lowmem_deathpending_timeout = jiffies + HZ;
task_handoff_register(&task_nb);
#endif
force_sig(SIGKILL, selected);
diff --git a/drivers/staging/android/pmem.c b/drivers/staging/android/pmem.c
deleted file mode 100644
index 7d97032c6508..000000000000
--- a/drivers/staging/android/pmem.c
+++ /dev/null
@@ -1,1345 +0,0 @@
-/* pmem.c
- *
- * Copyright (C) 2007 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.
- *
- */
-
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/debugfs.h>
-#include <linux/mempolicy.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/cacheflush.h>
-#include "android_pmem.h"
-
-#define PMEM_MAX_DEVICES 10
-#define PMEM_MAX_ORDER 128
-#define PMEM_MIN_ALLOC PAGE_SIZE
-
-#define PMEM_DEBUG 1
-
-/* indicates that a refernce to this file has been taken via get_pmem_file,
- * the file should not be released until put_pmem_file is called */
-#define PMEM_FLAGS_BUSY 0x1
-/* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
-/* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
-/* submap and unsubmap flags indicate:
- * 00: subregion has never been mmaped
- * 10: subregion has been mmaped, reference to the mm was taken
- * 11: subretion has ben released, refernece to the mm still held
- * 01: subretion has been released, reference to the mm has been released
- */
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
-
-
-struct pmem_data {
- /* in alloc mode: an index into the bitmap
- * in no_alloc mode: the size of the allocation */
- int index;
- /* see flags above for descriptions */
- unsigned int flags;
- /* protects this data field, if the mm_mmap sem will be held at the
- * same time as this sem, the mm sem must be taken first (as this is
- * the order for vma_open and vma_close ops */
- struct rw_semaphore sem;
- /* info about the mmaping process */
- struct vm_area_struct *vma;
- /* task struct of the mapping process */
- struct task_struct *task;
- /* process id of teh mapping process */
- pid_t pid;
- /* file descriptor of the master */
- int master_fd;
- /* file struct of the master */
- struct file *master_file;
- /* a list of currently available regions if this is a suballocation */
- struct list_head region_list;
- /* a linked list of data so we can access them for debugging */
- struct list_head list;
-#if PMEM_DEBUG
- int ref;
-#endif
-};
-
-struct pmem_bits {
- unsigned allocated:1; /* 1 if allocated, 0 if free */
- unsigned order:7; /* size of the region in pmem space */
-};
-
-struct pmem_region_node {
- struct pmem_region region;
- struct list_head list;
-};
-
-#define PMEM_DEBUG_MSGS 0
-#if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
- do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
- ##args); } \
- while (0)
-#else
-#define DLOG(x...) do {} while (0)
-#endif
-
-struct pmem_info {
- struct miscdevice dev;
- /* physical start address of the remaped pmem space */
- unsigned long base;
- /* vitual start address of the remaped pmem space */
- unsigned char __iomem *vbase;
- /* total size of the pmem space */
- unsigned long size;
- /* number of entries in the pmem space */
- unsigned long num_entries;
- /* pfn of the garbage page in memory */
- unsigned long garbage_pfn;
- /* index of the garbage page in the pmem space */
- int garbage_index;
- /* the bitmap for the region indicating which entries are allocated
- * and which are free */
- struct pmem_bits *bitmap;
- /* indicates the region should not be managed with an allocator */
- unsigned no_allocator;
- /* indicates maps of this region should be cached, if a mix of
- * cached and uncached is desired, set this and open the device with
- * O_SYNC to get an uncached region */
- unsigned cached;
- unsigned buffered;
- /* in no_allocator mode the first mapper gets the whole space and sets
- * this flag */
- unsigned allocated;
- /* for debugging, creates a list of pmem file structs, the
- * data_list_lock should be taken before pmem_data->sem if both are
- * needed */
- struct mutex data_list_lock;
- struct list_head data_list;
- /* pmem_sem protects the bitmap array
- * a write lock should be held when modifying entries in bitmap
- * a read lock should be held when reading data from bits or
- * dereferencing a pointer into bitmap
- *
- * pmem_data->sem protects the pmem data of a particular file
- * Many of the function that require the pmem_data->sem have a non-
- * locking version for when the caller is already holding that sem.
- *
- * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
- * down(pmem_data->sem) => down(bitmap_sem)
- */
- struct rw_semaphore bitmap_sem;
-
- long (*ioctl)(struct file *, unsigned int, unsigned long);
- int (*release)(struct inode *, struct file *);
-};
-
-static struct pmem_info pmem[PMEM_MAX_DEVICES];
-static int id_count;
-
-#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
-#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
-#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
-#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
-#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC)
-#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base)
-#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC)
-#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \
- PMEM_LEN(id, index))
-#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase)
-#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \
- PMEM_LEN(id, index))
-#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
-#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
-#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \
- (!(data->flags & PMEM_FLAGS_UNSUBMAP)))
-
-static int pmem_release(struct inode *, struct file *);
-static int pmem_mmap(struct file *, struct vm_area_struct *);
-static int pmem_open(struct inode *, struct file *);
-static long pmem_ioctl(struct file *, unsigned int, unsigned long);
-
-struct file_operations pmem_fops = {
- .release = pmem_release,
- .mmap = pmem_mmap,
- .open = pmem_open,
- .unlocked_ioctl = pmem_ioctl,
-};
-
-static int get_id(struct file *file)
-{
- return MINOR(file->f_dentry->d_inode->i_rdev);
-}
-
-int is_pmem_file(struct file *file)
-{
- int id;
-
- if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
- return 0;
- id = get_id(file);
- if (unlikely(id >= PMEM_MAX_DEVICES))
- return 0;
- if (unlikely(file->f_dentry->d_inode->i_rdev !=
- MKDEV(MISC_MAJOR, pmem[id].dev.minor)))
- return 0;
- return 1;
-}
-
-static int has_allocation(struct file *file)
-{
- struct pmem_data *data;
- /* check is_pmem_file first if not accessed via pmem_file_ops */
-
- if (unlikely(!file->private_data))
- return 0;
- data = (struct pmem_data *)file->private_data;
- if (unlikely(data->index < 0))
- return 0;
- return 1;
-}
-
-static int is_master_owner(struct file *file)
-{
- struct file *master_file;
- struct pmem_data *data;
- int put_needed, ret = 0;
-
- if (!is_pmem_file(file) || !has_allocation(file))
- return 0;
- data = (struct pmem_data *)file->private_data;
- if (PMEM_FLAGS_MASTERMAP & data->flags)
- return 1;
- master_file = fget_light(data->master_fd, &put_needed);
- if (master_file && data->master_file == master_file)
- ret = 1;
- fput_light(master_file, put_needed);
- return ret;
-}
-
-static int pmem_free(int id, int index)
-{
- /* caller should hold the write lock on pmem_sem! */
- int buddy, curr = index;
- DLOG("index %d\n", index);
-
- if (pmem[id].no_allocator) {
- pmem[id].allocated = 0;
- return 0;
- }
- /* clean up the bitmap, merging any buddies */
- pmem[id].bitmap[curr].allocated = 0;
- /* find a slots buddy Buddy# = Slot# ^ (1 << order)
- * if the buddy is also free merge them
- * repeat until the buddy is not free or end of the bitmap is reached
- */
- do {
- buddy = PMEM_BUDDY_INDEX(id, curr);
- if (PMEM_IS_FREE(id, buddy) &&
- PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) {
- PMEM_ORDER(id, buddy)++;
- PMEM_ORDER(id, curr)++;
- curr = min(buddy, curr);
- } else {
- break;
- }
- } while (curr < pmem[id].num_entries);
-
- return 0;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data);
-
-static int pmem_release(struct inode *inode, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- struct pmem_region_node *region_node;
- struct list_head *elt, *elt2;
- int id = get_id(file), ret = 0;
-
-
- mutex_lock(&pmem[id].data_list_lock);
- /* if this file is a master, revoke all the memory in the connected
- * files */
- if (PMEM_FLAGS_MASTERMAP & data->flags) {
- struct pmem_data *sub_data;
- list_for_each(elt, &pmem[id].data_list) {
- sub_data = list_entry(elt, struct pmem_data, list);
- down_read(&sub_data->sem);
- if (PMEM_IS_SUBMAP(sub_data) &&
- file == sub_data->master_file) {
- up_read(&sub_data->sem);
- pmem_revoke(file, sub_data);
- } else
- up_read(&sub_data->sem);
- }
- }
- list_del(&data->list);
- mutex_unlock(&pmem[id].data_list_lock);
-
-
- down_write(&data->sem);
-
- /* if its not a conencted file and it has an allocation, free it */
- if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
- down_write(&pmem[id].bitmap_sem);
- ret = pmem_free(id, data->index);
- up_write(&pmem[id].bitmap_sem);
- }
-
- /* if this file is a submap (mapped, connected file), downref the
- * task struct */
- if (PMEM_FLAGS_SUBMAP & data->flags)
- if (data->task) {
- put_task_struct(data->task);
- data->task = NULL;
- }
-
- file->private_data = NULL;
-
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node, list);
- list_del(elt);
- kfree(region_node);
- }
- BUG_ON(!list_empty(&data->region_list));
-
- up_write(&data->sem);
- kfree(data);
- if (pmem[id].release)
- ret = pmem[id].release(inode, file);
-
- return ret;
-}
-
-static int pmem_open(struct inode *inode, struct file *file)
-{
- struct pmem_data *data;
- int id = get_id(file);
- int ret = 0;
-
- DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file));
- /* setup file->private_data to indicate its unmapped */
- /* you can only open a pmem device one time */
- if (file->private_data != NULL)
- return -1;
- data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
- if (!data) {
- printk("pmem: unable to allocate memory for pmem metadata.");
- return -1;
- }
- data->flags = 0;
- data->index = -1;
- data->task = NULL;
- data->vma = NULL;
- data->pid = 0;
- data->master_file = NULL;
-#if PMEM_DEBUG
- data->ref = 0;
-#endif
- INIT_LIST_HEAD(&data->region_list);
- init_rwsem(&data->sem);
-
- file->private_data = data;
- INIT_LIST_HEAD(&data->list);
-
- mutex_lock(&pmem[id].data_list_lock);
- list_add(&data->list, &pmem[id].data_list);
- mutex_unlock(&pmem[id].data_list_lock);
- return ret;
-}
-
-static unsigned long pmem_order(unsigned long len)
-{
- int i;
-
- len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC;
- len--;
- for (i = 0; i < sizeof(len)*8; i++)
- if (len >> i == 0)
- break;
- return i;
-}
-
-static int pmem_allocate(int id, unsigned long len)
-{
- /* caller should hold the write lock on pmem_sem! */
- /* return the corresponding pdata[] entry */
- int curr = 0;
- int end = pmem[id].num_entries;
- int best_fit = -1;
- unsigned long order = pmem_order(len);
-
- if (pmem[id].no_allocator) {
- DLOG("no allocator");
- if ((len > pmem[id].size) || pmem[id].allocated)
- return -1;
- pmem[id].allocated = 1;
- return len;
- }
-
- if (order > PMEM_MAX_ORDER)
- return -1;
- DLOG("order %lx\n", order);
-
- /* look through the bitmap:
- * if you find a free slot of the correct order use it
- * otherwise, use the best fit (smallest with size > order) slot
- */
- while (curr < end) {
- if (PMEM_IS_FREE(id, curr)) {
- if (PMEM_ORDER(id, curr) == (unsigned char)order) {
- /* set the not free bit and clear others */
- best_fit = curr;
- break;
- }
- if (PMEM_ORDER(id, curr) > (unsigned char)order &&
- (best_fit < 0 ||
- PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit)))
- best_fit = curr;
- }
- curr = PMEM_NEXT_INDEX(id, curr);
- }
-
- /* if best_fit < 0, there are no suitable slots,
- * return an error
- */
- if (best_fit < 0) {
- printk("pmem: no space left to allocate!\n");
- return -1;
- }
-
- /* now partition the best fit:
- * split the slot into 2 buddies of order - 1
- * repeat until the slot is of the correct order
- */
- while (PMEM_ORDER(id, best_fit) > (unsigned char)order) {
- int buddy;
- PMEM_ORDER(id, best_fit) -= 1;
- buddy = PMEM_BUDDY_INDEX(id, best_fit);
- PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit);
- }
- pmem[id].bitmap[best_fit].allocated = 1;
- return best_fit;
-}
-
-static pgprot_t pmem_access_prot(struct file *file, pgprot_t vma_prot)
-{
- int id = get_id(file);
-#ifdef pgprot_noncached
- if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
- return pgprot_noncached(vma_prot);
-#endif
-#ifdef pgprot_ext_buffered
- else if (pmem[id].buffered)
- return pgprot_ext_buffered(vma_prot);
-#endif
- return vma_prot;
-}
-
-static unsigned long pmem_start_addr(int id, struct pmem_data *data)
-{
- if (pmem[id].no_allocator)
- return PMEM_START_ADDR(id, 0);
- else
- return PMEM_START_ADDR(id, data->index);
-
-}
-
-static void *pmem_start_vaddr(int id, struct pmem_data *data)
-{
- return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase;
-}
-
-static unsigned long pmem_len(int id, struct pmem_data *data)
-{
- if (pmem[id].no_allocator)
- return data->index;
- else
- return PMEM_LEN(id, data->index);
-}
-
-static int pmem_map_garbage(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- int i, garbage_pages = len >> PAGE_SHIFT;
-
- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
- for (i = 0; i < garbage_pages; i++) {
- if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
- pmem[id].garbage_pfn))
- return -EAGAIN;
- }
- return 0;
-}
-
-static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- int garbage_pages;
- DLOG("unmap offset %lx len %lx\n", offset, len);
-
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
-
- garbage_pages = len >> PAGE_SHIFT;
- zap_page_range(vma, vma->vm_start + offset, len, NULL);
- pmem_map_garbage(id, vma, data, offset, len);
- return 0;
-}
-
-static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- DLOG("map offset %lx len %lx\n", offset, len);
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
- BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
-
- if (io_remap_pfn_range(vma, vma->vm_start + offset,
- (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT,
- len, vma->vm_page_prot)) {
- return -EAGAIN;
- }
- return 0;
-}
-
-static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
- struct pmem_data *data, unsigned long offset,
- unsigned long len)
-{
- /* hold the mm semp for the vma you are modifying when you call this */
- BUG_ON(!vma);
- zap_page_range(vma, vma->vm_start + offset, len, NULL);
- return pmem_map_pfn_range(id, vma, data, offset, len);
-}
-
-static void pmem_vma_open(struct vm_area_struct *vma)
-{
- struct file *file = vma->vm_file;
- struct pmem_data *data = file->private_data;
- int id = get_id(file);
- /* this should never be called as we don't support copying pmem
- * ranges via fork */
- BUG_ON(!has_allocation(file));
- down_write(&data->sem);
- /* remap the garbage pages, forkers don't get access to the data */
- pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
- up_write(&data->sem);
-}
-
-static void pmem_vma_close(struct vm_area_struct *vma)
-{
- struct file *file = vma->vm_file;
- struct pmem_data *data = file->private_data;
-
- DLOG("current %u ppid %u file %p count %d\n", current->pid,
- current->parent->pid, file, file_count(file));
- if (unlikely(!is_pmem_file(file) || !has_allocation(file))) {
- printk(KERN_WARNING "pmem: something is very wrong, you are "
- "closing a vm backing an allocation that doesn't "
- "exist!\n");
- return;
- }
- down_write(&data->sem);
- if (data->vma == vma) {
- data->vma = NULL;
- if ((data->flags & PMEM_FLAGS_CONNECTED) &&
- (data->flags & PMEM_FLAGS_SUBMAP))
- data->flags |= PMEM_FLAGS_UNSUBMAP;
- }
- /* the kernel is going to free this vma now anyway */
- up_write(&data->sem);
-}
-
-static struct vm_operations_struct vm_ops = {
- .open = pmem_vma_open,
- .close = pmem_vma_close,
-};
-
-static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct pmem_data *data;
- int index;
- unsigned long vma_size = vma->vm_end - vma->vm_start;
- int ret = 0, id = get_id(file);
-
- if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
-#if PMEM_DEBUG
- printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned"
- " and a multiple of pages_size.\n");
-#endif
- return -EINVAL;
- }
-
- data = (struct pmem_data *)file->private_data;
- down_write(&data->sem);
- /* check this file isn't already mmaped, for submaps check this file
- * has never been mmaped */
- if ((data->flags & PMEM_FLAGS_SUBMAP) ||
- (data->flags & PMEM_FLAGS_UNSUBMAP)) {
-#if PMEM_DEBUG
- printk(KERN_ERR "pmem: you can only mmap a pmem file once, "
- "this file is already mmaped. %x\n", data->flags);
-#endif
- ret = -EINVAL;
- goto error;
- }
- /* if file->private_data == unalloced, alloc*/
- if (data && data->index == -1) {
- down_write(&pmem[id].bitmap_sem);
- index = pmem_allocate(id, vma->vm_end - vma->vm_start);
- up_write(&pmem[id].bitmap_sem);
- data->index = index;
- }
- /* either no space was available or an error occured */
- if (!has_allocation(file)) {
- ret = -EINVAL;
- printk("pmem: could not find allocation for map.\n");
- goto error;
- }
-
- if (pmem_len(id, data) < vma_size) {
-#if PMEM_DEBUG
- printk(KERN_WARNING "pmem: mmap size [%lu] does not match"
- "size of backing region [%lu].\n", vma_size,
- pmem_len(id, data));
-#endif
- ret = -EINVAL;
- goto error;
- }
-
- vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT;
- vma->vm_page_prot = pmem_access_prot(file, vma->vm_page_prot);
-
- if (data->flags & PMEM_FLAGS_CONNECTED) {
- struct pmem_region_node *region_node;
- struct list_head *elt;
- if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
- printk("pmem: mmap failed in kernel!\n");
- ret = -EAGAIN;
- goto error;
- }
- list_for_each(elt, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- DLOG("remapping file: %p %lx %lx\n", file,
- region_node->region.offset,
- region_node->region.len);
- if (pmem_remap_pfn_range(id, vma, data,
- region_node->region.offset,
- region_node->region.len)) {
- ret = -EAGAIN;
- goto error;
- }
- }
- data->flags |= PMEM_FLAGS_SUBMAP;
- get_task_struct(current->group_leader);
- data->task = current->group_leader;
- data->vma = vma;
-#if PMEM_DEBUG
- data->pid = current->pid;
-#endif
- DLOG("submmapped file %p vma %p pid %u\n", file, vma,
- current->pid);
- } else {
- if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
- printk(KERN_INFO "pmem: mmap failed in kernel!\n");
- ret = -EAGAIN;
- goto error;
- }
- data->flags |= PMEM_FLAGS_MASTERMAP;
- data->pid = current->pid;
- }
- vma->vm_ops = &vm_ops;
-error:
- up_write(&data->sem);
- return ret;
-}
-
-/* the following are the api for accessing pmem regions by other drivers
- * from inside the kernel */
-int get_pmem_user_addr(struct file *file, unsigned long *start,
- unsigned long *len)
-{
- struct pmem_data *data;
- if (!is_pmem_file(file) || !has_allocation(file)) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: requested pmem data from invalid"
- "file.\n");
-#endif
- return -1;
- }
- data = (struct pmem_data *)file->private_data;
- down_read(&data->sem);
- if (data->vma) {
- *start = data->vma->vm_start;
- *len = data->vma->vm_end - data->vma->vm_start;
- } else {
- *start = 0;
- *len = 0;
- }
- up_read(&data->sem);
- return 0;
-}
-
-int get_pmem_addr(struct file *file, unsigned long *start,
- unsigned long *vstart, unsigned long *len)
-{
- struct pmem_data *data;
- int id;
-
- if (!is_pmem_file(file) || !has_allocation(file)) {
- return -1;
- }
-
- data = (struct pmem_data *)file->private_data;
- if (data->index == -1) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: requested pmem data from file with no "
- "allocation.\n");
- return -1;
-#endif
- }
- id = get_id(file);
-
- down_read(&data->sem);
- *start = pmem_start_addr(id, data);
- *len = pmem_len(id, data);
- *vstart = (unsigned long)pmem_start_vaddr(id, data);
- up_read(&data->sem);
-#if PMEM_DEBUG
- down_write(&data->sem);
- data->ref++;
- up_write(&data->sem);
-#endif
- return 0;
-}
-
-int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
- unsigned long *len, struct file **filp)
-{
- struct file *file;
-
- file = fget(fd);
- if (unlikely(file == NULL)) {
- printk(KERN_INFO "pmem: requested data from file descriptor "
- "that doesn't exist.");
- return -1;
- }
-
- if (get_pmem_addr(file, start, vstart, len))
- goto end;
-
- if (filp)
- *filp = file;
- return 0;
-end:
- fput(file);
- return -1;
-}
-
-void put_pmem_file(struct file *file)
-{
- struct pmem_data *data;
- int id;
-
- if (!is_pmem_file(file))
- return;
- id = get_id(file);
- data = (struct pmem_data *)file->private_data;
-#if PMEM_DEBUG
- down_write(&data->sem);
- if (data->ref == 0) {
- printk("pmem: pmem_put > pmem_get %s (pid %d)\n",
- pmem[id].dev.name, data->pid);
- BUG();
- }
- data->ref--;
- up_write(&data->sem);
-#endif
- fput(file);
-}
-
-void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
-{
- struct pmem_data *data;
- int id;
- void *vaddr;
- struct pmem_region_node *region_node;
- struct list_head *elt;
- void *flush_start, *flush_end;
-
- if (!is_pmem_file(file) || !has_allocation(file)) {
- return;
- }
-
- id = get_id(file);
- data = (struct pmem_data *)file->private_data;
- if (!pmem[id].cached || file->f_flags & O_SYNC)
- return;
-
- down_read(&data->sem);
- vaddr = pmem_start_vaddr(id, data);
- /* if this isn't a submmapped file, flush the whole thing */
- if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
- dmac_flush_range(vaddr, vaddr + pmem_len(id, data));
- goto end;
- }
- /* otherwise, flush the region of the file we are drawing */
- list_for_each(elt, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node, list);
- if ((offset >= region_node->region.offset) &&
- ((offset + len) <= (region_node->region.offset +
- region_node->region.len))) {
- flush_start = vaddr + region_node->region.offset;
- flush_end = flush_start + region_node->region.len;
- dmac_flush_range(flush_start, flush_end);
- break;
- }
- }
-end:
- up_read(&data->sem);
-}
-
-static int pmem_connect(unsigned long connect, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- struct pmem_data *src_data;
- struct file *src_file;
- int ret = 0, put_needed;
-
- down_write(&data->sem);
- /* retrieve the src file and check it is a pmem file with an alloc */
- src_file = fget_light(connect, &put_needed);
- DLOG("connect %p to %p\n", file, src_file);
- if (!src_file) {
- printk("pmem: src file not found!\n");
- ret = -EINVAL;
- goto err_no_file;
- }
- if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) {
- printk(KERN_INFO "pmem: src file is not a pmem file or has no "
- "alloc!\n");
- ret = -EINVAL;
- goto err_bad_file;
- }
- src_data = (struct pmem_data *)src_file->private_data;
-
- if (has_allocation(file) && (data->index != src_data->index)) {
- printk("pmem: file is already mapped but doesn't match this"
- " src_file!\n");
- ret = -EINVAL;
- goto err_bad_file;
- }
- data->index = src_data->index;
- data->flags |= PMEM_FLAGS_CONNECTED;
- data->master_fd = connect;
- data->master_file = src_file;
-
-err_bad_file:
- fput_light(src_file, put_needed);
-err_no_file:
- up_write(&data->sem);
- return ret;
-}
-
-static void pmem_unlock_data_and_mm(struct pmem_data *data,
- struct mm_struct *mm)
-{
- up_write(&data->sem);
- if (mm != NULL) {
- up_write(&mm->mmap_sem);
- mmput(mm);
- }
-}
-
-static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
- struct mm_struct **locked_mm)
-{
- int ret = 0;
- struct mm_struct *mm = NULL;
- *locked_mm = NULL;
-lock_mm:
- down_read(&data->sem);
- if (PMEM_IS_SUBMAP(data)) {
- mm = get_task_mm(data->task);
- if (!mm) {
-#if PMEM_DEBUG
- printk("pmem: can't remap task is gone!\n");
-#endif
- up_read(&data->sem);
- return -1;
- }
- }
- up_read(&data->sem);
-
- if (mm)
- down_write(&mm->mmap_sem);
-
- down_write(&data->sem);
- /* check that the file didn't get mmaped before we could take the
- * data sem, this should be safe b/c you can only submap each file
- * once */
- if (PMEM_IS_SUBMAP(data) && !mm) {
- pmem_unlock_data_and_mm(data, mm);
- up_write(&data->sem);
- goto lock_mm;
- }
- /* now check that vma.mm is still there, it could have been
- * deleted by vma_close before we could get the data->sem */
- if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
- /* might as well release this */
- if (data->flags & PMEM_FLAGS_SUBMAP) {
- put_task_struct(data->task);
- data->task = NULL;
- /* lower the submap flag to show the mm is gone */
- data->flags &= ~(PMEM_FLAGS_SUBMAP);
- }
- pmem_unlock_data_and_mm(data, mm);
- return -1;
- }
- *locked_mm = mm;
- return ret;
-}
-
-int pmem_remap(struct pmem_region *region, struct file *file,
- unsigned operation)
-{
- int ret;
- struct pmem_region_node *region_node;
- struct mm_struct *mm = NULL;
- struct list_head *elt, *elt2;
- int id = get_id(file);
- struct pmem_data *data = (struct pmem_data *)file->private_data;
-
- /* pmem region must be aligned on a page boundry */
- if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
- !PMEM_IS_PAGE_ALIGNED(region->len))) {
-#if PMEM_DEBUG
- printk("pmem: request for unaligned pmem suballocation "
- "%lx %lx\n", region->offset, region->len);
-#endif
- return -EINVAL;
- }
-
- /* if userspace requests a region of len 0, there's nothing to do */
- if (region->len == 0)
- return 0;
-
- /* lock the mm and data */
- ret = pmem_lock_data_and_mm(file, data, &mm);
- if (ret)
- return 0;
-
- /* only the owner of the master file can remap the client fds
- * that back in it */
- if (!is_master_owner(file)) {
-#if PMEM_DEBUG
- printk("pmem: remap requested from non-master process\n");
-#endif
- ret = -EINVAL;
- goto err;
- }
-
- /* check that the requested range is within the src allocation */
- if (unlikely((region->offset > pmem_len(id, data)) ||
- (region->len > pmem_len(id, data)) ||
- (region->offset + region->len > pmem_len(id, data)))) {
-#if PMEM_DEBUG
- printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n");
-#endif
- ret = -EINVAL;
- goto err;
- }
-
- if (operation == PMEM_MAP) {
- region_node = kmalloc(sizeof(struct pmem_region_node),
- GFP_KERNEL);
- if (!region_node) {
- ret = -ENOMEM;
-#if PMEM_DEBUG
- printk(KERN_INFO "No space to allocate metadata!");
-#endif
- goto err;
- }
- region_node->region = *region;
- list_add(&region_node->list, &data->region_list);
- } else if (operation == PMEM_UNMAP) {
- int found = 0;
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- if (region->len == 0 ||
- (region_node->region.offset == region->offset &&
- region_node->region.len == region->len)) {
- list_del(elt);
- kfree(region_node);
- found = 1;
- }
- }
- if (!found) {
-#if PMEM_DEBUG
- printk("pmem: Unmap region does not map any mapped "
- "region!");
-#endif
- ret = -EINVAL;
- goto err;
- }
- }
-
- if (data->vma && PMEM_IS_SUBMAP(data)) {
- if (operation == PMEM_MAP)
- ret = pmem_remap_pfn_range(id, data->vma, data,
- region->offset, region->len);
- else if (operation == PMEM_UNMAP)
- ret = pmem_unmap_pfn_range(id, data->vma, data,
- region->offset, region->len);
- }
-
-err:
- pmem_unlock_data_and_mm(data, mm);
- return ret;
-}
-
-static void pmem_revoke(struct file *file, struct pmem_data *data)
-{
- struct pmem_region_node *region_node;
- struct list_head *elt, *elt2;
- struct mm_struct *mm = NULL;
- int id = get_id(file);
- int ret = 0;
-
- data->master_file = NULL;
- ret = pmem_lock_data_and_mm(file, data, &mm);
- /* if lock_data_and_mm fails either the task that mapped the fd, or
- * the vma that mapped it have already gone away, nothing more
- * needs to be done */
- if (ret)
- return;
- /* unmap everything */
- /* delete the regions and region list nothing is mapped any more */
- if (data->vma)
- list_for_each_safe(elt, elt2, &data->region_list) {
- region_node = list_entry(elt, struct pmem_region_node,
- list);
- pmem_unmap_pfn_range(id, data->vma, data,
- region_node->region.offset,
- region_node->region.len);
- list_del(elt);
- kfree(region_node);
- }
- /* delete the master file */
- pmem_unlock_data_and_mm(data, mm);
-}
-
-static void pmem_get_size(struct pmem_region *region, struct file *file)
-{
- struct pmem_data *data = (struct pmem_data *)file->private_data;
- int id = get_id(file);
-
- if (!has_allocation(file)) {
- region->offset = 0;
- region->len = 0;
- return;
- } else {
- region->offset = pmem_start_addr(id, data);
- region->len = pmem_len(id, data);
- }
- DLOG("offset %lx len %lx\n", region->offset, region->len);
-}
-
-
-static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct pmem_data *data;
- int id = get_id(file);
-
- switch (cmd) {
- case PMEM_GET_PHYS:
- {
- struct pmem_region region;
- DLOG("get_phys\n");
- if (!has_allocation(file)) {
- region.offset = 0;
- region.len = 0;
- } else {
- data = (struct pmem_data *)file->private_data;
- region.offset = pmem_start_addr(id, data);
- region.len = pmem_len(id, data);
- }
- printk(KERN_INFO "pmem: request for physical address of pmem region "
- "from process %d.\n", current->pid);
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_MAP:
- {
- struct pmem_region region;
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- data = (struct pmem_data *)file->private_data;
- return pmem_remap(&region, file, PMEM_MAP);
- }
- break;
- case PMEM_UNMAP:
- {
- struct pmem_region region;
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- data = (struct pmem_data *)file->private_data;
- return pmem_remap(&region, file, PMEM_UNMAP);
- break;
- }
- case PMEM_GET_SIZE:
- {
- struct pmem_region region;
- DLOG("get_size\n");
- pmem_get_size(&region, file);
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_GET_TOTAL_SIZE:
- {
- struct pmem_region region;
- DLOG("get total size\n");
- region.offset = 0;
- get_id(file);
- region.len = pmem[id].size;
- if (copy_to_user((void __user *)arg, &region,
- sizeof(struct pmem_region)))
- return -EFAULT;
- break;
- }
- case PMEM_ALLOCATE:
- {
- if (has_allocation(file))
- return -EINVAL;
- data = (struct pmem_data *)file->private_data;
- data->index = pmem_allocate(id, arg);
- break;
- }
- case PMEM_CONNECT:
- DLOG("connect\n");
- return pmem_connect(arg, file);
- break;
- case PMEM_CACHE_FLUSH:
- {
- struct pmem_region region;
- DLOG("flush\n");
- if (copy_from_user(&region, (void __user *)arg,
- sizeof(struct pmem_region)))
- return -EFAULT;
- flush_pmem_file(file, region.offset, region.len);
- break;
- }
- default:
- if (pmem[id].ioctl)
- return pmem[id].ioctl(file, cmd, arg);
- return -EINVAL;
- }
- return 0;
-}
-
-#if PMEM_DEBUG
-static ssize_t debug_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct list_head *elt, *elt2;
- struct pmem_data *data;
- struct pmem_region_node *region_node;
- int id = (int)file->private_data;
- const int debug_bufmax = 4096;
- static char buffer[4096];
- int n = 0;
-
- DLOG("debug open\n");
- n = scnprintf(buffer, debug_bufmax,
- "pid #: mapped regions (offset, len) (offset,len)...\n");
-
- mutex_lock(&pmem[id].data_list_lock);
- list_for_each(elt, &pmem[id].data_list) {
- data = list_entry(elt, struct pmem_data, list);
- down_read(&data->sem);
- n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:",
- data->pid);
- list_for_each(elt2, &data->region_list) {
- region_node = list_entry(elt2, struct pmem_region_node,
- list);
- n += scnprintf(buffer + n, debug_bufmax - n,
- "(%lx,%lx) ",
- region_node->region.offset,
- region_node->region.len);
- }
- n += scnprintf(buffer + n, debug_bufmax - n, "\n");
- up_read(&data->sem);
- }
- mutex_unlock(&pmem[id].data_list_lock);
-
- n++;
- buffer[n] = 0;
- return simple_read_from_buffer(buf, count, ppos, buffer, n);
-}
-
-static struct file_operations debug_fops = {
- .read = debug_read,
- .open = debug_open,
-};
-#endif
-
-#if 0
-static struct miscdevice pmem_dev = {
- .name = "pmem",
- .fops = &pmem_fops,
-};
-#endif
-
-int pmem_setup(struct android_pmem_platform_data *pdata,
- long (*ioctl)(struct file *, unsigned int, unsigned long),
- int (*release)(struct inode *, struct file *))
-{
- int err = 0;
- int i, index = 0;
- int id = id_count;
- id_count++;
-
- pmem[id].no_allocator = pdata->no_allocator;
- pmem[id].cached = pdata->cached;
- pmem[id].buffered = pdata->buffered;
- pmem[id].base = pdata->start;
- pmem[id].size = pdata->size;
- pmem[id].ioctl = ioctl;
- pmem[id].release = release;
- init_rwsem(&pmem[id].bitmap_sem);
- mutex_init(&pmem[id].data_list_lock);
- INIT_LIST_HEAD(&pmem[id].data_list);
- pmem[id].dev.name = pdata->name;
- pmem[id].dev.minor = id;
- pmem[id].dev.fops = &pmem_fops;
- printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached);
-
- err = misc_register(&pmem[id].dev);
- if (err) {
- printk(KERN_ALERT "Unable to register pmem driver!\n");
- goto err_cant_register_device;
- }
- pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC;
-
- pmem[id].bitmap = kmalloc(pmem[id].num_entries *
- sizeof(struct pmem_bits), GFP_KERNEL);
- if (!pmem[id].bitmap)
- goto err_no_mem_for_metadata;
-
- memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) *
- pmem[id].num_entries);
-
- for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) {
- if ((pmem[id].num_entries) & 1<<i) {
- PMEM_ORDER(id, index) = i;
- index = PMEM_NEXT_INDEX(id, index);
- }
- }
-
- if (pmem[id].cached)
- pmem[id].vbase = ioremap_cached(pmem[id].base,
- pmem[id].size);
-#ifdef ioremap_ext_buffered
- else if (pmem[id].buffered)
- pmem[id].vbase = ioremap_ext_buffered(pmem[id].base,
- pmem[id].size);
-#endif
- else
- pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size);
-
- if (pmem[id].vbase == 0)
- goto error_cant_remap;
-
- pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
- if (pmem[id].no_allocator)
- pmem[id].allocated = 0;
-
-#if PMEM_DEBUG
- debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id,
- &debug_fops);
-#endif
- return 0;
-error_cant_remap:
- kfree(pmem[id].bitmap);
-err_no_mem_for_metadata:
- misc_deregister(&pmem[id].dev);
-err_cant_register_device:
- return -1;
-}
-
-static int pmem_probe(struct platform_device *pdev)
-{
- struct android_pmem_platform_data *pdata;
-
- if (!pdev || !pdev->dev.platform_data) {
- printk(KERN_ALERT "Unable to probe pmem!\n");
- return -1;
- }
- pdata = pdev->dev.platform_data;
- return pmem_setup(pdata, NULL, NULL);
-}
-
-
-static int pmem_remove(struct platform_device *pdev)
-{
- int id = pdev->id;
- __free_page(pfn_to_page(pmem[id].garbage_pfn));
- misc_deregister(&pmem[id].dev);
- return 0;
-}
-
-static struct platform_driver pmem_driver = {
- .probe = pmem_probe,
- .remove = pmem_remove,
- .driver = { .name = "android_pmem" }
-};
-
-
-static int __init pmem_init(void)
-{
- return platform_driver_register(&pmem_driver);
-}
-
-static void __exit pmem_exit(void)
-{
- platform_driver_unregister(&pmem_driver);
-}
-
-module_init(pmem_init);
-module_exit(pmem_exit);
-
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index e77e4e0396cf..1df9586f2730 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -355,7 +355,14 @@ static void send_data(struct asus_oled_dev *odev)
static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
{
- while (count-- > 0 && val) {
+ odev->last_val = val;
+
+ if (val == 0) {
+ odev->buf_offs += count;
+ return 0;
+ }
+
+ while (count-- > 0) {
size_t x = odev->buf_offs % odev->width;
size_t y = odev->buf_offs / odev->width;
size_t i;
@@ -406,7 +413,6 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
;
}
- odev->last_val = val;
odev->buf_offs++;
}
@@ -805,10 +811,9 @@ error:
static void __exit asus_oled_exit(void)
{
+ usb_deregister(&oled_driver);
class_remove_file(oled_class, &class_attr_version.attr);
class_destroy(oled_class);
-
- usb_deregister(&oled_driver);
}
module_init(asus_oled_init);
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
deleted file mode 100644
index c7a2b3bc0a18..000000000000
--- a/drivers/staging/gma500/Kconfig
+++ /dev/null
@@ -1,33 +0,0 @@
-config DRM_PSB
- tristate "Intel GMA5/600 KMS Framebuffer"
- depends on DRM && PCI && X86 && BROKEN
- select FB_CFB_COPYAREA
- select FB_CFB_FILLRECT
- select FB_CFB_IMAGEBLIT
- select DRM_KMS_HELPER
- select DRM_TTM
- help
- Say yes for an experimental 2D KMS framebuffer driver for the
- Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
- devices.
-
-config DRM_PSB_MRST
- bool "Intel GMA600 support (Experimental)"
- depends on DRM_PSB
- help
- Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
- platforms with LVDS ports. HDMI and MIPI are not currently
- supported.
-
-config DRM_PSB_MFLD
- bool "Intel Medfield support (Experimental)"
- depends on DRM_PSB
- help
- Say yes to include support for Intel Medfield platforms with MIPI
- interfaces.
-
-config DRM_PSB_CDV
- bool "Intel Cedarview support (Experimental)"
- depends on DRM_PSB
- help
- Say yes to include support for Intel Cedarview platforms
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
deleted file mode 100644
index c729868b1b10..000000000000
--- a/drivers/staging/gma500/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# KMS driver for the GMA500
-#
-ccflags-y += -Iinclude/drm
-
-psb_gfx-y += gem_glue.o \
- accel_2d.o \
- backlight.o \
- framebuffer.o \
- gem.o \
- gtt.o \
- intel_bios.o \
- intel_i2c.o \
- intel_opregion.o \
- mmu.o \
- power.o \
- psb_drv.o \
- psb_intel_display.o \
- psb_intel_lvds.o \
- psb_intel_modes.o \
- psb_intel_sdvo.o \
- psb_lid.o \
- psb_irq.o \
- psb_device.o \
- mid_bios.o
-
-psb_gfx-$(CONFIG_DRM_PSB_CDV) += cdv_device.o \
- cdv_intel_crt.o \
- cdv_intel_display.o \
- cdv_intel_hdmi.o \
- cdv_intel_lvds.o
-
-psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
- mrst_crtc.o \
- mrst_lvds.o \
- mrst_hdmi.o \
- mrst_hdmi_i2c.o
-
-psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
- mdfld_output.o \
- mdfld_pyr_cmd.o \
- mdfld_tmd_vid.o \
- mdfld_tpo_cmd.o \
- mdfld_tpo_vid.o \
- mdfld_dsi_pkg_sender.o \
- mdfld_dsi_dpi.o \
- mdfld_dsi_output.o \
- mdfld_dsi_dbi.o \
- mdfld_dsi_dbi_dpu.o \
- mdfld_intel_display.o
-
-obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO
deleted file mode 100644
index fc836158e74c..000000000000
--- a/drivers/staging/gma500/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-- Sort out the power management side. Not important for Poulsbo but
- matters for Moorestown/Medfield
-- Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst,
- some other differences)
-- Add 2D acceleration via console and DRM
-- Add scrolling acceleration using the GTT to do remapping on the main
- framebuffer.
-- HDMI testing
-- Oaktrail HDMI and other features
-- Oaktrail MIPI
-- Medfield needs a lot of further love
-
-As per kernel policy and the in the interest of the safety of various
-kittens there is no support or plans to add hooks for the closed user space
-stuff.
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
deleted file mode 100644
index b8f78ebbb145..000000000000
--- a/drivers/staging/gma500/accel_2d.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "framebuffer.h"
-
-/**
- * psb_spank - reset the 2D engine
- * @dev_priv: our PSB DRM device
- *
- * Soft reset the graphics engine and then reload the necessary registers.
- * We use this at initialisation time but it will become relevant for
- * accelerated X later
- */
-void psb_spank(struct drm_psb_private *dev_priv)
-{
- PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
- _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
- _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
- _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
- PSB_RSGX32(PSB_CR_SOFT_RESET);
-
- msleep(1);
-
- PSB_WSGX32(0, PSB_CR_SOFT_RESET);
- wmb();
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
- PSB_CR_BIF_CTRL);
- wmb();
- (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-
- msleep(1);
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
- PSB_CR_BIF_CTRL);
- (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
- PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-}
-
-/**
- * psb2_2d_wait_available - wait for FIFO room
- * @dev_priv: our DRM device
- * @size: size (in dwords) of the command we want to issue
- *
- * Wait until there is room to load the FIFO with our data. If the
- * device is not responding then reset it
- */
-static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
- unsigned size)
-{
- uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
- unsigned long t = jiffies + HZ;
-
- while (avail < size) {
- avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
- if (time_after(jiffies, t)) {
- psb_spank(dev_priv);
- return -EIO;
- }
- }
- return 0;
-}
-
-/**
- * psb_2d_submit - submit a 2D command
- * @dev_priv: our DRM device
- * @cmdbuf: command to issue
- * @size: length (in dwords)
- *
- * Issue one or more 2D commands to the accelerator. This needs to be
- * serialized later when we add the GEM interfaces for acceleration
- */
-static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
- unsigned size)
-{
- int ret = 0;
- int i;
- unsigned submit_size;
- unsigned long flags;
-
- spin_lock_irqsave(&dev_priv->lock_2d, flags);
- while (size > 0) {
- submit_size = (size < 0x60) ? size : 0x60;
- size -= submit_size;
- ret = psb_2d_wait_available(dev_priv, submit_size);
- if (ret)
- break;
-
- submit_size <<= 2;
-
- for (i = 0; i < submit_size; i += 4)
- PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-
- (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
- }
- spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
- return ret;
-}
-
-
-/**
- * psb_accel_2d_copy_direction - compute blit order
- * @xdir: X direction of move
- * @ydir: Y direction of move
- *
- * Compute the correct order setings to ensure that an overlapping blit
- * correctly copies all the pixels.
- */
-static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
-{
- if (xdir < 0)
- return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
- PSB_2D_COPYORDER_TR2BL;
- else
- return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
- PSB_2D_COPYORDER_TL2BR;
-}
-
-/**
- * psb_accel_2d_copy - accelerated 2D copy
- * @dev_priv: our DRM device
- * @src_offset in bytes
- * @src_stride in bytes
- * @src_format psb 2D format defines
- * @dst_offset in bytes
- * @dst_stride in bytes
- * @dst_format psb 2D format defines
- * @src_x offset in pixels
- * @src_y offset in pixels
- * @dst_x offset in pixels
- * @dst_y offset in pixels
- * @size_x of the copied area
- * @size_y of the copied area
- *
- * Format and issue a 2D accelerated copy command.
- */
-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
- uint32_t src_offset, uint32_t src_stride,
- uint32_t src_format, uint32_t dst_offset,
- uint32_t dst_stride, uint32_t dst_format,
- uint16_t src_x, uint16_t src_y,
- uint16_t dst_x, uint16_t dst_y,
- uint16_t size_x, uint16_t size_y)
-{
- uint32_t blit_cmd;
- uint32_t buffer[10];
- uint32_t *buf;
- uint32_t direction;
-
- buf = buffer;
-
- direction =
- psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
-
- if (direction == PSB_2D_COPYORDER_BR2TL ||
- direction == PSB_2D_COPYORDER_TR2BL) {
- src_x += size_x - 1;
- dst_x += size_x - 1;
- }
- if (direction == PSB_2D_COPYORDER_BR2TL ||
- direction == PSB_2D_COPYORDER_BL2TR) {
- src_y += size_y - 1;
- dst_y += size_y - 1;
- }
-
- blit_cmd =
- PSB_2D_BLIT_BH |
- PSB_2D_ROT_NONE |
- PSB_2D_DSTCK_DISABLE |
- PSB_2D_SRCCK_DISABLE |
- PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
-
- *buf++ = PSB_2D_FENCE_BH;
- *buf++ =
- PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
- PSB_2D_DST_STRIDE_SHIFT);
- *buf++ = dst_offset;
- *buf++ =
- PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
- PSB_2D_SRC_STRIDE_SHIFT);
- *buf++ = src_offset;
- *buf++ =
- PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
- (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
- *buf++ = blit_cmd;
- *buf++ =
- (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
- PSB_2D_DST_YSTART_SHIFT);
- *buf++ =
- (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
- PSB_2D_DST_YSIZE_SHIFT);
- *buf++ = PSB_2D_FLUSH_BH;
-
- return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-/**
- * psbfb_copyarea_accel - copyarea acceleration for /dev/fb
- * @info: our framebuffer
- * @a: copyarea parameters from the framebuffer core
- *
- * Perform a 2D copy via the accelerator
- */
-static void psbfb_copyarea_accel(struct fb_info *info,
- const struct fb_copyarea *a)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
- struct drm_psb_private *dev_priv = dev->dev_private;
- uint32_t offset;
- uint32_t stride;
- uint32_t src_format;
- uint32_t dst_format;
-
- if (!fb)
- return;
-
- offset = psbfb->gtt->offset;
- stride = fb->pitches[0];
-
- switch (fb->depth) {
- case 8:
- src_format = PSB_2D_SRC_332RGB;
- dst_format = PSB_2D_DST_332RGB;
- break;
- case 15:
- src_format = PSB_2D_SRC_555RGB;
- dst_format = PSB_2D_DST_555RGB;
- break;
- case 16:
- src_format = PSB_2D_SRC_565RGB;
- dst_format = PSB_2D_DST_565RGB;
- break;
- case 24:
- case 32:
- /* this is wrong but since we don't do blending its okay */
- src_format = PSB_2D_SRC_8888ARGB;
- dst_format = PSB_2D_DST_8888ARGB;
- break;
- default:
- /* software fallback */
- cfb_copyarea(info, a);
- return;
- }
-
- if (!gma_power_begin(dev, false)) {
- cfb_copyarea(info, a);
- return;
- }
- psb_accel_2d_copy(dev_priv,
- offset, stride, src_format,
- offset, stride, dst_format,
- a->sx, a->sy, a->dx, a->dy, a->width, a->height);
- gma_power_end(dev);
-}
-
-/**
- * psbfb_copyarea - 2D copy interface
- * @info: our framebuffer
- * @region: region to copy
- *
- * Copy an area of the framebuffer console either by the accelerator
- * or directly using the cfb helpers according to the request
- */
-void psbfb_copyarea(struct fb_info *info,
- const struct fb_copyarea *region)
-{
- if (unlikely(info->state != FBINFO_STATE_RUNNING))
- return;
-
- /* Avoid the 8 pixel erratum */
- if (region->width == 8 || region->height == 8 ||
- (info->flags & FBINFO_HWACCEL_DISABLED))
- return cfb_copyarea(info, region);
-
- psbfb_copyarea_accel(info, region);
-}
-
-/**
- * psbfb_sync - synchronize 2D
- * @info: our framebuffer
- *
- * Wait for the 2D engine to quiesce so that we can do CPU
- * access to the framebuffer again
- */
-int psbfb_sync(struct fb_info *info)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long _end = jiffies + DRM_HZ;
- int busy = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&dev_priv->lock_2d, flags);
- /*
- * First idle the 2D engine.
- */
-
- if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
- ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
- goto out;
-
- do {
- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
- cpu_relax();
- } while (busy && !time_after_eq(jiffies, _end));
-
- if (busy)
- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
- if (busy)
- goto out;
-
- do {
- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
- _PSB_C2B_STATUS_BUSY) != 0);
- cpu_relax();
- } while (busy && !time_after_eq(jiffies, _end));
- if (busy)
- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
- _PSB_C2B_STATUS_BUSY) != 0);
-
-out:
- spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
- return (busy) ? -EBUSY : 0;
-}
-
-int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_psb_2d_op *op = data;
- u32 *op_ptr = &op->cmd[0];
- int i;
- struct drm_gem_object *obj;
- struct gtt_range *gtt;
- int err = -EINVAL;
-
- if (!dev_priv->ops->accel_2d)
- return -EOPNOTSUPP;
- if (op->size > PSB_2D_OP_BUFLEN)
- return -EINVAL;
-
- /* The GEM object being used. We need to support separate src/dst/etc
- in the end but for now keep them all the same */
- obj = drm_gem_object_lookup(dev, file, op->src);
- if (obj == NULL)
- return -ENOENT;
- gtt = container_of(obj, struct gtt_range, gem);
-
- if (psb_gtt_pin(gtt) < 0)
- goto bad_2;
- for (i = 0; i < op->size; i++, op_ptr++) {
- u32 r = *op_ptr & 0xF0000000;
- /* Fill in the GTT offsets for the command buffer */
- if (r == PSB_2D_SRC_SURF_BH ||
- r == PSB_2D_DST_SURF_BH ||
- r == PSB_2D_MASK_SURF_BH ||
- r == PSB_2D_PAT_SURF_BH) {
- i++;
- op_ptr++;
- if (i == op->size)
- goto bad;
- if (*op_ptr)
- goto bad;
- *op_ptr = gtt->offset;
- continue;
- }
- }
- psbfb_2d_submit(dev_priv, op->cmd, op->size);
- err = 0;
-bad:
- psb_gtt_unpin(gtt);
-bad_2:
- drm_gem_object_unreference(obj);
- return err;
-}
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
deleted file mode 100644
index 20793951fcac..000000000000
--- a/drivers/staging/gma500/backlight.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * GMA500 Backlight Interface
- *
- * Copyright (c) 2009-2011, Intel Corporation.
- *
- * 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.
- *
- * Authors: Eric Knopp
- *
- */
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "intel_bios.h"
-#include "power.h"
-
-int gma_backlight_init(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
- return dev_priv->ops->backlight_init(dev);
-#else
- return 0;
-#endif
-}
-
-void gma_backlight_exit(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->backlight_device) {
- dev_priv->backlight_device->props.brightness = 0;
- backlight_update_status(dev_priv->backlight_device);
- backlight_device_unregister(dev_priv->backlight_device);
- }
-#endif
-}
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
deleted file mode 100644
index 8ec10caab13e..000000000000
--- a/drivers/staging/gma500/cdv_device.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "cdv_device.h"
-
-#define VGA_SR_INDEX 0x3c4
-#define VGA_SR_DATA 0x3c5
-
-static void cdv_disable_vga(struct drm_device *dev)
-{
- u8 sr1;
- u32 vga_reg;
-
- vga_reg = VGACNTRL;
-
- outb(1, VGA_SR_INDEX);
- sr1 = inb(VGA_SR_DATA);
- outb(sr1 | 1<<5, VGA_SR_DATA);
- udelay(300);
-
- REG_WRITE(vga_reg, VGA_DISP_DISABLE);
- REG_READ(vga_reg);
-}
-
-static int cdv_output_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- cdv_disable_vga(dev);
-
- cdv_intel_crt_init(dev, &dev_priv->mode_dev);
- cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
-
- /* These bits indicate HDMI not SDVO on CDV, but we don't yet support
- the HDMI interface */
- if (REG_READ(SDVOB) & SDVO_DETECTED)
- cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
- if (REG_READ(SDVOC) & SDVO_DETECTED)
- cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
- return 0;
-}
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-/*
- * Poulsbo Backlight Interfaces
- */
-
-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-
-#define PSB_BLC_PWM_PRECISION_FACTOR 10
-#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
-
-static int cdv_brightness;
-static struct backlight_device *cdv_backlight_device;
-
-static int cdv_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return cdv_brightness;
-}
-
-
-static int cdv_backlight_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long core_clock;
- /* u32 bl_max_freq; */
- /* unsigned long value; */
- u16 bl_max_freq;
- uint32_t value;
- uint32_t blc_pwm_precision_factor;
-
- /* get bl_max_freq and pol from dev_priv*/
- if (!dev_priv->lvds_bl) {
- dev_err(dev->dev, "Has no valid LVDS backlight info\n");
- return -ENOENT;
- }
- bl_max_freq = dev_priv->lvds_bl->freq;
- blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-
- core_clock = dev_priv->core_freq;
-
- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
- value *= blc_pwm_precision_factor;
- value /= bl_max_freq;
- value /= blc_pwm_precision_factor;
-
- if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
- value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
- return -ERANGE;
- else {
- /* FIXME */
- }
- return 0;
-}
-
-static int cdv_set_brightness(struct backlight_device *bd)
-{
- int level = bd->props.brightness;
-
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
- /*cdv_intel_lvds_set_brightness(dev, level); FIXME */
- cdv_brightness = level;
- return 0;
-}
-
-static const struct backlight_ops cdv_ops = {
- .get_brightness = cdv_get_brightness,
- .update_status = cdv_set_brightness,
-};
-
-static int cdv_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- cdv_backlight_device = backlight_device_register("psb-bl",
- NULL, (void *)dev, &cdv_ops, &props);
- if (IS_ERR(cdv_backlight_device))
- return PTR_ERR(cdv_backlight_device);
-
- ret = cdv_backlight_setup(dev);
- if (ret < 0) {
- backlight_device_unregister(cdv_backlight_device);
- cdv_backlight_device = NULL;
- return ret;
- }
- cdv_backlight_device->props.brightness = 100;
- cdv_backlight_device->props.max_brightness = 100;
- backlight_update_status(cdv_backlight_device);
- dev_priv->backlight_device = cdv_backlight_device;
- return 0;
-}
-
-#endif
-
-/*
- * Provide the Cedarview specific chip logic and low level methods
- * for power management
- *
- * FIXME: we need to implement the apm/ospm base management bits
- * for this and the MID devices.
- */
-
-static inline u32 CDV_MSG_READ32(uint port, uint offset)
-{
- int mcr = (0x10<<24) | (port << 16) | (offset << 8);
- uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_read_config_dword(pci_root, 0xD4, &ret_val);
- pci_dev_put(pci_root);
- return ret_val;
-}
-
-static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
-{
- int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD4, value);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_dev_put(pci_root);
-}
-
-#define PSB_APM_CMD 0x0
-#define PSB_APM_STS 0x04
-#define PSB_PM_SSC 0x20
-#define PSB_PM_SSS 0x30
-#define PSB_PWRGT_GFX_MASK 0x3
-#define CDV_PWRGT_DISPLAY_CNTR 0x000fc00c
-#define CDV_PWRGT_DISPLAY_STS 0x000fc00c
-
-static void cdv_init_pm(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pwr_cnt;
- int i;
-
- dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
- PSB_APMBA) & 0xFFFF;
- dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
- PSB_OSPMBA) & 0xFFFF;
-
- /* Force power on for now */
- pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
- pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
-
- outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
- for (i = 0; i < 5; i++) {
- u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
- if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
- break;
- udelay(10);
- }
- pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
- pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
- outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
- for (i = 0; i < 5; i++) {
- u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
- if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
- break;
- udelay(10);
- }
-}
-
-/**
- * cdv_save_display_registers - save registers lost on suspend
- * @dev: our DRM device
- *
- * Save the state we need in order to be able to restore the interface
- * upon resume from suspend
- *
- * FIXME: review
- */
-static int cdv_save_display_registers(struct drm_device *dev)
-{
- return 0;
-}
-
-/**
- * cdv_restore_display_registers - restore lost register state
- * @dev: our DRM device
- *
- * Restore register state that was lost during suspend and resume.
- *
- * FIXME: review
- */
-static int cdv_restore_display_registers(struct drm_device *dev)
-{
- return 0;
-}
-
-static int cdv_power_down(struct drm_device *dev)
-{
- return 0;
-}
-
-static int cdv_power_up(struct drm_device *dev)
-{
- return 0;
-}
-
-/* FIXME ? - shared with Poulsbo */
-static void cdv_get_core_freq(struct drm_device *dev)
-{
- uint32_t clock;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
- pci_read_config_dword(pci_root, 0xD4, &clock);
- pci_dev_put(pci_root);
-
- switch (clock & 0x07) {
- case 0:
- dev_priv->core_freq = 100;
- break;
- case 1:
- dev_priv->core_freq = 133;
- break;
- case 2:
- dev_priv->core_freq = 150;
- break;
- case 3:
- dev_priv->core_freq = 178;
- break;
- case 4:
- dev_priv->core_freq = 200;
- break;
- case 5:
- case 6:
- case 7:
- dev_priv->core_freq = 266;
- default:
- dev_priv->core_freq = 0;
- }
-}
-
-static int cdv_chip_setup(struct drm_device *dev)
-{
- cdv_get_core_freq(dev);
- gma_intel_opregion_init(dev);
- psb_intel_init_bios(dev);
- return 0;
-}
-
-/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
-
-const struct psb_ops cdv_chip_ops = {
- .name = "Cedartrail",
- .accel_2d = 0,
- .pipes = 2,
- .sgx_offset = MRST_SGX_OFFSET,
- .chip_setup = cdv_chip_setup,
-
- .crtc_helper = &cdv_intel_helper_funcs,
- .crtc_funcs = &cdv_intel_crtc_funcs,
-
- .output_init = cdv_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = cdv_backlight_init,
-#endif
-
- .init_pm = cdv_init_pm,
- .save_regs = cdv_save_display_registers,
- .restore_regs = cdv_restore_display_registers,
- .power_down = cdv_power_down,
- .power_up = cdv_power_up,
-};
diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h
deleted file mode 100644
index 2a88b7beb551..000000000000
--- a/drivers/staging/gma500/cdv_device.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * 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.
- */
-
-extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
-extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
-extern void cdv_intel_crt_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void cdv_intel_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev,
- int reg);
-extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
- struct drm_crtc *crtc);
-
-extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
-{
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- /* FIXME: msleep ?? */
- mdelay(20);
-}
-
-
diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c
deleted file mode 100644
index efda63b97b45..000000000000
--- a/drivers/staging/gma500/cdv_intel_crt.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-
-static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- u32 temp, reg;
- reg = ADPA;
-
- temp = REG_READ(reg);
- temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
- temp &= ~ADPA_DAC_ENABLE;
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- temp |= ADPA_DAC_ENABLE;
- break;
- case DRM_MODE_DPMS_STANDBY:
- temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
- break;
- case DRM_MODE_DPMS_SUSPEND:
- temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
- break;
- case DRM_MODE_DPMS_OFF:
- temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
- break;
- }
-
- REG_WRITE(reg, temp);
-}
-
-static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- int max_clock = 0;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- /* The lowest clock for CDV is 20000KHz */
- if (mode->clock < 20000)
- return MODE_CLOCK_LOW;
-
- /* The max clock for CDV is 355 instead of 400 */
- max_clock = 355000;
- if (mode->clock > max_clock)
- return MODE_CLOCK_HIGH;
-
- if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
- return MODE_PANEL;
-
- return MODE_OK;
-}
-
-static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
-
- struct drm_device *dev = encoder->dev;
- struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *psb_intel_crtc =
- to_psb_intel_crtc(crtc);
- int dpll_md_reg;
- u32 adpa, dpll_md;
- u32 adpa_reg;
-
- if (psb_intel_crtc->pipe == 0)
- dpll_md_reg = DPLL_A_MD;
- else
- dpll_md_reg = DPLL_B_MD;
-
- adpa_reg = ADPA;
-
- /*
- * Disable separate mode multiplier used when cloning SDVO to CRT
- * XXX this needs to be adjusted when we really are cloning
- */
- {
- dpll_md = REG_READ(dpll_md_reg);
- REG_WRITE(dpll_md_reg,
- dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
- }
-
- adpa = 0;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- adpa |= ADPA_HSYNC_ACTIVE_HIGH;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- adpa |= ADPA_VSYNC_ACTIVE_HIGH;
-
- if (psb_intel_crtc->pipe == 0)
- adpa |= ADPA_PIPE_A_SELECT;
- else
- adpa |= ADPA_PIPE_B_SELECT;
-
- REG_WRITE(adpa_reg, adpa);
-}
-
-
-/**
- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
- *
- * \return true if CRT is connected.
- * \return false if CRT is disconnected.
- */
-static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
- bool force)
-{
- struct drm_device *dev = connector->dev;
- u32 hotplug_en;
- int i, tries = 0, ret = false;
- u32 adpa_orig;
-
- /* disable the DAC when doing the hotplug detection */
-
- adpa_orig = REG_READ(ADPA);
-
- REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
-
- /*
- * On a CDV thep, CRT detect sequence need to be done twice
- * to get a reliable result.
- */
- tries = 2;
-
- hotplug_en = REG_READ(PORT_HOTPLUG_EN);
- hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
- hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
-
- hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
- for (i = 0; i < tries ; i++) {
- unsigned long timeout;
- /* turn on the FORCE_DETECT */
- REG_WRITE(PORT_HOTPLUG_EN, hotplug_en);
- timeout = jiffies + msecs_to_jiffies(1000);
- /* wait for FORCE_DETECT to go off */
- do {
- if (!(REG_READ(PORT_HOTPLUG_EN) &
- CRT_HOTPLUG_FORCE_DETECT))
- break;
- msleep(1);
- } while (time_after(timeout, jiffies));
- }
-
- if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
- CRT_HOTPLUG_MONITOR_NONE)
- ret = true;
-
- /* Restore the saved ADPA */
- REG_WRITE(ADPA, adpa_orig);
- return ret;
-}
-
-static enum drm_connector_status cdv_intel_crt_detect(
- struct drm_connector *connector, bool force)
-{
- if (cdv_intel_crt_detect_hotplug(connector, force))
- return connector_status_connected;
- else
- return connector_status_disconnected;
-}
-
-static void cdv_intel_crt_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output *intel_output = to_psb_intel_output(connector);
-
- psb_intel_i2c_destroy(intel_output->ddc_bus);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-static int cdv_intel_crt_get_modes(struct drm_connector *connector)
-{
- struct psb_intel_output *intel_output =
- to_psb_intel_output(connector);
- return psb_intel_ddc_get_modes(intel_output);
-}
-
-static int cdv_intel_crt_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- return 0;
-}
-
-/*
- * Routines for controlling stuff on the analog port
- */
-
-static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
- .dpms = cdv_intel_crt_dpms,
- .mode_fixup = cdv_intel_crt_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
- .commit = psb_intel_encoder_commit,
- .mode_set = cdv_intel_crt_mode_set,
-};
-
-static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .detect = cdv_intel_crt_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = cdv_intel_crt_destroy,
- .set_property = cdv_intel_crt_set_property,
-};
-
-static const struct drm_connector_helper_funcs
- cdv_intel_crt_connector_helper_funcs = {
- .mode_valid = cdv_intel_crt_mode_valid,
- .get_modes = cdv_intel_crt_get_modes,
- .best_encoder = psb_intel_best_encoder,
-};
-
-static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
- .destroy = cdv_intel_crt_enc_destroy,
-};
-
-void cdv_intel_crt_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev)
-{
-
- struct psb_intel_output *psb_intel_output;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
-
- u32 i2c_reg;
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- psb_intel_output->mode_dev = mode_dev;
- connector = &psb_intel_output->base;
- drm_connector_init(dev, connector,
- &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
-
- encoder = &psb_intel_output->enc;
- drm_encoder_init(dev, encoder,
- &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
-
- /* Set up the DDC bus. */
- i2c_reg = GPIOA;
- /* Remove the following code for CDV */
- /*
- if (dev_priv->crt_ddc_bus != 0)
- i2c_reg = dev_priv->crt_ddc_bus;
- }*/
- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
- i2c_reg, "CRTDDC_A");
- if (!psb_intel_output->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
- "failed.\n");
- goto failed_ddc;
- }
-
- psb_intel_output->type = INTEL_OUTPUT_ANALOG;
- /*
- psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
- psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
- */
- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
-
- drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
- drm_connector_helper_add(connector,
- &cdv_intel_crt_connector_helper_funcs);
-
- drm_sysfs_connector_add(connector);
-
- return;
-failed_ddc:
- drm_encoder_cleanup(&psb_intel_output->enc);
- drm_connector_cleanup(&psb_intel_output->base);
- kfree(psb_intel_output);
- return;
-}
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
deleted file mode 100644
index c63a32776a9e..000000000000
--- a/drivers/staging/gma500/cdv_intel_display.c
+++ /dev/null
@@ -1,1508 +0,0 @@
-/*
- * Copyright © 2006-2011 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-#include "cdv_device.h"
-
-
-struct cdv_intel_range_t {
- int min, max;
-};
-
-struct cdv_intel_p2_t {
- int dot_limit;
- int p2_slow, p2_fast;
-};
-
-struct cdv_intel_clock_t {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
-};
-
-#define INTEL_P2_NUM 2
-
-struct cdv_intel_limit_t {
- struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
- struct cdv_intel_p2_t p2;
-};
-
-#define CDV_LIMIT_SINGLE_LVDS_96 0
-#define CDV_LIMIT_SINGLE_LVDS_100 1
-#define CDV_LIMIT_DAC_HDMI_27 2
-#define CDV_LIMIT_DAC_HDMI_96 3
-
-static const struct cdv_intel_limit_t cdv_intel_limits[] = {
- { /* CDV_SIGNLE_LVDS_96MHz */
- .dot = {.min = 20000, .max = 115500},
- .vco = {.min = 1800000, .max = 3600000},
- .n = {.min = 2, .max = 6},
- .m = {.min = 60, .max = 160},
- .m1 = {.min = 0, .max = 0},
- .m2 = {.min = 58, .max = 158},
- .p = {.min = 28, .max = 140},
- .p1 = {.min = 2, .max = 10},
- .p2 = {.dot_limit = 200000,
- .p2_slow = 14, .p2_fast = 14},
- },
- { /* CDV_SINGLE_LVDS_100MHz */
- .dot = {.min = 20000, .max = 115500},
- .vco = {.min = 1800000, .max = 3600000},
- .n = {.min = 2, .max = 6},
- .m = {.min = 60, .max = 160},
- .m1 = {.min = 0, .max = 0},
- .m2 = {.min = 58, .max = 158},
- .p = {.min = 28, .max = 140},
- .p1 = {.min = 2, .max = 10},
- /* The single-channel range is 25-112Mhz, and dual-channel
- * is 80-224Mhz. Prefer single channel as much as possible.
- */
- .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
- },
- { /* CDV_DAC_HDMI_27MHz */
- .dot = {.min = 20000, .max = 400000},
- .vco = {.min = 1809000, .max = 3564000},
- .n = {.min = 1, .max = 1},
- .m = {.min = 67, .max = 132},
- .m1 = {.min = 0, .max = 0},
- .m2 = {.min = 65, .max = 130},
- .p = {.min = 5, .max = 90},
- .p1 = {.min = 1, .max = 9},
- .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
- },
- { /* CDV_DAC_HDMI_96MHz */
- .dot = {.min = 20000, .max = 400000},
- .vco = {.min = 1800000, .max = 3600000},
- .n = {.min = 2, .max = 6},
- .m = {.min = 60, .max = 160},
- .m1 = {.min = 0, .max = 0},
- .m2 = {.min = 58, .max = 158},
- .p = {.min = 5, .max = 100},
- .p1 = {.min = 1, .max = 10},
- .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
- },
-};
-
-#define _wait_for(COND, MS, W) ({ \
- unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
- int ret__ = 0; \
- while (!(COND)) { \
- if (time_after(jiffies, timeout__)) { \
- ret__ = -ETIMEDOUT; \
- break; \
- } \
- if (W && !in_dbg_master()) \
- msleep(W); \
- } \
- ret__; \
-})
-
-#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-
-
-static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
-{
- int ret;
-
- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
- if (ret) {
- DRM_ERROR("timeout waiting for SB to idle before read\n");
- return ret;
- }
-
- REG_WRITE(SB_ADDR, reg);
- REG_WRITE(SB_PCKT,
- SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
- SET_FIELD(SB_DEST_DPLL, SB_DEST) |
- SET_FIELD(0xf, SB_BYTE_ENABLE));
-
- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
- if (ret) {
- DRM_ERROR("timeout waiting for SB to idle after read\n");
- return ret;
- }
-
- *val = REG_READ(SB_DATA);
-
- return 0;
-}
-
-static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
-{
- int ret;
- static bool dpio_debug = true;
- u32 temp;
-
- if (dpio_debug) {
- if (cdv_sb_read(dev, reg, &temp) == 0)
- DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
- DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
- }
-
- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
- if (ret) {
- DRM_ERROR("timeout waiting for SB to idle before write\n");
- return ret;
- }
-
- REG_WRITE(SB_ADDR, reg);
- REG_WRITE(SB_DATA, val);
- REG_WRITE(SB_PCKT,
- SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
- SET_FIELD(SB_DEST_DPLL, SB_DEST) |
- SET_FIELD(0xf, SB_BYTE_ENABLE));
-
- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
- if (ret) {
- DRM_ERROR("timeout waiting for SB to idle after write\n");
- return ret;
- }
-
- if (dpio_debug) {
- if (cdv_sb_read(dev, reg, &temp) == 0)
- DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
- }
-
- return 0;
-}
-
-/* Reset the DPIO configuration register. The BIOS does this at every
- * mode set.
- */
-static void cdv_sb_reset(struct drm_device *dev)
-{
-
- REG_WRITE(DPIO_CFG, 0);
- REG_READ(DPIO_CFG);
- REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
-}
-
-/* Unlike most Intel display engines, on Cedarview the DPLL registers
- * are behind this sideband bus. They must be programmed while the
- * DPLL reference clock is on in the DPLL control register, but before
- * the DPLL is enabled in the DPLL control register.
- */
-static int
-cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
- struct cdv_intel_clock_t *clock)
-{
- struct psb_intel_crtc *psb_crtc =
- to_psb_intel_crtc(crtc);
- int pipe = psb_crtc->pipe;
- u32 m, n_vco, p;
- int ret = 0;
- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- u32 ref_value;
-
- cdv_sb_reset(dev);
-
- if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
- DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
- return -EBUSY;
- }
-
- /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
- ref_value = 0x68A701;
-
- cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
-
- /* We don't know what the other fields of these regs are, so
- * leave them in place.
- */
- ret = cdv_sb_read(dev, SB_M(pipe), &m);
- if (ret)
- return ret;
- m &= ~SB_M_DIVIDER_MASK;
- m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
- ret = cdv_sb_write(dev, SB_M(pipe), m);
- if (ret)
- return ret;
-
- ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
- if (ret)
- return ret;
-
- /* Follow the BIOS to program the N_DIVIDER REG */
- n_vco &= 0xFFFF;
- n_vco |= 0x107;
- n_vco &= ~(SB_N_VCO_SEL_MASK |
- SB_N_DIVIDER_MASK |
- SB_N_CB_TUNE_MASK);
-
- n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
-
- if (clock->vco < 2250000) {
- n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
- n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
- } else if (clock->vco < 2750000) {
- n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
- n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
- } else if (clock->vco < 3300000) {
- n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
- n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
- } else {
- n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
- n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
- }
-
- ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
- if (ret)
- return ret;
-
- ret = cdv_sb_read(dev, SB_P(pipe), &p);
- if (ret)
- return ret;
- p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
- p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
- switch (clock->p2) {
- case 5:
- p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
- break;
- case 10:
- p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
- break;
- case 14:
- p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
- break;
- case 7:
- p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
- break;
- default:
- DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
- return -EINVAL;
- }
- ret = cdv_sb_write(dev, SB_P(pipe), p);
- if (ret)
- return ret;
-
- /* always Program the Lane Register for the Pipe A*/
- if (pipe == 0) {
- /* Program the Lane0/1 for HDMI B */
- u32 lane_reg, lane_value;
-
- lane_reg = PSB_LANE0;
- cdv_sb_read(dev, lane_reg, &lane_value);
- lane_value &= ~(LANE_PLL_MASK);
- lane_value |= LANE_PLL_ENABLE;
- cdv_sb_write(dev, lane_reg, lane_value);
-
- lane_reg = PSB_LANE1;
- cdv_sb_read(dev, lane_reg, &lane_value);
- lane_value &= ~(LANE_PLL_MASK);
- lane_value |= LANE_PLL_ENABLE;
- cdv_sb_write(dev, lane_reg, lane_value);
-
- /* Program the Lane2/3 for HDMI C */
- lane_reg = PSB_LANE2;
- cdv_sb_read(dev, lane_reg, &lane_value);
- lane_value &= ~(LANE_PLL_MASK);
- lane_value |= LANE_PLL_ENABLE;
- cdv_sb_write(dev, lane_reg, lane_value);
-
- lane_reg = PSB_LANE3;
- cdv_sb_read(dev, lane_reg, &lane_value);
- lane_value &= ~(LANE_PLL_MASK);
- lane_value |= LANE_PLL_ENABLE;
- cdv_sb_write(dev, lane_reg, lane_value);
- }
-
- return 0;
-}
-
-/*
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *l_entry;
-
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
- if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(l_entry);
- if (psb_intel_output->type == type)
- return true;
- }
- }
- return false;
-}
-
-static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
- int refclk)
-{
- const struct cdv_intel_limit_t *limit;
- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
- /*
- * Now only single-channel LVDS is supported on CDV. If it is
- * incorrect, please add the dual-channel LVDS.
- */
- if (refclk == 96000)
- limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
- else
- limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
- } else {
- if (refclk == 27000)
- limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
- else
- limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
- }
- return limit;
-}
-
-/* m1 is reserved as 0 in CDV, n is a ring counter */
-static void cdv_intel_clock(struct drm_device *dev,
- int refclk, struct cdv_intel_clock_t *clock)
-{
- clock->m = clock->m2 + 2;
- clock->p = clock->p1 * clock->p2;
- clock->vco = (refclk * clock->m) / clock->n;
- clock->dot = clock->vco / clock->p;
-}
-
-
-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
-static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
- const struct cdv_intel_limit_t *limit,
- struct cdv_intel_clock_t *clock)
-{
- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
- INTELPllInvalid("p1 out of range\n");
- if (clock->p < limit->p.min || limit->p.max < clock->p)
- INTELPllInvalid("p out of range\n");
- /* unnecessary to check the range of m(m1/M2)/n again */
- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
- INTELPllInvalid("vco out of range\n");
- /* XXX: We may need to be checking "Dot clock"
- * depending on the multiplier, connector, etc.,
- * rather than just a single range.
- */
- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
- INTELPllInvalid("dot out of range\n");
-
- return true;
-}
-
-static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
- int refclk,
- struct cdv_intel_clock_t *best_clock)
-{
- struct drm_device *dev = crtc->dev;
- struct cdv_intel_clock_t clock;
- const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
- int err = target;
-
-
- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
- /*
- * For LVDS, if the panel is on, just rely on its current
- * settings for dual-channel. We haven't figured out how to
- * reliably set up different single/dual channel state, if we
- * even can.
- */
- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
- LVDS_CLKB_POWER_UP)
- clock.p2 = limit->p2.p2_fast;
- else
- clock.p2 = limit->p2.p2_slow;
- } else {
- if (target < limit->p2.dot_limit)
- clock.p2 = limit->p2.p2_slow;
- else
- clock.p2 = limit->p2.p2_fast;
- }
-
- memset(best_clock, 0, sizeof(*best_clock));
- clock.m1 = 0;
- /* m1 is reserved as 0 in CDV, n is a ring counter.
- So skip the m1 loop */
- for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
- for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
- clock.m2++) {
- for (clock.p1 = limit->p1.min;
- clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- cdv_intel_clock(dev, refclk, &clock);
-
- if (!cdv_intel_PLL_is_valid(crtc,
- limit, &clock))
- continue;
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- }
-
- return err != target;
-}
-
-int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
- int x, int y, struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- unsigned long start, offset;
- int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- u32 dspcntr;
- int ret = 0;
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_err(dev->dev, "No FB bound\n");
- goto psb_intel_pipe_cleaner;
- }
-
-
- /* We are displaying this buffer, make sure it is actually loaded
- into the GTT */
- ret = psb_gtt_pin(psbfb->gtt);
- if (ret < 0)
- goto psb_intel_pipe_set_base_exit;
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- goto psb_intel_pipe_set_base_exit;
- }
- REG_WRITE(dspcntr_reg, dspcntr);
-
- dev_dbg(dev->dev,
- "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
-
- REG_WRITE(dspbase, offset);
- REG_READ(dspbase);
- REG_WRITE(dspsurf, start);
- REG_READ(dspsurf);
-
-psb_intel_pipe_cleaner:
- /* If there was a previous display we can now unpin it */
- if (old_fb)
- psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- u32 temp;
- bool enabled;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- /* Enable the DPLL */
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) == 0) {
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- }
-
- /* Jim Bish - switch plan and pipe per scott */
- /* Enable the plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
- REG_WRITE(dspcntr_reg,
- temp | DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- }
-
- udelay(150);
-
- /* Enable the pipe */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) == 0)
- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Jim Bish - changed pipe/plane here as well. */
-
- /* Wait for vblank for the disable to take effect */
- cdv_intel_wait_for_vblank(dev);
-
- /* Next, disable display pipes */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
- REG_READ(pipeconf_reg);
- }
-
- /* Wait for vblank for the disable to take effect. */
- cdv_intel_wait_for_vblank(dev);
-
- udelay(150);
-
- /* Disable display plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(dspcntr_reg,
- temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
- }
-
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) != 0) {
- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- }
-
- /* Wait for the clocks to turn off. */
- udelay(150);
- break;
- }
- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
- /*Set FIFO Watermarks*/
- REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of prepare see cdv_intel_lvds_prepare */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void cdv_intel_encoder_commit(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of commit see cdv_intel_lvds_commit */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
-{
- u32 pfit_control;
-
- pfit_control = REG_READ(PFIT_CONTROL);
-
- /* See if the panel fitter is in use */
- if ((pfit_control & PFIT_ENABLE) == 0)
- return -1;
- return (pfit_control >> 29) & 0x3;
-}
-
-static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
- int refclk;
- struct cdv_intel_clock_t clock;
- u32 dpll = 0, dspcntr, pipeconf;
- bool ok, is_sdvo = false, is_dvo = false;
- bool is_crt = false, is_lvds = false, is_tv = false;
- bool is_hdmi = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *connector;
-
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (!connector->encoder
- || connector->encoder->crtc != crtc)
- continue;
-
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_LVDS:
- is_lvds = true;
- break;
- case INTEL_OUTPUT_SDVO:
- is_sdvo = true;
- break;
- case INTEL_OUTPUT_DVO:
- is_dvo = true;
- break;
- case INTEL_OUTPUT_TVOUT:
- is_tv = true;
- break;
- case INTEL_OUTPUT_ANALOG:
- is_crt = true;
- break;
- case INTEL_OUTPUT_HDMI:
- is_hdmi = true;
- break;
- }
- }
-
- refclk = 96000;
-
- /* Hack selection about ref clk for CRT */
- /* Select 27MHz as the reference clk for HDMI */
- if (is_crt || is_hdmi)
- refclk = 27000;
-
- drm_mode_debug_printmodeline(adjusted_mode);
-
- ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
- &clock);
- if (!ok) {
- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
- return 0;
- }
-
- dpll = DPLL_VGA_MODE_DIS;
- if (is_tv) {
- /* XXX: just matching BIOS for now */
-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
- dpll |= 3;
- }
- dpll |= PLL_REF_INPUT_DREFCLK;
-
- dpll |= DPLL_SYNCLOCK_ENABLE;
- dpll |= DPLL_VGA_MODE_DIS;
- if (is_lvds)
- dpll |= DPLLB_MODE_LVDS;
- else
- dpll |= DPLLB_MODE_DAC_SERIAL;
- /* dpll |= (2 << 11); */
-
- /* setup pipeconf */
- pipeconf = REG_READ(pipeconf_reg);
-
- /* Set up the display plane register */
- dspcntr = DISPPLANE_GAMMA_ENABLE;
-
- if (pipe == 0)
- dspcntr |= DISPPLANE_SEL_PIPE_A;
- else
- dspcntr |= DISPPLANE_SEL_PIPE_B;
-
- dspcntr |= DISPLAY_PLANE_ENABLE;
- pipeconf |= PIPEACONF_ENABLE;
-
- REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
- REG_READ(dpll_reg);
-
- cdv_dpll_set_clock_cdv(dev, crtc, &clock);
-
- udelay(150);
-
-
- /* The LVDS pin pair needs to be on before the DPLLs are enabled.
- * This is an exception to the general rule that mode_set doesn't turn
- * things on.
- */
- if (is_lvds) {
- u32 lvds = REG_READ(LVDS);
-
- lvds |=
- LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
- LVDS_PIPEB_SELECT;
- /* Set the B0-B3 data pairs corresponding to
- * whether we're going to
- * set the DPLLs for dual-channel mode or not.
- */
- if (clock.p2 == 7)
- lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
- else
- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
- * appropriately here, but we need to look more
- * thoroughly into how panels behave in the two modes.
- */
-
- REG_WRITE(LVDS, lvds);
- REG_READ(LVDS);
- }
-
- dpll |= DPLL_VCO_ENABLE;
-
- /* Disable the panel fitter if it was on our pipe */
- if (cdv_intel_panel_fitter_pipe(dev) == pipe)
- REG_WRITE(PFIT_CONTROL, 0);
-
- DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
- drm_mode_debug_printmodeline(mode);
-
- REG_WRITE(dpll_reg,
- (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */
-
- if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
- dev_err(dev->dev, "Failed to get DPLL lock\n");
- return -EBUSY;
- }
-
- {
- int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
- REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
- }
-
- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
- ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
- ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
- ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
- ((adjusted_mode->crtc_vsync_end - 1) << 16));
- /* pipesrc and dspsize control the size that is scaled from,
- * which should always be the user's requested size.
- */
- REG_WRITE(dspsize_reg,
- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
- REG_WRITE(dsppos_reg, 0);
- REG_WRITE(pipesrc_reg,
- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
-
- cdv_intel_wait_for_vblank(dev);
-
- REG_WRITE(dspcntr_reg, dspcntr);
-
- /* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs =
- crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
-
- cdv_intel_wait_for_vblank(dev);
-
- return 0;
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int palreg = PALETTE_A;
- int i;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->enabled)
- return;
-
- switch (psb_intel_crtc->pipe) {
- case 0:
- break;
- case 1:
- palreg = PALETTE_B;
- break;
- case 2:
- palreg = PALETTE_C;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- if (gma_power_begin(dev, false)) {
- for (i = 0; i < 256; i++) {
- REG_WRITE(palreg + 4 * i,
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]));
- }
- gma_power_end(dev);
- } else {
- for (i = 0; i < 256; i++) {
- dev_priv->save_palette_a[i] =
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]);
- }
-
- }
-}
-
-/**
- * Save HW states of giving crtc
- */
-static void cdv_intel_crtc_save(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- int pipeA = (psb_intel_crtc->pipe == 0);
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_dbg(dev->dev, "No CRTC state found\n");
- return;
- }
-
- crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
- crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
- crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
- crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
- crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
- crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
- crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
- crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
- crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
- crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
- crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
- crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
- crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
-
- /*NOTE: DSPSIZE DSPPOS only for psb*/
- crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
- crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
-
- crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
-
- DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
- paletteReg = pipeA ? PALETTE_A : PALETTE_B;
- for (i = 0; i < 256; ++i)
- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_psb_private * dev_priv =
- (struct drm_psb_private *)dev->dev_private; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
- int pipeA = (psb_intel_crtc->pipe == 0);
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_dbg(dev->dev, "No crtc state\n");
- return;
- }
-
- DRM_DEBUG(
- "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
- REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
- REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
- REG_READ(pipeA ? FPA0 : FPB0),
- REG_READ(pipeA ? FPA1 : FPB1),
- REG_READ(pipeA ? DPLL_A : DPLL_B),
- REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
- REG_READ(pipeA ? HBLANK_A : HBLANK_B),
- REG_READ(pipeA ? HSYNC_A : HSYNC_B),
- REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
- REG_READ(pipeA ? VBLANK_A : VBLANK_B),
- REG_READ(pipeA ? VSYNC_A : VSYNC_B),
- REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
- REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
- REG_READ(pipeA ? DSPAPOS : DSPBPOS),
- REG_READ(pipeA ? DSPABASE : DSPBBASE)
- );
-
- DRM_DEBUG(
- "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
-
- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
- REG_WRITE(pipeA ? DPLL_A : DPLL_B,
- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
- REG_READ(pipeA ? DPLL_A : DPLL_B);
- DRM_DEBUG("write dpll: %x\n",
- REG_READ(pipeA ? DPLL_A : DPLL_B));
- udelay(150);
- }
-
- REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
- REG_READ(pipeA ? FPA0 : FPB0);
-
- REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
- REG_READ(pipeA ? FPA1 : FPB1);
-
- REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
- REG_READ(pipeA ? DPLL_A : DPLL_B);
- udelay(150);
-
- REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
- REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
- REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
- REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
- REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
- REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
- REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
-
- REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
- REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
-
- REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
- REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
-
- cdv_intel_wait_for_vblank(dev);
-
- REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-
- cdv_intel_wait_for_vblank(dev);
-
- paletteReg = pipeA ? PALETTE_A : PALETTE_B;
- for (i = 0; i < 256; ++i)
- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
- uint32_t temp;
- size_t addr = 0;
- struct gtt_range *gt;
- struct drm_gem_object *obj;
- int ret;
-
- /* if we want to turn of the cursor ignore width and height */
- if (!handle) {
- /* turn off the cursor */
- temp = CURSOR_MODE_DISABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, 0);
- gma_power_end(dev);
- }
-
- /* unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = NULL;
- }
-
- return 0;
- }
-
- /* Currently we only support 64x64 cursors */
- if (width != 64 || height != 64) {
- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
-
- if (obj->size < width * height * 4) {
- dev_dbg(dev->dev, "buffer is to small\n");
- return -ENOMEM;
- }
-
- gt = container_of(obj, struct gtt_range, gem);
-
- /* Pin the memory into the GTT */
- ret = psb_gtt_pin(gt);
- if (ret) {
- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
- return ret;
- }
-
- addr = gt->offset; /* Or resource.start ??? */
-
- psb_intel_crtc->cursor_addr = addr;
-
- temp = 0;
- /* set the pipe for the cursor */
- temp |= (pipe << 28);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
-
- /* unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = obj;
- }
- return 0;
-}
-
-static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t temp = 0;
- uint32_t adder;
-
-
- if (x < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
- x = -x;
- }
- if (y < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
- y = -y;
- }
-
- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
- adder = psb_intel_crtc->cursor_addr;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
- gma_power_end(dev);
- }
- return 0;
-}
-
-static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t start, uint32_t size)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int i;
- int end = (start + size > 256) ? 256 : start + size;
-
- for (i = start; i < end; i++) {
- psb_intel_crtc->lut_r[i] = red[i] >> 8;
- psb_intel_crtc->lut_g[i] = green[i] >> 8;
- psb_intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- cdv_intel_crtc_load_lut(crtc);
-}
-
-static int cdv_crtc_set_config(struct drm_mode_set *set)
-{
- int ret = 0;
- struct drm_device *dev = set->crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->rpm_enabled)
- return drm_crtc_helper_set_config(set);
-
- pm_runtime_forbid(&dev->pdev->dev);
-
- ret = drm_crtc_helper_set_config(set);
-
- pm_runtime_allow(&dev->pdev->dev);
-
- return ret;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-/* FIXME: why are we using this, should it be cdv_ in this tree ? */
-
-static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
-{
- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
- clock->p = clock->p1 * clock->p2;
- clock->vco = refclk * clock->m / (clock->n + 2);
- clock->dot = clock->vco / clock->p;
-}
-
-/* Returns the clock of the currently programmed mode of the given pipe. */
-static int cdv_intel_crtc_clock_get(struct drm_device *dev,
- struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- u32 dpll;
- u32 fp;
- struct cdv_intel_clock_t clock;
- bool is_lvds;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (gma_power_begin(dev, false)) {
- dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
- fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
- else
- fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
- is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
- gma_power_end(dev);
- } else {
- dpll = (pipe == 0) ?
- dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
-
- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
- fp = (pipe == 0) ?
- dev_priv->saveFPA0 :
- dev_priv->saveFPB0;
- else
- fp = (pipe == 0) ?
- dev_priv->saveFPA1 :
- dev_priv->saveFPB1;
-
- is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
- }
-
- clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
- clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
- clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-
- if (is_lvds) {
- clock.p1 =
- ffs((dpll &
- DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
- DPLL_FPA01_P1_POST_DIV_SHIFT);
- if (clock.p1 == 0) {
- clock.p1 = 4;
- dev_err(dev->dev, "PLL %d\n", dpll);
- }
- clock.p2 = 14;
-
- if ((dpll & PLL_REF_INPUT_MASK) ==
- PLLB_REF_INPUT_SPREADSPECTRUMIN) {
- /* XXX: might not be 66MHz */
- i8xx_clock(66000, &clock);
- } else
- i8xx_clock(48000, &clock);
- } else {
- if (dpll & PLL_P1_DIVIDE_BY_TWO)
- clock.p1 = 2;
- else {
- clock.p1 =
- ((dpll &
- DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
- DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
- }
- if (dpll & PLL_P2_DIVIDE_BY_4)
- clock.p2 = 4;
- else
- clock.p2 = 2;
-
- i8xx_clock(48000, &clock);
- }
-
- /* XXX: It would be nice to validate the clocks, but we can't reuse
- * i830PllIsValid() because it relies on the xf86_config connector
- * configuration being accurate, which it isn't necessarily.
- */
-
- return clock.dot;
-}
-
-/** Returns the currently programmed mode of the given pipe. */
-struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
- struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- struct drm_display_mode *mode;
- int htot;
- int hsync;
- int vtot;
- int vsync;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (gma_power_begin(dev, false)) {
- htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
- hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
- vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
- vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
- gma_power_end(dev);
- } else {
- htot = (pipe == 0) ?
- dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
- hsync = (pipe == 0) ?
- dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
- vtot = (pipe == 0) ?
- dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
- vsync = (pipe == 0) ?
- dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
- }
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
- mode->hdisplay = (htot & 0xffff) + 1;
- mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
- mode->hsync_start = (hsync & 0xffff) + 1;
- mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
- mode->vdisplay = (vtot & 0xffff) + 1;
- mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
- mode->vsync_start = (vsync & 0xffff) + 1;
- mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- return mode;
-}
-
-static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-
- kfree(psb_intel_crtc->crtc_state);
- drm_crtc_cleanup(crtc);
- kfree(psb_intel_crtc);
-}
-
-const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
- .dpms = cdv_intel_crtc_dpms,
- .mode_fixup = cdv_intel_crtc_mode_fixup,
- .mode_set = cdv_intel_crtc_mode_set,
- .mode_set_base = cdv_intel_pipe_set_base,
- .prepare = cdv_intel_crtc_prepare,
- .commit = cdv_intel_crtc_commit,
-};
-
-const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
- .save = cdv_intel_crtc_save,
- .restore = cdv_intel_crtc_restore,
- .cursor_set = cdv_intel_crtc_cursor_set,
- .cursor_move = cdv_intel_crtc_cursor_move,
- .gamma_set = cdv_intel_crtc_gamma_set,
- .set_config = cdv_crtc_set_config,
- .destroy = cdv_intel_crtc_destroy,
-};
-
-/*
- * Set the default value of cursor control and base register
- * to zero. This is a workaround for h/w defect on oaktrail
- */
-void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
-{
- uint32_t control;
- uint32_t base;
-
- switch (pipe) {
- case 0:
- control = CURACNTR;
- base = CURABASE;
- break;
- case 1:
- control = CURBCNTR;
- base = CURBBASE;
- break;
- case 2:
- control = CURCCNTR;
- base = CURCBASE;
- break;
- default:
- return;
- }
-
- REG_WRITE(control, 0);
- REG_WRITE(base, 0);
-}
-
diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c
deleted file mode 100644
index cbca2b0c7d58..000000000000
--- a/drivers/staging/gma500/cdv_intel_hdmi.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright © 2006-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- *
- * FIXME:
- * We should probably make this generic and share it with Medfield
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-#include "psb_intel_drv.h"
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include <linux/pm_runtime.h>
-
-/* hdmi control bits */
-#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
-#define HDMI_BORDER_ENABLE (1 << 7)
-#define HDMI_AUDIO_ENABLE (1 << 6)
-#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4)
-#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3)
-/* hdmi-b control bits */
-#define HDMIB_PIPE_B_SELECT (1 << 30)
-
-
-struct mid_intel_hdmi_priv {
- u32 hdmi_reg;
- u32 save_HDMIB;
- bool has_hdmi_sink;
- bool has_hdmi_audio;
- /* Should set this when detect hotplug */
- bool hdmi_device_connected;
- struct mdfld_hdmi_i2c *i2c_bus;
- struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
- struct drm_device *dev;
-};
-
-static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
- u32 hdmib;
- struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
-
- hdmib = (2 << 10);
-
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- hdmib |= HDMI_VSYNC_ACTIVE_HIGH;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
-
- if (intel_crtc->pipe == 1)
- hdmib |= HDMIB_PIPE_B_SELECT;
-
- if (hdmi_priv->has_hdmi_audio) {
- hdmib |= HDMI_AUDIO_ENABLE;
- hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC;
- }
-
- REG_WRITE(hdmi_priv->hdmi_reg, hdmib);
- REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
- u32 hdmib;
-
- hdmib = REG_READ(hdmi_priv->hdmi_reg);
-
- if (mode != DRM_MODE_DPMS_ON)
- REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN);
- else
- REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN);
- REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static void cdv_hdmi_save(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *output = to_psb_intel_output(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-
- hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static void cdv_hdmi_restore(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *output = to_psb_intel_output(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
-
- REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
- REG_READ(hdmi_priv->hdmi_reg);
-}
-
-static enum drm_connector_status cdv_hdmi_detect(
- struct drm_connector *connector, bool force)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv;
- struct edid *edid = NULL;
- enum drm_connector_status status = connector_status_disconnected;
-
- edid = drm_get_edid(&psb_intel_output->base,
- psb_intel_output->hdmi_i2c_adapter);
-
- hdmi_priv->has_hdmi_sink = false;
- hdmi_priv->has_hdmi_audio = false;
- if (edid) {
- if (edid->input & DRM_EDID_INPUT_DIGITAL) {
- status = connector_status_connected;
- hdmi_priv->has_hdmi_sink =
- drm_detect_hdmi_monitor(edid);
- hdmi_priv->has_hdmi_audio =
- drm_detect_monitor_audio(edid);
- }
-
- psb_intel_output->base.display_info.raw_edid = NULL;
- kfree(edid);
- }
- return status;
-}
-
-static int cdv_hdmi_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- struct drm_encoder *encoder = connector->encoder;
-
- if (!strcmp(property->name, "scaling mode") && encoder) {
- struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
- bool centre;
- uint64_t curValue;
-
- if (!crtc)
- return -1;
-
- switch (value) {
- case DRM_MODE_SCALE_FULLSCREEN:
- break;
- case DRM_MODE_SCALE_NO_SCALE:
- break;
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- return -1;
- }
-
- if (drm_connector_property_get_value(connector,
- property, &curValue))
- return -1;
-
- if (curValue == value)
- return 0;
-
- if (drm_connector_property_set_value(connector,
- property, value))
- return -1;
-
- centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
- (value == DRM_MODE_SCALE_NO_SCALE);
-
- if (crtc->saved_mode.hdisplay != 0 &&
- crtc->saved_mode.vdisplay != 0) {
- if (centre) {
- if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
- encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
- return -1;
- } else {
- struct drm_encoder_helper_funcs *helpers
- = encoder->helper_private;
- helpers->mode_set(encoder, &crtc->saved_mode,
- &crtc->saved_adjusted_mode);
- }
- }
- }
- return 0;
-}
-
-/*
- * Return the list of HDMI DDC modes if available.
- */
-static int cdv_hdmi_get_modes(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct edid *edid = NULL;
- int ret = 0;
-
- edid = drm_get_edid(&psb_intel_output->base,
- psb_intel_output->hdmi_i2c_adapter);
- if (edid) {
- drm_mode_connector_update_edid_property(&psb_intel_output->
- base, edid);
- ret = drm_add_edid_modes(&psb_intel_output->base, edid);
- kfree(edid);
- }
- return ret;
-}
-
-static int cdv_hdmi_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
-
- if (mode->clock > 165000)
- return MODE_CLOCK_HIGH;
- if (mode->clock < 20000)
- return MODE_CLOCK_HIGH;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- return MODE_NO_INTERLACE;
-
- /*
- * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
- * will go beyond the stolen memory size allocated to the framebuffer
- */
- if (mode->hdisplay > 1680)
- return MODE_PANEL;
- if (mode->vdisplay > 1050)
- return MODE_PANEL;
- return MODE_OK;
-}
-
-static void cdv_hdmi_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
- .dpms = cdv_hdmi_dpms,
- .mode_fixup = cdv_hdmi_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
- .mode_set = cdv_hdmi_mode_set,
- .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_helper_funcs
- cdv_hdmi_connector_helper_funcs = {
- .get_modes = cdv_hdmi_get_modes,
- .mode_valid = cdv_hdmi_mode_valid,
- .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .save = cdv_hdmi_save,
- .restore = cdv_hdmi_restore,
- .detect = cdv_hdmi_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = cdv_hdmi_set_property,
- .destroy = cdv_hdmi_destroy,
-};
-
-void cdv_hdmi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev, int reg)
-{
- struct psb_intel_output *psb_intel_output;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- struct mid_intel_hdmi_priv *hdmi_priv;
- int ddc_bus;
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
- sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
- psb_intel_output->mode_dev = mode_dev;
- connector = &psb_intel_output->base;
- encoder = &psb_intel_output->enc;
- drm_connector_init(dev, &psb_intel_output->base,
- &cdv_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_DVID);
-
- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_TMDS);
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
- psb_intel_output->type = INTEL_OUTPUT_HDMI;
- hdmi_priv->hdmi_reg = reg;
- hdmi_priv->has_hdmi_sink = false;
- psb_intel_output->dev_priv = hdmi_priv;
-
- drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
- drm_connector_helper_add(connector,
- &cdv_hdmi_connector_helper_funcs);
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- drm_connector_attach_property(connector,
- dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
-
- switch (reg) {
- case SDVOB:
- ddc_bus = GPIOE;
- break;
- case SDVOC:
- ddc_bus = GPIOD;
- break;
- default:
- DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
- goto failed_ddc;
- break;
- }
-
- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
- ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
-
- if (!psb_intel_output->ddc_bus) {
- dev_err(dev->dev, "No ddc adapter available!\n");
- goto failed_ddc;
- }
- psb_intel_output->hdmi_i2c_adapter =
- &(psb_intel_output->ddc_bus->adapter);
- hdmi_priv->dev = dev;
- drm_sysfs_connector_add(connector);
- return;
-
-failed_ddc:
- drm_encoder_cleanup(&psb_intel_output->enc);
- drm_connector_cleanup(&psb_intel_output->base);
- kfree(psb_intel_output);
-}
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
deleted file mode 100644
index 988b2d0acf43..000000000000
--- a/drivers/staging/gma500/cdv_intel_lvds.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright © 2006-2011 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/dmi.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-#include "cdv_device.h"
-
-/**
- * LVDS I2C backlight control macros
- */
-#define BRIGHTNESS_MAX_LEVEL 100
-#define BRIGHTNESS_MASK 0xFF
-#define BLC_I2C_TYPE 0x01
-#define BLC_PWM_TYPT 0x02
-
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-
-#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE)
-#define PSB_BLC_MIN_PWM_REG_FREQ (0x2)
-#define PSB_BLC_PWM_PRECISION_FACTOR (10)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-
-struct cdv_intel_lvds_priv {
- /**
- * Saved LVDO output states
- */
- uint32_t savePP_ON;
- uint32_t savePP_OFF;
- uint32_t saveLVDS;
- uint32_t savePP_CONTROL;
- uint32_t savePP_CYCLE;
- uint32_t savePFIT_CONTROL;
- uint32_t savePFIT_PGM_RATIOS;
- uint32_t saveBLC_PWM_CTL;
-};
-
-/*
- * Returns the maximum level of the backlight duty cycle field.
- */
-static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 retval;
-
- if (gma_power_begin(dev, false)) {
- retval = ((REG_READ(BLC_PWM_CTL) &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
- gma_power_end(dev);
- } else
- retval = ((dev_priv->saveBLC_PWM_CTL &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
- return retval;
-}
-
-/*
- * Set LVDS backlight level by I2C command
- */
-static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
- unsigned int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
- u8 out_buf[2];
- unsigned int blc_i2c_brightness;
-
- struct i2c_msg msgs[] = {
- {
- .addr = lvds_i2c_bus->slave_addr,
- .flags = 0,
- .len = 2,
- .buf = out_buf,
- }
- };
-
- blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
- BRIGHTNESS_MASK /
- BRIGHTNESS_MAX_LEVEL);
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
-
- out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
- out_buf[1] = (u8)blc_i2c_brightness;
-
- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
- return 0;
-
- DRM_ERROR("I2C transfer error\n");
- return -1;
-}
-
-
-static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- u32 max_pwm_blc;
- u32 blc_pwm_duty_cycle;
-
- max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
-
- /*BLC_PWM_CTL Should be initiated while backlight device init*/
- BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
-
- blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
-
- blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
- REG_WRITE(BLC_PWM_CTL,
- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
- (blc_pwm_duty_cycle));
-
- return 0;
-}
-
-/*
- * Set LVDS backlight level either by I2C or PWM
- */
-void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->lvds_bl) {
- DRM_ERROR("NO LVDS Backlight Info\n");
- return;
- }
-
- if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
- cdv_lvds_i2c_set_brightness(dev, level);
- else
- cdv_lvds_pwm_set_brightness(dev, level);
-}
-
-/**
- * Sets the backlight level.
- *
- * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
- */
-static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 blc_pwm_ctl;
-
- if (gma_power_begin(dev, false)) {
- blc_pwm_ctl =
- REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
- REG_WRITE(BLC_PWM_CTL,
- (blc_pwm_ctl |
- (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
- gma_power_end(dev);
- } else {
- blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
- ~BACKLIGHT_DUTY_CYCLE_MASK;
- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
- (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
- }
-}
-
-/**
- * Sets the power state for the panel.
- */
-static void cdv_intel_lvds_set_power(struct drm_device *dev,
- struct psb_intel_output *output, bool on)
-{
- u32 pp_status;
-
- if (!gma_power_begin(dev, true))
- return;
-
- if (on) {
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
- POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
-
- cdv_intel_lvds_set_backlight(dev,
- output->
- mode_dev->backlight_duty_cycle);
- } else {
- cdv_intel_lvds_set_backlight(dev, 0);
-
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
- ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while (pp_status & PP_ON);
- }
- gma_power_end(dev);
-}
-
-static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- if (mode == DRM_MODE_DPMS_ON)
- cdv_intel_lvds_set_power(dev, output, true);
- else
- cdv_intel_lvds_set_power(dev, output, false);
- /* XXX: We never power down the LVDS pairs. */
-}
-
-static void cdv_intel_lvds_save(struct drm_connector *connector)
-{
-}
-
-static void cdv_intel_lvds_restore(struct drm_connector *connector)
-{
-}
-
-int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct drm_display_mode *fixed_mode =
- psb_intel_output->mode_dev->panel_fixed_mode;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- return MODE_NO_INTERLACE;
-
- if (fixed_mode) {
- if (mode->hdisplay > fixed_mode->hdisplay)
- return MODE_PANEL;
- if (mode->vdisplay > fixed_mode->vdisplay)
- return MODE_PANEL;
- }
- return MODE_OK;
-}
-
-bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct psb_intel_mode_device *mode_dev =
- enc_to_psb_intel_output(encoder)->mode_dev;
- struct drm_device *dev = encoder->dev;
- struct drm_encoder *tmp_encoder;
- struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
-
- /* Should never happen!! */
- list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
- head) {
- if (tmp_encoder != encoder
- && tmp_encoder->crtc == encoder->crtc) {
- printk(KERN_ERR "Can't enable LVDS and another "
- "encoder on the same pipe\n");
- return false;
- }
- }
-
- /*
- * If we have timings from the BIOS for the panel, put them in
- * to the adjusted mode. The CRTC will be set up for this mode,
- * with the panel scaling set up to source from the H/VDisplay
- * of the original mode.
- */
- if (panel_fixed_mode != NULL) {
- adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
- adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
- adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
- adjusted_mode->htotal = panel_fixed_mode->htotal;
- adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
- adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
- adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
- adjusted_mode->vtotal = panel_fixed_mode->vtotal;
- adjusted_mode->clock = panel_fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode,
- CRTC_INTERLACE_HALVE_V);
- }
-
- /*
- * XXX: It would be nice to support lower refresh rates on the
- * panels to reduce power consumption, and perhaps match the
- * user's requested refresh rate.
- */
-
- return true;
-}
-
-static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (!gma_power_begin(dev, true))
- return;
-
- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
- BACKLIGHT_DUTY_CYCLE_MASK);
-
- cdv_intel_lvds_set_power(dev, output, false);
-
- gma_power_end(dev);
-}
-
-static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (mode_dev->backlight_duty_cycle == 0)
- mode_dev->backlight_duty_cycle =
- cdv_intel_lvds_get_max_backlight(dev);
-
- cdv_intel_lvds_set_power(dev, output, true);
-}
-
-static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pfit_control;
-
- /*
- * The LVDS pin pair will already have been turned on in the
- * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
- * settings.
- */
-
- /*
- * Enable automatic panel scaling so that non-native modes fill the
- * screen. Should be enabled before the pipe is enabled, according to
- * register description and PRM.
- */
- if (mode->hdisplay != adjusted_mode->hdisplay ||
- mode->vdisplay != adjusted_mode->vdisplay)
- pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
- HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- else
- pfit_control = 0;
-
- if (dev_priv->lvds_dither)
- pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
- REG_WRITE(PFIT_CONTROL, pfit_control);
-}
-
-/**
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status cdv_intel_lvds_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/**
- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
- */
-static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_mode_device *mode_dev =
- psb_intel_output->mode_dev;
- int ret;
-
- ret = psb_intel_ddc_get_modes(psb_intel_output);
-
- if (ret)
- return ret;
-
- /* Didn't get an EDID, so
- * Set wide sync ranges so we get all modes
- * handed to valid_mode for checking
- */
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
- if (mode_dev->panel_fixed_mode != NULL) {
- struct drm_display_mode *mode =
- drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
- drm_mode_probed_add(connector, mode);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * cdv_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
-void cdv_intel_lvds_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-int cdv_intel_lvds_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- struct drm_encoder *encoder = connector->encoder;
-
- if (!strcmp(property->name, "scaling mode") && encoder) {
- struct psb_intel_crtc *crtc =
- to_psb_intel_crtc(encoder->crtc);
- uint64_t curValue;
-
- if (!crtc)
- return -1;
-
- switch (value) {
- case DRM_MODE_SCALE_FULLSCREEN:
- break;
- case DRM_MODE_SCALE_NO_SCALE:
- break;
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- return -1;
- }
-
- if (drm_connector_property_get_value(connector,
- property,
- &curValue))
- return -1;
-
- if (curValue == value)
- return 0;
-
- if (drm_connector_property_set_value(connector,
- property,
- value))
- return -1;
-
- if (crtc->saved_mode.hdisplay != 0 &&
- crtc->saved_mode.vdisplay != 0) {
- if (!drm_crtc_helper_set_mode(encoder->crtc,
- &crtc->saved_mode,
- encoder->crtc->x,
- encoder->crtc->y,
- encoder->crtc->fb))
- return -1;
- }
- } else if (!strcmp(property->name, "backlight") && encoder) {
- if (drm_connector_property_set_value(connector,
- property,
- value))
- return -1;
- else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv =
- encoder->dev->dev_private;
- struct backlight_device *bd =
- dev_priv->backlight_device;
- bd->props.brightness = value;
- backlight_update_status(bd);
-#endif
- }
- } else if (!strcmp(property->name, "DPMS") && encoder) {
- struct drm_encoder_helper_funcs *helpers =
- encoder->helper_private;
- helpers->dpms(encoder, value);
- }
- return 0;
-}
-
-static const struct drm_encoder_helper_funcs
- cdv_intel_lvds_helper_funcs = {
- .dpms = cdv_intel_lvds_encoder_dpms,
- .mode_fixup = cdv_intel_lvds_mode_fixup,
- .prepare = cdv_intel_lvds_prepare,
- .mode_set = cdv_intel_lvds_mode_set,
- .commit = cdv_intel_lvds_commit,
-};
-
-static const struct drm_connector_helper_funcs
- cdv_intel_lvds_connector_helper_funcs = {
- .get_modes = cdv_intel_lvds_get_modes,
- .mode_valid = cdv_intel_lvds_mode_valid,
- .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .save = cdv_intel_lvds_save,
- .restore = cdv_intel_lvds_restore,
- .detect = cdv_intel_lvds_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = cdv_intel_lvds_set_property,
- .destroy = cdv_intel_lvds_destroy,
-};
-
-
-static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
- .destroy = cdv_intel_lvds_enc_destroy,
-};
-
-/**
- * cdv_intel_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void cdv_intel_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev)
-{
- struct psb_intel_output *psb_intel_output;
- struct cdv_intel_lvds_priv *lvds_priv;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- struct drm_display_mode *scan;
- struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 lvds;
- int pipe;
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
- sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
-
- psb_intel_output->dev_priv = lvds_priv;
-
- psb_intel_output->mode_dev = mode_dev;
- connector = &psb_intel_output->base;
- encoder = &psb_intel_output->enc;
-
-
- drm_connector_init(dev, &psb_intel_output->base,
- &cdv_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
-
- drm_encoder_init(dev, &psb_intel_output->enc,
- &cdv_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
-
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
- psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
- drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
- drm_connector_helper_add(connector,
- &cdv_intel_lvds_connector_helper_funcs);
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- /*Attach connector properties*/
- drm_connector_attach_property(connector,
- dev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_FULLSCREEN);
- drm_connector_attach_property(connector,
- dev_priv->backlight_property,
- BRIGHTNESS_MAX_LEVEL);
-
- /**
- * Set up I2C bus
- * FIXME: distroy i2c_bus when exit
- */
- psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
- GPIOB,
- "LVDSBLC_B");
- if (!psb_intel_output->i2c_bus) {
- dev_printk(KERN_ERR,
- &dev->pdev->dev, "I2C bus registration failed.\n");
- goto failed_blc_i2c;
- }
- psb_intel_output->i2c_bus->slave_addr = 0x2C;
- dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
-
- /*
- * LVDS discovery:
- * 1) check for EDID on DDC
- * 2) check for VBT data
- * 3) check to see if LVDS is already on
- * if none of the above, no panel
- * 4) make sure lid is open
- * if closed, act like it's not there for now
- */
-
- /* Set up the DDC bus. */
- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
- GPIOC,
- "LVDSDDC_C");
- if (!psb_intel_output->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev,
- "DDC bus registration " "failed.\n");
- goto failed_ddc;
- }
-
- /*
- * Attempt to get the fixed panel mode from DDC. Assume that the
- * preferred mode is the right one.
- */
- psb_intel_ddc_get_modes(psb_intel_output);
- list_for_each_entry(scan, &connector->probed_modes, head) {
- if (scan->type & DRM_MODE_TYPE_PREFERRED) {
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, scan);
- goto out; /* FIXME: check for quirks */
- }
- }
-
- /* Failed to get EDID, what about VBT? do we need this?*/
- if (dev_priv->lfp_lvds_vbt_mode) {
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
- if (mode_dev->panel_fixed_mode) {
- mode_dev->panel_fixed_mode->type |=
- DRM_MODE_TYPE_PREFERRED;
- goto out; /* FIXME: check for quirks */
- }
- }
- /*
- * If we didn't get EDID, try checking if the panel is already turned
- * on. If so, assume that whatever is currently programmed is the
- * correct mode.
- */
- lvds = REG_READ(LVDS);
- pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
- crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
-
- if (crtc && (lvds & LVDS_PORT_EN)) {
- mode_dev->panel_fixed_mode =
- cdv_intel_crtc_mode_get(dev, crtc);
- if (mode_dev->panel_fixed_mode) {
- mode_dev->panel_fixed_mode->type |=
- DRM_MODE_TYPE_PREFERRED;
- goto out; /* FIXME: check for quirks */
- }
- }
-
- /* If we still don't have a mode after all that, give up. */
- if (!mode_dev->panel_fixed_mode) {
- DRM_DEBUG
- ("Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
- }
-
-out:
- drm_sysfs_connector_add(connector);
- return;
-
-failed_find:
- printk(KERN_ERR "Failed find\n");
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-failed_ddc:
- printk(KERN_ERR "Failed DDC\n");
- if (psb_intel_output->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-failed_blc_i2c:
- printk(KERN_ERR "Failed BLC\n");
- drm_encoder_cleanup(encoder);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h
deleted file mode 100644
index d58ba9bd010f..000000000000
--- a/drivers/staging/gma500/displays/hdmi.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef HDMI_H
-#define HDMI_H
-
-extern void hdmi_init(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h
deleted file mode 100644
index 84bae5c8c552..000000000000
--- a/drivers/staging/gma500/displays/pyr_cmd.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef PYR_CMD_H
-#define PYR_CMD_H
-
-extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-
-#endif
-
diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h
deleted file mode 100644
index ce98860fa68a..000000000000
--- a/drivers/staging/gma500/displays/pyr_vid.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef PYR_VID_H
-#define PYR_VID_H
-
-extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h
deleted file mode 100644
index 641e85eedece..000000000000
--- a/drivers/staging/gma500/displays/tmd_cmd.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef TMD_CMD_H
-#define TMD_CMD_H
-
-extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h
deleted file mode 100644
index 7a5fa3b935e3..000000000000
--- a/drivers/staging/gma500/displays/tmd_vid.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef TMD_VID_H
-#define TMD_VID_H
-
-extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h
deleted file mode 100644
index 610552730d71..000000000000
--- a/drivers/staging/gma500/displays/tpo_cmd.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef TPO_CMD_H
-#define TPO_CMD_H
-
-extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-/* extern struct drm_display_mode * */
-/* tpo_cmd_get_config_mode(struct drm_device *dev); */
-
-#endif
diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h
deleted file mode 100644
index c24f05722de1..000000000000
--- a/drivers/staging/gma500/displays/tpo_vid.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#ifndef TPO_VID_H
-#define TPO_VID_H
-
-extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
-
-#endif
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
deleted file mode 100644
index b00761cba144..000000000000
--- a/drivers/staging/gma500/framebuffer.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "framebuffer.h"
-#include "gtt.h"
-
-#include "mdfld_output.h"
-
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle);
-
-static const struct drm_framebuffer_funcs psb_fb_funcs = {
- .destroy = psb_user_framebuffer_destroy,
- .create_handle = psb_user_framebuffer_create_handle,
-};
-
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct psb_fbdev *fbdev = info->par;
- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
- uint32_t v;
-
- if (!fb)
- return -ENOMEM;
-
- if (regno > 255)
- return 1;
-
- red = CMAP_TOHW(red, info->var.red.length);
- blue = CMAP_TOHW(blue, info->var.blue.length);
- green = CMAP_TOHW(green, info->var.green.length);
- transp = CMAP_TOHW(transp, info->var.transp.length);
-
- v = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
-
- if (regno < 16) {
- switch (fb->bits_per_pixel) {
- case 16:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- case 24:
- case 32:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- }
- }
-
- return 0;
-}
-
-static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
-
- /*
- * We have to poke our nose in here. The core fb code assumes
- * panning is part of the hardware that can be invoked before
- * the actual fb is mapped. In our case that isn't quite true.
- */
- if (psbfb->gtt->npage)
- psb_gtt_roll(dev, psbfb->gtt, var->yoffset);
- return 0;
-}
-
-void psbfb_suspend(struct drm_device *dev)
-{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
- console_lock();
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
- struct fb_info *info = psbfb->fbdev;
- fb_set_suspend(info, 1);
- drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
- }
- mutex_unlock(&dev->mode_config.mutex);
- console_unlock();
-}
-
-void psbfb_resume(struct drm_device *dev)
-{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
- console_lock();
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
- struct fb_info *info = psbfb->fbdev;
- fb_set_suspend(info, 0);
- drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
- }
- mutex_unlock(&dev->mode_config.mutex);
- console_unlock();
- drm_helper_disable_unused_functions(dev);
-}
-
-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct psb_framebuffer *psbfb = vma->vm_private_data;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- int page_num;
- int i;
- unsigned long address;
- int ret;
- unsigned long pfn;
- /* FIXME: assumes fb at stolen base which may not be true */
- unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
-
- page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- address = (unsigned long)vmf->virtual_address;
-
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- for (i = 0; i < page_num; i++) {
- pfn = (phys_addr >> PAGE_SHIFT);
-
- ret = vm_insert_mixed(vma, address, pfn);
- if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
- break;
- else if (unlikely(ret != 0)) {
- ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
- return ret;
- }
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- }
- return VM_FAULT_NOPAGE;
-}
-
-static void psbfb_vm_open(struct vm_area_struct *vma)
-{
-}
-
-static void psbfb_vm_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct psbfb_vm_ops = {
- .fault = psbfb_vm_fault,
- .open = psbfb_vm_open,
- .close = psbfb_vm_close
-};
-
-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
-
- if (vma->vm_pgoff != 0)
- return -EINVAL;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
-
- if (!psbfb->addr_space)
- psbfb->addr_space = vma->vm_file->f_mapping;
- /*
- * If this is a GEM object then info->screen_base is the virtual
- * kernel remapping of the object. FIXME: Review if this is
- * suitable for our mmap work
- */
- vma->vm_ops = &psbfb_vm_ops;
- vma->vm_private_data = (void *)psbfb;
- vma->vm_flags |= VM_RESERVED | VM_IO |
- VM_MIXEDMAP | VM_DONTEXPAND;
- return 0;
-}
-
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg)
-{
- return -ENOTTY;
-}
-
-static struct fb_ops psbfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = psbfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_mmap = psbfb_mmap,
- .fb_sync = psbfb_sync,
- .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_roll_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_pan_display = psbfb_pan,
- .fb_mmap = psbfb_mmap,
- .fb_sync = psbfb_sync,
- .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_unaccel_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_mmap = psbfb_mmap,
- .fb_ioctl = psbfb_ioctl,
-};
-
-/**
- * psb_framebuffer_init - initialize a framebuffer
- * @dev: our DRM device
- * @fb: framebuffer to set up
- * @mode_cmd: mode description
- * @gt: backing object
- *
- * Configure and fill in the boilerplate for our frame buffer. Return
- * 0 on success or an error code if we fail.
- */
-static int psb_framebuffer_init(struct drm_device *dev,
- struct psb_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct gtt_range *gt)
-{
- u32 bpp, depth;
- int ret;
-
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
-
- if (mode_cmd->pitches[0] & 63)
- return -EINVAL;
- switch (bpp) {
- case 8:
- case 16:
- case 24:
- case 32:
- break;
- default:
- return -EINVAL;
- }
- ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
- if (ret) {
- dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
- return ret;
- }
- drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
- fb->gtt = gt;
- return 0;
-}
-
-/**
- * psb_framebuffer_create - create a framebuffer backed by gt
- * @dev: our DRM device
- * @mode_cmd: the description of the requested mode
- * @gt: the backing object
- *
- * Create a framebuffer object backed by the gt, and fill in the
- * boilerplate required
- *
- * TODO: review object references
- */
-
-static struct drm_framebuffer *psb_framebuffer_create
- (struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct gtt_range *gt)
-{
- struct psb_framebuffer *fb;
- int ret;
-
- fb = kzalloc(sizeof(*fb), GFP_KERNEL);
- if (!fb)
- return ERR_PTR(-ENOMEM);
-
- ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
- if (ret) {
- kfree(fb);
- return ERR_PTR(ret);
- }
- return &fb->base;
-}
-
-/**
- * psbfb_alloc - allocate frame buffer memory
- * @dev: the DRM device
- * @aligned_size: space needed
- * @force: fall back to GEM buffers if need be
- *
- * Allocate the frame buffer. In the usual case we get a GTT range that
- * is stolen memory backed and life is simple. If there isn't sufficient
- * stolen memory or the system has no stolen memory we allocate a range
- * and back it with a GEM object.
- *
- * In this case the GEM object has no handle.
- */
-static struct gtt_range *psbfb_alloc(struct drm_device *dev,
- int aligned_size, int force)
-{
- struct gtt_range *backing;
- /* Begin by trying to use stolen memory backing */
- backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
- if (backing) {
- if (drm_gem_private_object_init(dev,
- &backing->gem, aligned_size) == 0)
- return backing;
- psb_gtt_free_range(dev, backing);
- }
- if (!force)
- return NULL;
-
- /* Next try using GEM host memory */
- backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
- if (backing == NULL)
- return NULL;
-
- /* Now back it with an object */
- if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
- psb_gtt_free_range(dev, backing);
- return NULL;
- }
- return backing;
-}
-
-/**
- * psbfb_create - create a framebuffer
- * @fbdev: the framebuffer device
- * @sizes: specification of the layout
- *
- * Create a framebuffer to the specifications provided
- */
-static int psbfb_create(struct psb_fbdev *fbdev,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct drm_device *dev = fbdev->psb_fb_helper.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct fb_info *info;
- struct drm_framebuffer *fb;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_mode_fb_cmd2 mode_cmd;
- struct device *device = &dev->pdev->dev;
- int size;
- int ret;
- struct gtt_range *backing;
- int gtt_roll = 1;
- u32 bpp, depth;
-
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
- bpp = sizes->surface_bpp;
-
- /* No 24bit packed */
- if (bpp == 24)
- bpp = 32;
-
- /* Acceleration via the GTT requires pitch to be 4096 byte aligned
- (ie 1024 or 2048 pixels in normal use) */
- mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096);
- depth = sizes->surface_depth;
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
-
- /* Allocate the framebuffer in the GTT with stolen page backing */
- backing = psbfb_alloc(dev, size, 0);
- if (backing == NULL) {
- /*
- * We couldn't get the space we wanted, fall back to the
- * display engine requirement instead. The HW requires
- * the pitch to be 64 byte aligned
- */
-
- gtt_roll = 0; /* Don't use GTT accelerated scrolling */
-
- mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
- depth = sizes->surface_depth;
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
-
- /* Allocate the framebuffer in the GTT with stolen page
- backing when there is room */
- backing = psbfb_alloc(dev, size, 1);
- if (backing == NULL)
- return -ENOMEM;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- info = framebuffer_alloc(0, device);
- if (!info) {
- ret = -ENOMEM;
- goto out_err1;
- }
- info->par = fbdev;
-
- mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
- ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
- if (ret)
- goto out_unref;
-
- fb = &psbfb->base;
- psbfb->fbdev = info;
-
- fbdev->psb_fb_helper.fb = fb;
- fbdev->psb_fb_helper.fbdev = info;
-
- strcpy(info->fix.id, "psbfb");
-
- info->flags = FBINFO_DEFAULT;
- if (gtt_roll) { /* GTT rolling seems best */
- info->fbops = &psbfb_roll_ops;
- info->flags |= FBINFO_HWACCEL_YPAN;
- }
- else if (dev_priv->ops->accel_2d) /* 2D engine */
- info->fbops = &psbfb_ops;
- else /* Software */
- info->fbops = &psbfb_unaccel_ops;
-
- ret = fb_alloc_cmap(&info->cmap, 256, 0);
- if (ret) {
- ret = -ENOMEM;
- goto out_unref;
- }
-
- info->fix.smem_start = dev->mode_config.fb_base;
- info->fix.smem_len = size;
- info->fix.ywrapstep = gtt_roll;
- info->fix.ypanstep = gtt_roll;
-
- if (backing->stolen) {
- /* Accessed stolen memory directly */
- info->screen_base = (char *)dev_priv->vram_addr +
- backing->offset;
- } else {
- /* Pin the pages into the GTT and create a mapping to them */
- psb_gtt_pin(backing);
- info->screen_base = vm_map_ram(backing->pages, backing->npage,
- -1, PAGE_KERNEL);
- if (info->screen_base == NULL) {
- psb_gtt_unpin(backing);
- ret = -ENOMEM;
- goto out_unref;
- }
- psbfb->vm_map = 1;
- }
- info->screen_size = size;
-
- if (dev_priv->gtt.stolen_size) {
- info->apertures = alloc_apertures(1);
- if (!info->apertures) {
- ret = -ENOMEM;
- goto out_unref;
- }
- info->apertures->ranges[0].base = dev->mode_config.fb_base;
- info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
- }
-
- drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
- drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
- sizes->fb_width, sizes->fb_height);
-
- info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
- info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
- info->pixmap.size = 64 * 1024;
- info->pixmap.buf_align = 8;
- info->pixmap.access_align = 32;
- info->pixmap.flags = FB_PIXMAP_SYSTEM;
- info->pixmap.scan_align = 1;
-
- dev_info(dev->dev, "allocated %dx%d fb\n",
- psbfb->base.width, psbfb->base.height);
-
- mutex_unlock(&dev->struct_mutex);
- return 0;
-out_unref:
- if (backing->stolen)
- psb_gtt_free_range(dev, backing);
- else {
- if (psbfb->vm_map)
- vm_unmap_ram(info->screen_base, backing->npage);
- drm_gem_object_unreference(&backing->gem);
- }
-out_err1:
- mutex_unlock(&dev->struct_mutex);
- psb_gtt_free_range(dev, backing);
- return ret;
-}
-
-/**
- * psb_user_framebuffer_create - create framebuffer
- * @dev: our DRM device
- * @filp: client file
- * @cmd: mode request
- *
- * Create a new framebuffer backed by a userspace GEM object
- */
-static struct drm_framebuffer *psb_user_framebuffer_create
- (struct drm_device *dev, struct drm_file *filp,
- struct drm_mode_fb_cmd2 *cmd)
-{
- struct gtt_range *r;
- struct drm_gem_object *obj;
-
- /*
- * Find the GEM object and thus the gtt range object that is
- * to back this space
- */
- obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]);
- if (obj == NULL)
- return ERR_PTR(-ENOENT);
-
- /* Let the core code do all the work */
- r = container_of(obj, struct gtt_range, gem);
- return psb_framebuffer_create(dev, cmd, r);
-}
-
-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
- u16 blue, int regno)
-{
-}
-
-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, int regno)
-{
-}
-
-static int psbfb_probe(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
- int new_fb = 0;
- int ret;
-
- if (!helper->fb) {
- ret = psbfb_create(psb_fbdev, sizes);
- if (ret)
- return ret;
- new_fb = 1;
- }
- return new_fb;
-}
-
-struct drm_fb_helper_funcs psb_fb_helper_funcs = {
- .gamma_set = psbfb_gamma_set,
- .gamma_get = psbfb_gamma_get,
- .fb_probe = psbfb_probe,
-};
-
-int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
-{
- struct fb_info *info;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
-
- if (fbdev->psb_fb_helper.fbdev) {
- info = fbdev->psb_fb_helper.fbdev;
-
- /* If this is our base framebuffer then kill any virtual map
- for the framebuffer layer and unpin it */
- if (psbfb->vm_map) {
- vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
- psb_gtt_unpin(psbfb->gtt);
- }
- unregister_framebuffer(info);
- if (info->cmap.len)
- fb_dealloc_cmap(&info->cmap);
- framebuffer_release(info);
- }
- drm_fb_helper_fini(&fbdev->psb_fb_helper);
- drm_framebuffer_cleanup(&psbfb->base);
-
- if (psbfb->gtt)
- drm_gem_object_unreference(&psbfb->gtt->gem);
- return 0;
-}
-
-int psb_fbdev_init(struct drm_device *dev)
-{
- struct psb_fbdev *fbdev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
- if (!fbdev) {
- dev_err(dev->dev, "no memory\n");
- return -ENOMEM;
- }
-
- dev_priv->fbdev = fbdev;
- fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
-
- drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
- INTELFB_CONN_LIMIT);
-
- drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
- drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
- return 0;
-}
-
-void psb_fbdev_fini(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->fbdev)
- return;
-
- psb_fbdev_destroy(dev, dev_priv->fbdev);
- kfree(dev_priv->fbdev);
- dev_priv->fbdev = NULL;
-}
-
-static void psbfb_output_poll_changed(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
- drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
-}
-
-/**
- * psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- * @fb: framebuffer
- * @file_priv: our DRM file
- * @handle: returned handle
- *
- * Our framebuffer object is a GTT range which also contains a GEM
- * object. We need to turn it into a handle for userspace. GEM will do
- * the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle)
-{
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->gtt;
- return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- * psb_user_framebuffer_destroy - destruct user created fb
- * @fb: framebuffer
- *
- * User framebuffers are backed by GEM objects so all we have to do is
- * clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->gtt;
- struct drm_device *dev = fb->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_fbdev *fbdev = dev_priv->fbdev;
- struct drm_crtc *crtc;
- int reset = 0;
-
- /* Should never get stolen memory for a user fb */
- WARN_ON(r->stolen);
-
- /* Check if we are erroneously live */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- if (crtc->fb == fb)
- reset = 1;
-
- if (reset)
- /*
- * Now force a sane response before we permit the DRM CRTC
- * layer to do stupid things like blank the display. Instead
- * we reset this framebuffer as if the user had forced a reset.
- * We must do this before the cleanup so that the DRM layer
- * doesn't get a chance to stick its oar in where it isn't
- * wanted.
- */
- drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
-
- /* Let DRM do its clean up */
- drm_framebuffer_cleanup(fb);
- /* We are no longer using the resource in GEM */
- drm_gem_object_unreference_unlocked(&r->gem);
- kfree(fb);
-}
-
-static const struct drm_mode_config_funcs psb_mode_funcs = {
- .fb_create = psb_user_framebuffer_create,
- .output_poll_changed = psbfb_output_poll_changed,
-};
-
-static int psb_create_backlight_property(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_property *backlight;
-
- if (dev_priv->backlight_property)
- return 0;
-
- backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "backlight", 2);
- backlight->values[0] = 0;
- backlight->values[1] = 100;
-
- dev_priv->backlight_property = backlight;
-
- return 0;
-}
-
-static void psb_setup_outputs(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_connector *connector;
-
- drm_mode_create_scaling_mode_property(dev);
- psb_create_backlight_property(dev);
-
- dev_priv->ops->output_init(dev);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct drm_encoder *encoder = &psb_intel_output->enc;
- int crtc_mask = 0, clone_mask = 0;
-
- /* valid crtcs */
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_ANALOG:
- crtc_mask = (1 << 0);
- clone_mask = (1 << INTEL_OUTPUT_ANALOG);
- break;
- case INTEL_OUTPUT_SDVO:
- crtc_mask = ((1 << 0) | (1 << 1));
- clone_mask = (1 << INTEL_OUTPUT_SDVO);
- break;
- case INTEL_OUTPUT_LVDS:
- if (IS_MRST(dev))
- crtc_mask = (1 << 0);
- else
- crtc_mask = (1 << 1);
- clone_mask = (1 << INTEL_OUTPUT_LVDS);
- break;
- case INTEL_OUTPUT_MIPI:
- crtc_mask = (1 << 0);
- clone_mask = (1 << INTEL_OUTPUT_MIPI);
- break;
- case INTEL_OUTPUT_MIPI2:
- crtc_mask = (1 << 2);
- clone_mask = (1 << INTEL_OUTPUT_MIPI2);
- break;
- case INTEL_OUTPUT_HDMI:
- /* HDMI on crtc 1 for SoC devices and crtc 0 for
- Cedarview. HDMI on Poulsbo is only via external
- logic */
- if (IS_MFLD(dev) || IS_MRST(dev))
- crtc_mask = (1 << 1);
- else
- crtc_mask = (1 << 0); /* Cedarview */
- clone_mask = (1 << INTEL_OUTPUT_HDMI);
- break;
- }
- encoder->possible_crtcs = crtc_mask;
- encoder->possible_clones =
- psb_intel_connector_clones(dev, clone_mask);
- }
-}
-
-void psb_modeset_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
- int i;
-
- drm_mode_config_init(dev);
-
- dev->mode_config.min_width = 0;
- dev->mode_config.min_height = 0;
-
- dev->mode_config.funcs = (void *) &psb_mode_funcs;
-
- /* set memory base */
- /* MRST and PSB should use BAR 2*/
- pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
- &(dev->mode_config.fb_base));
-
- /* num pipes is 2 for PSB but 1 for Mrst */
- for (i = 0; i < dev_priv->num_pipe; i++)
- psb_intel_crtc_init(dev, i, mode_dev);
-
- dev->mode_config.max_width = 2048;
- dev->mode_config.max_height = 2048;
-
- psb_setup_outputs(dev);
-}
-
-void psb_modeset_cleanup(struct drm_device *dev)
-{
- mutex_lock(&dev->struct_mutex);
-
- drm_kms_helper_poll_fini(dev);
- psb_fbdev_fini(dev);
- drm_mode_config_cleanup(dev);
-
- mutex_unlock(&dev->struct_mutex);
-}
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h
deleted file mode 100644
index d1b2289447f0..000000000000
--- a/drivers/staging/gma500/framebuffer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _FRAMEBUFFER_H_
-#define _FRAMEBUFFER_H_
-
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-
-struct psb_framebuffer {
- struct drm_framebuffer base;
- struct address_space *addr_space;
- struct fb_info *fbdev;
- struct gtt_range *gtt;
- bool vm_map; /* True if we must undo a vm_map_ram */
-};
-
-struct psb_fbdev {
- struct drm_fb_helper psb_fb_helper;
- struct psb_framebuffer pfb;
-};
-
-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
-
-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
-
-#endif
-
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
deleted file mode 100644
index f6433c037d24..000000000000
--- a/drivers/staging/gma500/gem.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * psb GEM interface
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * 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.
- *
- * Authors: Alan Cox
- *
- * TODO:
- * - we need to work out if the MMU is relevant (eg for
- * accelerated operations on a GEM object)
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-
-int psb_gem_init_object(struct drm_gem_object *obj)
-{
- return -EINVAL;
-}
-
-void psb_gem_free_object(struct drm_gem_object *obj)
-{
- struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
- drm_gem_object_release_wrap(obj);
- /* This must occur last as it frees up the memory of the GEM object */
- psb_gtt_free_range(obj->dev, gtt);
-}
-
-int psb_gem_get_aperture(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- return -EINVAL;
-}
-
-/**
- * psb_gem_dumb_map_gtt - buffer mapping for dumb interface
- * @file: our drm client file
- * @dev: drm device
- * @handle: GEM handle to the object (from dumb_create)
- *
- * Do the necessary setup to allow the mapping of the frame buffer
- * into user memory. We don't have to do much here at the moment.
- */
-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset)
-{
- int ret = 0;
- struct drm_gem_object *obj;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- mutex_lock(&dev->struct_mutex);
-
- /* GEM does all our handle to object mapping */
- obj = drm_gem_object_lookup(dev, file, handle);
- if (obj == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
- /* What validation is needed here ? */
-
- /* Make it mmapable */
- if (!obj->map_list.map) {
- ret = gem_create_mmap_offset(obj);
- if (ret)
- goto out;
- }
- /* GEM should really work out the hash offsets for us */
- *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
-out:
- drm_gem_object_unreference(obj);
-unlock:
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-/**
- * psb_gem_create - create a mappable object
- * @file: the DRM file of the client
- * @dev: our device
- * @size: the size requested
- * @handlep: returned handle (opaque number)
- *
- * Create a GEM object, fill in the boilerplate and attach a handle to
- * it so that userspace can speak about it. This does the core work
- * for the various methods that do/will create GEM objects for things
- */
-static int psb_gem_create(struct drm_file *file,
- struct drm_device *dev, uint64_t size, uint32_t *handlep)
-{
- struct gtt_range *r;
- int ret;
- u32 handle;
-
- size = roundup(size, PAGE_SIZE);
-
- /* Allocate our object - for now a direct gtt range which is not
- stolen memory backed */
- r = psb_gtt_alloc_range(dev, size, "gem", 0);
- if (r == NULL) {
- dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
- return -ENOSPC;
- }
- /* Initialize the extra goodies GEM needs to do all the hard work */
- if (drm_gem_object_init(dev, &r->gem, size) != 0) {
- psb_gtt_free_range(dev, r);
- /* GEM doesn't give an error code so use -ENOMEM */
- dev_err(dev->dev, "GEM init failed for %lld\n", size);
- return -ENOMEM;
- }
- /* Give the object a handle so we can carry it more easily */
- ret = drm_gem_handle_create(file, &r->gem, &handle);
- if (ret) {
- dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
- &r->gem, size);
- drm_gem_object_release(&r->gem);
- psb_gtt_free_range(dev, r);
- return ret;
- }
- /* We have the initial and handle reference but need only one now */
- drm_gem_object_unreference(&r->gem);
- *handlep = handle;
- return 0;
-}
-
-/**
- * psb_gem_dumb_create - create a dumb buffer
- * @drm_file: our client file
- * @dev: our device
- * @args: the requested arguments copied from userspace
- *
- * Allocate a buffer suitable for use for a frame buffer of the
- * form described by user space. Give userspace a handle by which
- * to reference it.
- */
-int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args)
-{
- args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
- args->size = args->pitch * args->height;
- return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-/**
- * psb_gem_dumb_destroy - destroy a dumb buffer
- * @file: client file
- * @dev: our DRM device
- * @handle: the object handle
- *
- * Destroy a handle that was created via psb_gem_dumb_create, at least
- * we hope it was created that way. i915 seems to assume the caller
- * does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle)
-{
- /* No special work needed, drop the reference and see what falls out */
- return drm_gem_handle_delete(file, handle);
-}
-
-/**
- * psb_gem_fault - pagefault handler for GEM objects
- * @vma: the VMA of the GEM object
- * @vmf: fault detail
- *
- * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
- * does most of the work for us including the actual map/unmap calls
- * but we need to do the actual page work.
- *
- * This code eventually needs to handle faulting objects in and out
- * of the GTT and repacking it when we run out of space. We can put
- * that off for now and for our simple uses
- *
- * The VMA was set up by GEM. In doing so it also ensured that the
- * vma->vm_private_data points to the GEM object that is backing this
- * mapping.
- */
-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_gem_object *obj;
- struct gtt_range *r;
- int ret;
- unsigned long pfn;
- pgoff_t page_offset;
- struct drm_device *dev;
- struct drm_psb_private *dev_priv;
-
- obj = vma->vm_private_data; /* GEM object */
- dev = obj->dev;
- dev_priv = dev->dev_private;
-
- r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */
-
- /* Make sure we don't parallel update on a fault, nor move or remove
- something from beneath our feet */
- mutex_lock(&dev->struct_mutex);
-
- /* For now the mmap pins the object and it stays pinned. As things
- stand that will do us no harm */
- if (r->mmapping == 0) {
- ret = psb_gtt_pin(r);
- if (ret < 0) {
- dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
- goto fail;
- }
- r->mmapping = 1;
- }
-
- /* Page relative to the VMA start - we must calculate this ourselves
- because vmf->pgoff is the fake GEM offset */
- page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
- >> PAGE_SHIFT;
-
- /* CPU view of the page, don't go via the GART for CPU writes */
- if (r->stolen)
- pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
- else
- pfn = page_to_pfn(r->pages[page_offset]);
- ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
-fail:
- mutex_unlock(&dev->struct_mutex);
- switch (ret) {
- case 0:
- case -ERESTARTSYS:
- case -EINTR:
- return VM_FAULT_NOPAGE;
- case -ENOMEM:
- return VM_FAULT_OOM;
- default:
- return VM_FAULT_SIGBUS;
- }
-}
-
-static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
- int size, u32 *handle)
-{
- struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
- if (gtt == NULL)
- return -ENOMEM;
- if (drm_gem_private_object_init(dev, &gtt->gem, size) != 0)
- goto free_gtt;
- if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
- return 0;
-free_gtt:
- psb_gtt_free_range(dev, gtt);
- return -ENOMEM;
-}
-
-/*
- * GEM interfaces for our specific client
- */
-int psb_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_psb_gem_create *args = data;
- int ret;
- if (args->flags & PSB_GEM_CREATE_STOLEN) {
- ret = psb_gem_create_stolen(file, dev, args->size,
- &args->handle);
- if (ret == 0)
- return 0;
- /* Fall throguh */
- args->flags &= ~PSB_GEM_CREATE_STOLEN;
- }
- return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_psb_gem_mmap *args = data;
- return dev->driver->dumb_map_offset(file, dev,
- args->handle, &args->offset);
-}
-
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
deleted file mode 100644
index daac12120653..000000000000
--- a/drivers/staging/gma500/gem_glue.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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 <drm/drmP.h>
-#include <drm/drm.h>
-
-void drm_gem_object_release_wrap(struct drm_gem_object *obj)
-{
- /* Remove the list map if one is present */
- if (obj->map_list.map) {
- struct drm_gem_mm *mm = obj->dev->mm_private;
- struct drm_map_list *list = &obj->map_list;
- drm_ht_remove_item(&mm->offset_hash, &list->hash);
- drm_mm_put_block(list->file_offset_node);
- kfree(list->map);
- list->map = NULL;
- }
- drm_gem_object_release(obj);
-}
-
-/**
- * gem_create_mmap_offset - invent an mmap offset
- * @obj: our object
- *
- * Standard implementation of offset generation for mmap as is
- * duplicated in several drivers. This belongs in GEM.
- */
-int gem_create_mmap_offset(struct drm_gem_object *obj)
-{
- struct drm_device *dev = obj->dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_map_list *list;
- struct drm_local_map *map;
- int ret;
-
- list = &obj->map_list;
- list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
- if (list->map == NULL)
- return -ENOMEM;
- map = list->map;
- map->type = _DRM_GEM;
- map->size = obj->size;
- map->handle = obj;
-
- list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
- obj->size / PAGE_SIZE, 0, 0);
- if (!list->file_offset_node) {
- dev_err(dev->dev, "failed to allocate offset for bo %d\n",
- obj->name);
- ret = -ENOSPC;
- goto free_it;
- }
- list->file_offset_node = drm_mm_get_block(list->file_offset_node,
- obj->size / PAGE_SIZE, 0);
- if (!list->file_offset_node) {
- ret = -ENOMEM;
- goto free_it;
- }
- list->hash.key = list->file_offset_node->start;
- ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
- if (ret) {
- dev_err(dev->dev, "failed to add to map hash\n");
- goto free_mm;
- }
- return 0;
-
-free_mm:
- drm_mm_put_block(list->file_offset_node);
-free_it:
- kfree(list->map);
- list->map = NULL;
- return ret;
-}
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h
deleted file mode 100644
index ce5ce30f74db..000000000000
--- a/drivers/staging/gma500/gem_glue.h
+++ /dev/null
@@ -1,2 +0,0 @@
-extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
-extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
deleted file mode 100644
index e770bd190a5c..000000000000
--- a/drivers/staging/gma500/gtt.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
- * Alan Cox <alan@linux.intel.com>
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-
-
-/*
- * GTT resource allocator - manage page mappings in GTT space
- */
-
-/**
- * psb_gtt_mask_pte - generate GTT pte entry
- * @pfn: page number to encode
- * @type: type of memory in the GTT
- *
- * Set the GTT entry for the appropriate memory type.
- */
-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
-{
- uint32_t mask = PSB_PTE_VALID;
-
- if (type & PSB_MMU_CACHED_MEMORY)
- mask |= PSB_PTE_CACHED;
- if (type & PSB_MMU_RO_MEMORY)
- mask |= PSB_PTE_RO;
- if (type & PSB_MMU_WO_MEMORY)
- mask |= PSB_PTE_WO;
-
- return (pfn << PAGE_SHIFT) | mask;
-}
-
-/**
- * psb_gtt_entry - find the GTT entries for a gtt_range
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Given a gtt_range object return the GTT offset of the page table
- * entries for this gtt_range
- */
-u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long offset;
-
- offset = r->resource.start - dev_priv->gtt_mem->start;
-
- return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
-}
-
-/**
- * psb_gtt_insert - put an object into the GTT
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Take our preallocated GTT range and insert the GEM object into
- * the GTT. This is protected via the gtt mutex which the caller
- * must hold.
- */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
-{
- u32 *gtt_slot, pte;
- struct page **pages;
- int i;
-
- if (r->pages == NULL) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- WARN_ON(r->stolen); /* refcount these maybe ? */
-
- gtt_slot = psb_gtt_entry(dev, r);
- pages = r->pages;
-
- /* Make sure changes are visible to the GPU */
- set_pages_array_uc(pages, r->npage);
-
- /* Write our page entries into the GTT itself */
- for (i = r->roll; i < r->npage; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- for (i = 0; i < r->roll; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- /* Make sure all the entries are set before we return */
- ioread32(gtt_slot - 1);
-
- return 0;
-}
-
-/**
- * psb_gtt_remove - remove an object from the GTT
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Remove a preallocated GTT range from the GTT. Overwrite all the
- * page table entries with the dummy page. This is protected via the gtt
- * mutex which the caller must hold.
- */
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 *gtt_slot, pte;
- int i;
-
- WARN_ON(r->stolen);
-
- gtt_slot = psb_gtt_entry(dev, r);
- pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
-
- for (i = 0; i < r->npage; i++)
- iowrite32(pte, gtt_slot++);
- ioread32(gtt_slot - 1);
- set_pages_array_wb(r->pages, r->npage);
-}
-
-/**
- * psb_gtt_roll - set scrolling position
- * @dev: our DRM device
- * @r: the gtt mapping we are using
- * @roll: roll offset
- *
- * Roll an existing pinned mapping by moving the pages through the GTT.
- * This allows us to implement hardware scrolling on the consoles without
- * a 2D engine
- */
-void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
-{
- u32 *gtt_slot, pte;
- int i;
-
- if (roll >= r->npage) {
- WARN_ON(1);
- return;
- }
-
- r->roll = roll;
-
- /* Not currently in the GTT - no worry we will write the mapping at
- the right position when it gets pinned */
- if (!r->stolen && !r->in_gart)
- return;
-
- gtt_slot = psb_gtt_entry(dev, r);
-
- for (i = r->roll; i < r->npage; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- for (i = 0; i < r->roll; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- ioread32(gtt_slot - 1);
-}
-
-/**
- * psb_gtt_attach_pages - attach and pin GEM pages
- * @gt: the gtt range
- *
- * Pin and build an in kernel list of the pages that back our GEM object.
- * While we hold this the pages cannot be swapped out. This is protected
- * via the gtt mutex which the caller must hold.
- */
-static int psb_gtt_attach_pages(struct gtt_range *gt)
-{
- struct inode *inode;
- struct address_space *mapping;
- int i;
- struct page *p;
- int pages = gt->gem.size / PAGE_SIZE;
-
- WARN_ON(gt->pages);
-
- /* This is the shared memory object that backs the GEM resource */
- inode = gt->gem.filp->f_path.dentry->d_inode;
- mapping = inode->i_mapping;
-
- gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
- if (gt->pages == NULL)
- return -ENOMEM;
- gt->npage = pages;
-
- for (i = 0; i < pages; i++) {
- /* FIXME: needs updating as per mail from Hugh Dickins */
- p = read_cache_page_gfp(mapping, i,
- __GFP_COLD | GFP_KERNEL);
- if (IS_ERR(p))
- goto err;
- gt->pages[i] = p;
- }
- return 0;
-
-err:
- while (i--)
- page_cache_release(gt->pages[i]);
- kfree(gt->pages);
- gt->pages = NULL;
- return PTR_ERR(p);
-}
-
-/**
- * psb_gtt_detach_pages - attach and pin GEM pages
- * @gt: the gtt range
- *
- * Undo the effect of psb_gtt_attach_pages. At this point the pages
- * must have been removed from the GTT as they could now be paged out
- * and move bus address. This is protected via the gtt mutex which the
- * caller must hold.
- */
-static void psb_gtt_detach_pages(struct gtt_range *gt)
-{
- int i;
- for (i = 0; i < gt->npage; i++) {
- /* FIXME: do we need to force dirty */
- set_page_dirty(gt->pages[i]);
- page_cache_release(gt->pages[i]);
- }
- kfree(gt->pages);
- gt->pages = NULL;
-}
-
-/**
- * psb_gtt_pin - pin pages into the GTT
- * @gt: range to pin
- *
- * Pin a set of pages into the GTT. The pins are refcounted so that
- * multiple pins need multiple unpins to undo.
- *
- * Non GEM backed objects treat this as a no-op as they are always GTT
- * backed objects.
- */
-int psb_gtt_pin(struct gtt_range *gt)
-{
- int ret = 0;
- struct drm_device *dev = gt->gem.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- mutex_lock(&dev_priv->gtt_mutex);
-
- if (gt->in_gart == 0 && gt->stolen == 0) {
- ret = psb_gtt_attach_pages(gt);
- if (ret < 0)
- goto out;
- ret = psb_gtt_insert(dev, gt);
- if (ret < 0) {
- psb_gtt_detach_pages(gt);
- goto out;
- }
- }
- gt->in_gart++;
-out:
- mutex_unlock(&dev_priv->gtt_mutex);
- return ret;
-}
-
-/**
- * psb_gtt_unpin - Drop a GTT pin requirement
- * @gt: range to pin
- *
- * Undoes the effect of psb_gtt_pin. On the last drop the GEM object
- * will be removed from the GTT which will also drop the page references
- * and allow the VM to clean up or page stuff.
- *
- * Non GEM backed objects treat this as a no-op as they are always GTT
- * backed objects.
- */
-void psb_gtt_unpin(struct gtt_range *gt)
-{
- struct drm_device *dev = gt->gem.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- mutex_lock(&dev_priv->gtt_mutex);
-
- WARN_ON(!gt->in_gart);
-
- gt->in_gart--;
- if (gt->in_gart == 0 && gt->stolen == 0) {
- psb_gtt_remove(dev, gt);
- psb_gtt_detach_pages(gt);
- }
- mutex_unlock(&dev_priv->gtt_mutex);
-}
-
-/*
- * GTT resource allocator - allocate and manage GTT address space
- */
-
-/**
- * psb_gtt_alloc_range - allocate GTT address space
- * @dev: Our DRM device
- * @len: length (bytes) of address space required
- * @name: resource name
- * @backed: resource should be backed by stolen pages
- *
- * Ask the kernel core to find us a suitable range of addresses
- * to use for a GTT mapping.
- *
- * Returns a gtt_range structure describing the object, or NULL on
- * error. On successful return the resource is both allocated and marked
- * as in use.
- */
-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name, int backed)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct gtt_range *gt;
- struct resource *r = dev_priv->gtt_mem;
- int ret;
- unsigned long start, end;
-
- if (backed) {
- /* The start of the GTT is the stolen pages */
- start = r->start;
- end = r->start + dev_priv->gtt.stolen_size - 1;
- } else {
- /* The rest we will use for GEM backed objects */
- start = r->start + dev_priv->gtt.stolen_size;
- end = r->end;
- }
-
- gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
- if (gt == NULL)
- return NULL;
- gt->resource.name = name;
- gt->stolen = backed;
- gt->in_gart = backed;
- gt->roll = 0;
- /* Ensure this is set for non GEM objects */
- gt->gem.dev = dev;
- ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
- len, start, end, PAGE_SIZE, NULL, NULL);
- if (ret == 0) {
- gt->offset = gt->resource.start - r->start;
- return gt;
- }
- kfree(gt);
- return NULL;
-}
-
-/**
- * psb_gtt_free_range - release GTT address space
- * @dev: our DRM device
- * @gt: a mapping created with psb_gtt_alloc_range
- *
- * Release a resource that was allocated with psb_gtt_alloc_range. If the
- * object has been pinned by mmap users we clean this up here currently.
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
-{
- /* Undo the mmap pin if we are destroying the object */
- if (gt->mmapping) {
- psb_gtt_unpin(gt);
- gt->mmapping = 0;
- }
- WARN_ON(gt->in_gart && !gt->stolen);
- release_resource(&gt->resource);
- kfree(gt);
-}
-
-void psb_gtt_alloc(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- init_rwsem(&dev_priv->gtt.sem);
-}
-
-void psb_gtt_takedown(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (dev_priv->gtt_map) {
- iounmap(dev_priv->gtt_map);
- dev_priv->gtt_map = NULL;
- }
- if (dev_priv->gtt_initialized) {
- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
- dev_priv->gmch_ctrl);
- PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
- }
- if (dev_priv->vram_addr)
- iounmap(dev_priv->gtt_map);
-}
-
-int psb_gtt_init(struct drm_device *dev, int resume)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned gtt_pages;
- unsigned long stolen_size, vram_stolen_size;
- unsigned i, num_pages;
- unsigned pfn_base;
- uint32_t vram_pages;
- uint32_t dvmt_mode = 0;
- struct psb_gtt *pg;
-
- int ret = 0;
- uint32_t pte;
-
- mutex_init(&dev_priv->gtt_mutex);
-
- psb_gtt_alloc(dev);
- pg = &dev_priv->gtt;
-
- /* Enable the GTT */
- pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
- dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
- dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
- PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
-
- /* The root resource we allocate address space from */
- dev_priv->gtt_initialized = 1;
-
- pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
-
- /*
- * The video mmu has a hw bug when accessing 0x0D0000000.
- * Make gatt start at 0x0e000,0000. This doesn't actually
- * matter for us but may do if the video acceleration ever
- * gets opened up.
- */
- pg->mmu_gatt_start = 0xE0000000;
-
- pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
- gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
- >> PAGE_SHIFT;
- /* Some CDV firmware doesn't report this currently. In which case the
- system has 64 gtt pages */
- if (pg->gtt_start == 0 || gtt_pages == 0) {
- dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
- gtt_pages = 64;
- pg->gtt_start = dev_priv->pge_ctl;
- }
-
- pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
- pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
- >> PAGE_SHIFT;
- dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-
- if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
- static struct resource fudge; /* Preferably peppermint */
- /* This can occur on CDV SDV systems. Fudge it in this case.
- We really don't care what imaginary space is being allocated
- at this point */
- dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
- pg->gatt_start = 0x40000000;
- pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
- /* This is a little confusing but in fact the GTT is providing
- a view from the GPU into memory and not vice versa. As such
- this is really allocating space that is not the same as the
- CPU address space on CDV */
- fudge.start = 0x40000000;
- fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
- fudge.name = "fudge";
- fudge.flags = IORESOURCE_MEM;
- dev_priv->gtt_mem = &fudge;
- }
-
- pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
- vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
- - PAGE_SIZE;
-
- stolen_size = vram_stolen_size;
-
- printk(KERN_INFO "Stolen memory information\n");
- printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base);
- printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
- vram_stolen_size/1024);
- dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
- printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n",
- (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
-
- if (resume && (gtt_pages != pg->gtt_pages) &&
- (stolen_size != pg->stolen_size)) {
- dev_err(dev->dev, "GTT resume error.\n");
- ret = -EINVAL;
- goto out_err;
- }
-
- pg->gtt_pages = gtt_pages;
- pg->stolen_size = stolen_size;
- dev_priv->vram_stolen_size = vram_stolen_size;
-
- /*
- * Map the GTT and the stolen memory area
- */
- dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
- gtt_pages << PAGE_SHIFT);
- if (!dev_priv->gtt_map) {
- dev_err(dev->dev, "Failure to map gtt.\n");
- ret = -ENOMEM;
- goto out_err;
- }
-
- dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
- if (!dev_priv->vram_addr) {
- dev_err(dev->dev, "Failure to map stolen base.\n");
- ret = -ENOMEM;
- goto out_err;
- }
-
- /*
- * Insert vram stolen pages into the GTT
- */
-
- pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
- vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
- printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
- num_pages, pfn_base << PAGE_SHIFT, 0);
- for (i = 0; i < num_pages; ++i) {
- pte = psb_gtt_mask_pte(pfn_base + i, 0);
- iowrite32(pte, dev_priv->gtt_map + i);
- }
-
- /*
- * Init rest of GTT to the scratch page to avoid accidents or scribbles
- */
-
- pfn_base = page_to_pfn(dev_priv->scratch_page);
- pte = psb_gtt_mask_pte(pfn_base, 0);
- for (; i < gtt_pages; ++i)
- iowrite32(pte, dev_priv->gtt_map + i);
-
- (void) ioread32(dev_priv->gtt_map + i - 1);
- return 0;
-
-out_err:
- psb_gtt_takedown(dev);
- return ret;
-}
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
deleted file mode 100644
index aa1742387f5a..000000000000
--- a/drivers/staging/gma500/gtt.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2008, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-#ifndef _PSB_GTT_H_
-#define _PSB_GTT_H_
-
-#include <drm/drmP.h>
-
-/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
-struct psb_gtt {
- uint32_t gatt_start;
- uint32_t mmu_gatt_start;
- uint32_t gtt_start;
- uint32_t gtt_phys_start;
- unsigned gtt_pages;
- unsigned gatt_pages;
- unsigned long stolen_size;
- unsigned long vram_stolen_size;
- struct rw_semaphore sem;
-};
-
-/* Exported functions */
-extern int psb_gtt_init(struct drm_device *dev, int resume);
-extern void psb_gtt_takedown(struct drm_device *dev);
-
-/* Each gtt_range describes an allocation in the GTT area */
-struct gtt_range {
- struct resource resource; /* Resource for our allocation */
- u32 offset; /* GTT offset of our object */
- struct drm_gem_object gem; /* GEM high level stuff */
- int in_gart; /* Currently in the GART (ref ct) */
- bool stolen; /* Backed from stolen RAM */
- bool mmapping; /* Is mmappable */
- struct page **pages; /* Backing pages if present */
- int npage; /* Number of backing pages */
- int roll; /* Roll applied to the GTT entries */
-};
-
-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name, int backed);
-extern void psb_gtt_kref_put(struct gtt_range *gt);
-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_pin(struct gtt_range *gt);
-extern void psb_gtt_unpin(struct gtt_range *gt);
-extern void psb_gtt_roll(struct drm_device *dev,
- struct gtt_range *gt, int roll);
-
-#endif
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
deleted file mode 100644
index 096757f9bc89..000000000000
--- a/drivers/staging/gma500/intel_bios.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-
-
-static void *find_section(struct bdb_header *bdb, int section_id)
-{
- u8 *base = (u8 *)bdb;
- int index = 0;
- u16 total, current_size;
- u8 current_id;
-
- /* skip to first section */
- index += bdb->header_size;
- total = bdb->bdb_size;
-
- /* walk the sections looking for section_id */
- while (index < total) {
- current_id = *(base + index);
- index++;
- current_size = *((u16 *)(base + index));
- index += 2;
- if (current_id == section_id)
- return base + index;
- index += current_size;
- }
-
- return NULL;
-}
-
-static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
- struct lvds_dvo_timing *dvo_timing)
-{
- panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
- dvo_timing->hactive_lo;
- panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
- ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
- panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
- dvo_timing->hsync_pulse_width;
- panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
- ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
-
- panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
- dvo_timing->vactive_lo;
- panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
- dvo_timing->vsync_off;
- panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
- dvo_timing->vsync_pulse_width;
- panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
- ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
- panel_fixed_mode->clock = dvo_timing->clock * 10;
- panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
-
- /* Some VBTs have bogus h/vtotal values */
- if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
- panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
- if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
- panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
-
- drm_mode_set_name(panel_fixed_mode);
-}
-
-static void parse_backlight_data(struct drm_psb_private *dev_priv,
- struct bdb_header *bdb)
-{
- struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
- struct bdb_lvds_backlight *lvds_bl;
- u8 p_type = 0;
- void *bl_start = NULL;
- struct bdb_lvds_options *lvds_opts
- = find_section(bdb, BDB_LVDS_OPTIONS);
-
- dev_priv->lvds_bl = NULL;
-
- if (lvds_opts)
- p_type = lvds_opts->panel_type;
- else
- return;
-
- bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
- vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
-
- lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
- if (!lvds_bl) {
- dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
- return;
- }
- memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
- dev_priv->lvds_bl = lvds_bl;
-}
-
-/* Try to find integrated panel data */
-static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
- struct bdb_header *bdb)
-{
- struct bdb_lvds_options *lvds_options;
- struct bdb_lvds_lfp_data *lvds_lfp_data;
- struct bdb_lvds_lfp_data_entry *entry;
- struct lvds_dvo_timing *dvo_timing;
- struct drm_display_mode *panel_fixed_mode;
-
- /* Defaults if we can't find VBT info */
- dev_priv->lvds_dither = 0;
- dev_priv->lvds_vbt = 0;
-
- lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
- if (!lvds_options)
- return;
-
- dev_priv->lvds_dither = lvds_options->pixel_dither;
- if (lvds_options->panel_type == 0xff)
- return;
-
- lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
- if (!lvds_lfp_data)
- return;
-
-
- entry = &lvds_lfp_data->data[lvds_options->panel_type];
- dvo_timing = &entry->dvo_timing;
-
- panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
- GFP_KERNEL);
- if (panel_fixed_mode == NULL) {
- dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n");
- return;
- }
-
- dev_priv->lvds_vbt = 1;
- fill_detail_timing_data(panel_fixed_mode, dvo_timing);
-
- if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
- dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
- drm_mode_debug_printmodeline(panel_fixed_mode);
- } else {
- dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
- dev_priv->lvds_vbt = 0;
- kfree(panel_fixed_mode);
- }
- return;
-}
-
-/* Try to find sdvo panel data */
-static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
- struct bdb_header *bdb)
-{
- struct bdb_sdvo_lvds_options *sdvo_lvds_options;
- struct lvds_dvo_timing *dvo_timing;
- struct drm_display_mode *panel_fixed_mode;
-
- dev_priv->sdvo_lvds_vbt_mode = NULL;
-
- sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
- if (!sdvo_lvds_options)
- return;
-
- dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
- if (!dvo_timing)
- return;
-
- panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
- if (!panel_fixed_mode)
- return;
-
- fill_detail_timing_data(panel_fixed_mode,
- dvo_timing + sdvo_lvds_options->panel_type);
-
- dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
-
- return;
-}
-
-static void parse_general_features(struct drm_psb_private *dev_priv,
- struct bdb_header *bdb)
-{
- struct bdb_general_features *general;
-
- /* Set sensible defaults in case we can't find the general block */
- dev_priv->int_tv_support = 1;
- dev_priv->int_crt_support = 1;
-
- general = find_section(bdb, BDB_GENERAL_FEATURES);
- if (general) {
- dev_priv->int_tv_support = general->int_tv_support;
- dev_priv->int_crt_support = general->int_crt_support;
- dev_priv->lvds_use_ssc = general->enable_ssc;
-
- if (dev_priv->lvds_use_ssc) {
- dev_priv->lvds_ssc_freq
- = general->ssc_freq ? 100 : 96;
- }
- }
-}
-
-/**
- * psb_intel_init_bios - initialize VBIOS settings & find VBT
- * @dev: DRM device
- *
- * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers
- * to appropriate values.
- *
- * VBT existence is a sanity check that is relied on by other i830_bios.c code.
- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
- * feed an updated VBT back through that, compared to what we'll fetch using
- * this method of groping around in the BIOS data.
- *
- * Returns 0 on success, nonzero on failure.
- */
-bool psb_intel_init_bios(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct pci_dev *pdev = dev->pdev;
- struct vbt_header *vbt = NULL;
- struct bdb_header *bdb;
- u8 __iomem *bios;
- size_t size;
- int i;
-
- bios = pci_map_rom(pdev, &size);
- if (!bios)
- return -1;
-
- /* Scour memory looking for the VBT signature */
- for (i = 0; i + 4 < size; i++) {
- if (!memcmp(bios + i, "$VBT", 4)) {
- vbt = (struct vbt_header *)(bios + i);
- break;
- }
- }
-
- if (!vbt) {
- dev_err(dev->dev, "VBT signature missing\n");
- pci_unmap_rom(pdev, bios);
- return -1;
- }
-
- bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
- /* Grab useful general definitions */
- parse_general_features(dev_priv, bdb);
- parse_lfp_panel_data(dev_priv, bdb);
- parse_sdvo_panel_data(dev_priv, bdb);
- parse_backlight_data(dev_priv, bdb);
-
- pci_unmap_rom(pdev, bios);
-
- return 0;
-}
-
-/**
- * Destroy and free VBT data
- */
-void psb_intel_destroy_bios(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_display_mode *sdvo_lvds_vbt_mode =
- dev_priv->sdvo_lvds_vbt_mode;
- struct drm_display_mode *lfp_lvds_vbt_mode =
- dev_priv->lfp_lvds_vbt_mode;
- struct bdb_lvds_backlight *lvds_bl =
- dev_priv->lvds_bl;
-
- /*free sdvo panel mode*/
- if (sdvo_lvds_vbt_mode) {
- dev_priv->sdvo_lvds_vbt_mode = NULL;
- kfree(sdvo_lvds_vbt_mode);
- }
-
- if (lfp_lvds_vbt_mode) {
- dev_priv->lfp_lvds_vbt_mode = NULL;
- kfree(lfp_lvds_vbt_mode);
- }
-
- if (lvds_bl) {
- dev_priv->lvds_bl = NULL;
- kfree(lvds_bl);
- }
-}
diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h
deleted file mode 100644
index 70f1bf018183..000000000000
--- a/drivers/staging/gma500/intel_bios.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _I830_BIOS_H_
-#define _I830_BIOS_H_
-
-#include <drm/drmP.h>
-
-struct vbt_header {
- u8 signature[20]; /**< Always starts with 'VBT$' */
- u16 version; /**< decimal */
- u16 header_size; /**< in bytes */
- u16 vbt_size; /**< in bytes */
- u8 vbt_checksum;
- u8 reserved0;
- u32 bdb_offset; /**< from beginning of VBT */
- u32 aim_offset[4]; /**< from beginning of VBT */
-} __attribute__((packed));
-
-
-struct bdb_header {
- u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
- u16 version; /**< decimal */
- u16 header_size; /**< in bytes */
- u16 bdb_size; /**< in bytes */
-};
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
- u8 type; /* 0 == desktop, 1 == mobile */
- u8 relstage;
- u8 chipset;
- u8 lvds_present:1;
- u8 tv_present:1;
- u8 rsvd2:6; /* finish byte */
- u8 rsvd3[4];
- u8 signon[155];
- u8 copyright[61];
- u16 code_segment;
- u8 dos_boot_mode;
- u8 bandwidth_percent;
- u8 rsvd4; /* popup memory size */
- u8 resize_pci_bios;
- u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
-
-/*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
- */
-#define BDB_GENERAL_FEATURES 1
-#define BDB_GENERAL_DEFINITIONS 2
-#define BDB_OLD_TOGGLE_LIST 3
-#define BDB_MODE_SUPPORT_LIST 4
-#define BDB_GENERIC_MODE_TABLE 5
-#define BDB_EXT_MMIO_REGS 6
-#define BDB_SWF_IO 7
-#define BDB_SWF_MMIO 8
-#define BDB_DOT_CLOCK_TABLE 9
-#define BDB_MODE_REMOVAL_TABLE 10
-#define BDB_CHILD_DEVICE_TABLE 11
-#define BDB_DRIVER_FEATURES 12
-#define BDB_DRIVER_PERSISTENCE 13
-#define BDB_EXT_TABLE_PTRS 14
-#define BDB_DOT_CLOCK_OVERRIDE 15
-#define BDB_DISPLAY_SELECT 16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION 18
-#define BDB_DISPLAY_REMOVE 19
-#define BDB_OEM_CUSTOM 20
-#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS 22
-#define BDB_SDVO_PANEL_DTDS 23
-#define BDB_SDVO_LVDS_PNP_IDS 24
-#define BDB_SDVO_LVDS_POWER_SEQ 25
-#define BDB_TV_OPTIONS 26
-#define BDB_LVDS_OPTIONS 40
-#define BDB_LVDS_LFP_DATA_PTRS 41
-#define BDB_LVDS_LFP_DATA 42
-#define BDB_LVDS_BACKLIGHT 43
-#define BDB_LVDS_POWER 44
-#define BDB_SKIP 254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
- /* bits 1 */
- u8 panel_fitting:2;
- u8 flexaim:1;
- u8 msg_enable:1;
- u8 clear_screen:3;
- u8 color_flip:1;
-
- /* bits 2 */
- u8 download_ext_vbt:1;
- u8 enable_ssc:1;
- u8 ssc_freq:1;
- u8 enable_lfp_on_override:1;
- u8 disable_ssc_ddt:1;
- u8 rsvd8:3; /* finish byte */
-
- /* bits 3 */
- u8 disable_smooth_vision:1;
- u8 single_dvi:1;
- u8 rsvd9:6; /* finish byte */
-
- /* bits 4 */
- u8 legacy_monitor_detect;
-
- /* bits 5 */
- u8 int_crt_support:1;
- u8 int_tv_support:1;
- u8 rsvd11:6; /* finish byte */
-} __attribute__((packed));
-
-struct bdb_general_definitions {
- /* DDC GPIO */
- u8 crt_ddc_gmbus_pin;
-
- /* DPMS bits */
- u8 dpms_acpi:1;
- u8 skip_boot_crt_detect:1;
- u8 dpms_aim:1;
- u8 rsvd1:5; /* finish byte */
-
- /* boot device bits */
- u8 boot_display[2];
- u8 child_dev_size;
-
- /* device info */
- u8 tv_or_lvds_info[33];
- u8 dev1[33];
- u8 dev2[33];
- u8 dev3[33];
- u8 dev4[33];
- /* may be another device block here on some platforms */
-};
-
-struct bdb_lvds_options {
- u8 panel_type;
- u8 rsvd1;
- /* LVDS capabilities, stored in a dword */
- u8 pfit_mode:2;
- u8 pfit_text_mode_enhanced:1;
- u8 pfit_gfx_mode_enhanced:1;
- u8 pfit_ratio_auto:1;
- u8 pixel_dither:1;
- u8 lvds_edid:1;
- u8 rsvd2:1;
- u8 rsvd4;
-} __attribute__((packed));
-
-struct bdb_lvds_backlight {
- u8 type:2;
- u8 pol:1;
- u8 gpio:3;
- u8 gmbus:2;
- u16 freq;
- u8 minbrightness;
- u8 i2caddr;
- u8 brightnesscmd;
- /*FIXME: more...*/
-} __attribute__((packed));
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
- u16 fp_timing_offset; /* offsets are from start of bdb */
- u8 fp_table_size;
- u16 dvo_timing_offset;
- u8 dvo_table_size;
- u16 panel_pnp_id_offset;
- u8 pnp_table_size;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_ptrs {
- u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
- struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
- u16 x_res;
- u16 y_res;
- u32 lvds_reg;
- u32 lvds_reg_val;
- u32 pp_on_reg;
- u32 pp_on_reg_val;
- u32 pp_off_reg;
- u32 pp_off_reg_val;
- u32 pp_cycle_reg;
- u32 pp_cycle_reg_val;
- u32 pfit_reg;
- u32 pfit_reg_val;
- u16 terminator;
-} __attribute__((packed));
-
-struct lvds_dvo_timing {
- u16 clock; /**< In 10khz */
- u8 hactive_lo;
- u8 hblank_lo;
- u8 hblank_hi:4;
- u8 hactive_hi:4;
- u8 vactive_lo;
- u8 vblank_lo;
- u8 vblank_hi:4;
- u8 vactive_hi:4;
- u8 hsync_off_lo;
- u8 hsync_pulse_width;
- u8 vsync_pulse_width:4;
- u8 vsync_off:4;
- u8 rsvd0:6;
- u8 hsync_off_hi:2;
- u8 h_image;
- u8 v_image;
- u8 max_hv;
- u8 h_border;
- u8 v_border;
- u8 rsvd1:3;
- u8 digital:2;
- u8 vsync_positive:1;
- u8 hsync_positive:1;
- u8 rsvd2:1;
-} __attribute__((packed));
-
-struct lvds_pnp_id {
- u16 mfg_name;
- u16 product_code;
- u32 serial;
- u8 mfg_week;
- u8 mfg_year;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_entry {
- struct lvds_fp_timing fp_timing;
- struct lvds_dvo_timing dvo_timing;
- struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data {
- struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
-
-struct aimdb_header {
- char signature[16];
- char oem_device[20];
- u16 aimdb_version;
- u16 aimdb_header_size;
- u16 aimdb_size;
-} __attribute__((packed));
-
-struct aimdb_block {
- u8 aimdb_id;
- u16 aimdb_size;
-} __attribute__((packed));
-
-struct vch_panel_data {
- u16 fp_timing_offset;
- u8 fp_timing_size;
- u16 dvo_timing_offset;
- u8 dvo_timing_size;
- u16 text_fitting_offset;
- u8 text_fitting_size;
- u16 graphics_fitting_offset;
- u8 graphics_fitting_size;
-} __attribute__((packed));
-
-struct vch_bdb_22 {
- struct aimdb_block aimdb_block;
- struct vch_panel_data panels[16];
-} __attribute__((packed));
-
-struct bdb_sdvo_lvds_options {
- u8 panel_backlight;
- u8 h40_set_panel_type;
- u8 panel_type;
- u8 ssc_clk_freq;
- u16 als_low_trip;
- u16 als_high_trip;
- u8 sclalarcoeff_tab_row_num;
- u8 sclalarcoeff_tab_row_size;
- u8 coefficient[8];
- u8 panel_misc_bits_1;
- u8 panel_misc_bits_2;
- u8 panel_misc_bits_3;
- u8 panel_misc_bits_4;
-} __attribute__((packed));
-
-
-extern bool psb_intel_init_bios(struct drm_device *dev);
-extern void psb_intel_destroy_bios(struct drm_device *dev);
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */
-#define GR18_HK_NONE (0x0<<3)
-#define GR18_HK_LFP_STRETCH (0x1<<3)
-#define GR18_HK_TOGGLE_DISP (0x2<<3)
-#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */
-#define GR18_HK_POPUP_DISABLED (0x6<<3)
-#define GR18_HK_POPUP_ENABLED (0x7<<3)
-#define GR18_HK_PFIT (0x8<<3)
-#define GR18_HK_APM_CHANGE (0xa<<3)
-#define GR18_HK_MULTIPLE (0xc<<3)
-#define GR18_USER_INT_EN (1<<2)
-#define GR18_A0000_FLUSH_EN (1<<1)
-#define GR18_SMM_EN (1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT 16
-#define SWF00_XRES_SHIFT 0
-#define SWF00_RES_MASK 0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT 8
-#define SWF01_TV1_FORMAT_SHIFT 0
-#define SWF01_TV_FORMAT_MASK 0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
-#define SWF10_GTT_OVERRIDE_EN (1<<28)
-#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define SWF10_OLD_TOGGLE 0x0
-#define SWF10_TOGGLE_LIST_1 0x1
-#define SWF10_TOGGLE_LIST_2 0x2
-#define SWF10_TOGGLE_LIST_3 0x3
-#define SWF10_TOGGLE_LIST_4 0x4
-#define SWF10_PANNING_EN (1<<23)
-#define SWF10_DRIVER_LOADED (1<<22)
-#define SWF10_EXTENDED_DESKTOP (1<<21)
-#define SWF10_EXCLUSIVE_MODE (1<<20)
-#define SWF10_OVERLAY_EN (1<<19)
-#define SWF10_PLANEB_HOLDOFF (1<<18)
-#define SWF10_PLANEA_HOLDOFF (1<<17)
-#define SWF10_VGA_HOLDOFF (1<<16)
-#define SWF10_ACTIVE_DISP_MASK 0xffff
-#define SWF10_PIPEB_LFP2 (1<<15)
-#define SWF10_PIPEB_EFP2 (1<<14)
-#define SWF10_PIPEB_TV2 (1<<13)
-#define SWF10_PIPEB_CRT2 (1<<12)
-#define SWF10_PIPEB_LFP (1<<11)
-#define SWF10_PIPEB_EFP (1<<10)
-#define SWF10_PIPEB_TV (1<<9)
-#define SWF10_PIPEB_CRT (1<<8)
-#define SWF10_PIPEA_LFP2 (1<<7)
-#define SWF10_PIPEA_EFP2 (1<<6)
-#define SWF10_PIPEA_TV2 (1<<5)
-#define SWF10_PIPEA_CRT2 (1<<4)
-#define SWF10_PIPEA_LFP (1<<3)
-#define SWF10_PIPEA_EFP (1<<2)
-#define SWF10_PIPEA_TV (1<<1)
-#define SWF10_PIPEA_CRT (1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT 16
-#define SWF11_SV_TEST_EN (1<<15)
-#define SWF11_IS_AGP (1<<14)
-#define SWF11_DISPLAY_HOLDOFF (1<<13)
-#define SWF11_DPMS_REDUCED (1<<12)
-#define SWF11_IS_VBE_MODE (1<<11)
-#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK 0x07
-#define SWF11_DPMS_OFF (1<<2)
-#define SWF11_DPMS_SUSPEND (1<<1)
-#define SWF11_DPMS_STANDBY (1<<0)
-#define SWF11_DPMS_ON 0
-
-#define SWF14_GFX_PFIT_EN (1<<31)
-#define SWF14_TEXT_PFIT_EN (1<<30)
-#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN (1<<28)
-#define SWF14_DISPLAY_HOLDOFF (1<<27)
-#define SWF14_DISP_DETECT_EN (1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS (1<<24)
-#define SWF14_OS_TYPE_WIN9X (1<<23)
-#define SWF14_OS_TYPE_WINNT (1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK 0x00070000
-#define SWF14_PM_ACPI_VIDEO (0x4 << 16)
-#define SWF14_PM_ACPI (0x3 << 16)
-#define SWF14_PM_APM_12 (0x2 << 16)
-#define SWF14_PM_APM_11 (0x1 << 16)
-#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */
- /* if GR18 indicates a display switch */
-#define SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define SWF14_DS_PIPEB_TV2_EN (1<<13)
-#define SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define SWF14_DS_PIPEB_LFP_EN (1<<11)
-#define SWF14_DS_PIPEB_EFP_EN (1<<10)
-#define SWF14_DS_PIPEB_TV_EN (1<<9)
-#define SWF14_DS_PIPEB_CRT_EN (1<<8)
-#define SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define SWF14_DS_PIPEA_TV2_EN (1<<5)
-#define SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define SWF14_DS_PIPEA_LFP_EN (1<<3)
-#define SWF14_DS_PIPEA_EFP_EN (1<<2)
-#define SWF14_DS_PIPEA_TV_EN (1<<1)
-#define SWF14_DS_PIPEA_CRT_EN (1<<0)
- /* if GR18 indicates a panel fitting request */
-#define SWF14_PFIT_EN (1<<0) /* 0 means disable */
- /* if GR18 indicates an APM change request */
-#define SWF14_APM_HIBERNATE 0x4
-#define SWF14_APM_SUSPEND 0x3
-#define SWF14_APM_STANDBY 0x1
-#define SWF14_APM_RESTORE 0x0
-
-#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c
deleted file mode 100644
index 51cbf65268e6..000000000000
--- a/drivers/staging/gma500/intel_i2c.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/export.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-
-/*
- * Intel GPIO access functions
- */
-
-#define I2C_RISEFALL_TIME 20
-
-static int get_clock(void *data)
-{
- struct psb_intel_i2c_chan *chan = data;
- struct drm_device *dev = chan->drm_dev;
- u32 val;
-
- val = REG_READ(chan->reg);
- return (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-static int get_data(void *data)
-{
- struct psb_intel_i2c_chan *chan = data;
- struct drm_device *dev = chan->drm_dev;
- u32 val;
-
- val = REG_READ(chan->reg);
- return (val & GPIO_DATA_VAL_IN) != 0;
-}
-
-static void set_clock(void *data, int state_high)
-{
- struct psb_intel_i2c_chan *chan = data;
- struct drm_device *dev = chan->drm_dev;
- u32 reserved = 0, clock_bits;
-
- /* On most chips, these bits must be preserved in software. */
- reserved =
- REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
- GPIO_CLOCK_PULLUP_DISABLE);
-
- if (state_high)
- clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
- else
- clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
- GPIO_CLOCK_VAL_MASK;
- REG_WRITE(chan->reg, reserved | clock_bits);
- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
-}
-
-static void set_data(void *data, int state_high)
-{
- struct psb_intel_i2c_chan *chan = data;
- struct drm_device *dev = chan->drm_dev;
- u32 reserved = 0, data_bits;
-
- /* On most chips, these bits must be preserved in software. */
- reserved =
- REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
- GPIO_CLOCK_PULLUP_DISABLE);
-
- if (state_high)
- data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
- else
- data_bits =
- GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
- GPIO_DATA_VAL_MASK;
-
- REG_WRITE(chan->reg, reserved | data_bits);
- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
-}
-
-/**
- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
- * @dev: DRM device
- * @output: driver specific output device
- * @reg: GPIO reg to use
- * @name: name for this bus
- *
- * Creates and registers a new i2c bus with the Linux i2c layer, for use
- * in output probing and control (e.g. DDC or SDVO control functions).
- *
- * Possible values for @reg include:
- * %GPIOA
- * %GPIOB
- * %GPIOC
- * %GPIOD
- * %GPIOE
- * %GPIOF
- * %GPIOG
- * %GPIOH
- * see PRM for details on how these different busses are used.
- */
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
- const u32 reg, const char *name)
-{
- struct psb_intel_i2c_chan *chan;
-
- chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
- if (!chan)
- goto out_free;
-
- chan->drm_dev = dev;
- chan->reg = reg;
- snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
- chan->adapter.owner = THIS_MODULE;
- chan->adapter.algo_data = &chan->algo;
- chan->adapter.dev.parent = &dev->pdev->dev;
- chan->algo.setsda = set_data;
- chan->algo.setscl = set_clock;
- chan->algo.getsda = get_data;
- chan->algo.getscl = get_clock;
- chan->algo.udelay = 20;
- chan->algo.timeout = usecs_to_jiffies(2200);
- chan->algo.data = chan;
-
- i2c_set_adapdata(&chan->adapter, chan);
-
- if (i2c_bit_add_bus(&chan->adapter))
- goto out_free;
-
- /* JJJ: raise SCL and SDA? */
- set_data(chan, 1);
- set_clock(chan, 1);
- udelay(20);
-
- return chan;
-
-out_free:
- kfree(chan);
- return NULL;
-}
-
-/**
- * psb_intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
- *
- * Unregister the adapter from the i2c layer, then free the structure.
- */
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
-{
- if (!chan)
- return;
-
- i2c_del_adapter(&chan->adapter);
- kfree(chan);
-}
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
deleted file mode 100644
index d946bc1b17bf..000000000000
--- a/drivers/staging/gma500/intel_opregion.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * FIXME: resolve with the i915 version
- */
-
-#include "psb_drv.h"
-
-struct opregion_header {
- u8 signature[16];
- u32 size;
- u32 opregion_ver;
- u8 bios_ver[32];
- u8 vbios_ver[16];
- u8 driver_ver[16];
- u32 mboxes;
- u8 reserved[164];
-} __packed;
-
-struct opregion_apci {
- /*FIXME: add it later*/
-} __packed;
-
-struct opregion_swsci {
- /*FIXME: add it later*/
-} __packed;
-
-struct opregion_acpi {
- /*FIXME: add it later*/
-} __packed;
-
-int gma_intel_opregion_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 opregion_phy;
- void *base;
- u32 *lid_state;
-
- dev_priv->lid_state = NULL;
-
- pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
- if (opregion_phy == 0)
- return -ENOTSUPP;
-
- base = ioremap(opregion_phy, 8*1024);
- if (!base)
- return -ENOMEM;
-
- lid_state = base + 0x01ac;
-
- dev_priv->lid_state = lid_state;
- dev_priv->lid_last_state = readl(lid_state);
- return 0;
-}
-
-int gma_intel_opregion_exit(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->lid_state)
- iounmap(dev_priv->lid_state);
- return 0;
-}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
deleted file mode 100644
index f47aeb7a2039..000000000000
--- a/drivers/staging/gma500/mdfld_device.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_output.h"
-#include "mid_bios.h"
-
-/*
- * Provide the Medfield specific backlight management
- */
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-static int mdfld_brightness;
-struct backlight_device *mdfld_backlight_device;
-
-static int mfld_set_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(mdfld_backlight_device);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int level = bd->props.brightness;
-
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
- if (gma_power_begin(dev, 0)) {
- /* Calculate and set the brightness value */
- u32 adjusted_level;
-
- /* Adjust the backlight level with the percent in
- * dev_priv->blc_adj2;
- */
- adjusted_level = level * dev_priv->blc_adj2;
- adjusted_level = adjusted_level / 100;
-#if 0
-#ifndef CONFIG_MDFLD_DSI_DPU
- if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) &&
- (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
- mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
- dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
- }
-#endif
- mdfld_dsi_brightness_control(dev, 0, adjusted_level);
-
- if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
- mdfld_dsi_brightness_control(dev, 2, adjusted_level);
-#endif
- gma_power_end(dev);
- }
- mdfld_brightness = level;
- return 0;
-}
-
-int psb_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return mdfld_brightness;
-}
-
-static const struct backlight_ops mfld_ops = {
- .get_brightness = psb_get_brightness,
- .update_status = mfld_set_brightness,
-};
-
-static int mdfld_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct backlight_properties props;
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- mdfld_backlight_device = backlight_device_register("mfld-bl",
- NULL, (void *)dev, &mfld_ops, &props);
-
- if (IS_ERR(mdfld_backlight_device))
- return PTR_ERR(mdfld_backlight_device);
-
- dev_priv->blc_adj1 = 100;
- dev_priv->blc_adj2 = 100;
- mdfld_backlight_device->props.brightness = 100;
- mdfld_backlight_device->props.max_brightness = 100;
- backlight_update_status(mdfld_backlight_device);
- dev_priv->backlight_device = mdfld_backlight_device;
- return 0;
-}
-
-#endif
-
-/*
- * Provide the Medfield specific chip logic and low level methods for
- * power management.
- */
-
-static void mdfld_init_pm(struct drm_device *dev)
-{
- /* No work needed here yet */
-}
-
-/**
- * mdfld_save_display_registers - save registers for pipe
- * @dev: our device
- * @pipe: pipe to save
- *
- * Save the pipe state of the device before we power it off. Keep everything
- * we need to put it back again
- */
-static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int i;
-
- /* register */
- u32 dpll_reg = MRST_DPLL_A;
- u32 fp_reg = MRST_FPA0;
- u32 pipeconf_reg = PIPEACONF;
- u32 htot_reg = HTOTAL_A;
- u32 hblank_reg = HBLANK_A;
- u32 hsync_reg = HSYNC_A;
- u32 vtot_reg = VTOTAL_A;
- u32 vblank_reg = VBLANK_A;
- u32 vsync_reg = VSYNC_A;
- u32 pipesrc_reg = PIPEASRC;
- u32 dspstride_reg = DSPASTRIDE;
- u32 dsplinoff_reg = DSPALINOFF;
- u32 dsptileoff_reg = DSPATILEOFF;
- u32 dspsize_reg = DSPASIZE;
- u32 dsppos_reg = DSPAPOS;
- u32 dspsurf_reg = DSPASURF;
- u32 mipi_reg = MIPI;
- u32 dspcntr_reg = DSPACNTR;
- u32 dspstatus_reg = PIPEASTAT;
- u32 palette_reg = PALETTE_A;
-
- /* pointer to values */
- u32 *dpll_val = &dev_priv->saveDPLL_A;
- u32 *fp_val = &dev_priv->saveFPA0;
- u32 *pipeconf_val = &dev_priv->savePIPEACONF;
- u32 *htot_val = &dev_priv->saveHTOTAL_A;
- u32 *hblank_val = &dev_priv->saveHBLANK_A;
- u32 *hsync_val = &dev_priv->saveHSYNC_A;
- u32 *vtot_val = &dev_priv->saveVTOTAL_A;
- u32 *vblank_val = &dev_priv->saveVBLANK_A;
- u32 *vsync_val = &dev_priv->saveVSYNC_A;
- u32 *pipesrc_val = &dev_priv->savePIPEASRC;
- u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
- u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
- u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
- u32 *dspsize_val = &dev_priv->saveDSPASIZE;
- u32 *dsppos_val = &dev_priv->saveDSPAPOS;
- u32 *dspsurf_val = &dev_priv->saveDSPASURF;
- u32 *mipi_val = &dev_priv->saveMIPI;
- u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
- u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
- u32 *palette_val = dev_priv->save_palette_a;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- /* register */
- dpll_reg = MDFLD_DPLL_B;
- fp_reg = MDFLD_DPLL_DIV0;
- pipeconf_reg = PIPEBCONF;
- htot_reg = HTOTAL_B;
- hblank_reg = HBLANK_B;
- hsync_reg = HSYNC_B;
- vtot_reg = VTOTAL_B;
- vblank_reg = VBLANK_B;
- vsync_reg = VSYNC_B;
- pipesrc_reg = PIPEBSRC;
- dspstride_reg = DSPBSTRIDE;
- dsplinoff_reg = DSPBLINOFF;
- dsptileoff_reg = DSPBTILEOFF;
- dspsize_reg = DSPBSIZE;
- dsppos_reg = DSPBPOS;
- dspsurf_reg = DSPBSURF;
- dspcntr_reg = DSPBCNTR;
- dspstatus_reg = PIPEBSTAT;
- palette_reg = PALETTE_B;
-
- /* values */
- dpll_val = &dev_priv->saveDPLL_B;
- fp_val = &dev_priv->saveFPB0;
- pipeconf_val = &dev_priv->savePIPEBCONF;
- htot_val = &dev_priv->saveHTOTAL_B;
- hblank_val = &dev_priv->saveHBLANK_B;
- hsync_val = &dev_priv->saveHSYNC_B;
- vtot_val = &dev_priv->saveVTOTAL_B;
- vblank_val = &dev_priv->saveVBLANK_B;
- vsync_val = &dev_priv->saveVSYNC_B;
- pipesrc_val = &dev_priv->savePIPEBSRC;
- dspstride_val = &dev_priv->saveDSPBSTRIDE;
- dsplinoff_val = &dev_priv->saveDSPBLINOFF;
- dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
- dspsize_val = &dev_priv->saveDSPBSIZE;
- dsppos_val = &dev_priv->saveDSPBPOS;
- dspsurf_val = &dev_priv->saveDSPBSURF;
- dspcntr_val = &dev_priv->saveDSPBCNTR;
- dspstatus_val = &dev_priv->saveDSPBSTATUS;
- palette_val = dev_priv->save_palette_b;
- break;
- case 2:
- /* register */
- pipeconf_reg = PIPECCONF;
- htot_reg = HTOTAL_C;
- hblank_reg = HBLANK_C;
- hsync_reg = HSYNC_C;
- vtot_reg = VTOTAL_C;
- vblank_reg = VBLANK_C;
- vsync_reg = VSYNC_C;
- pipesrc_reg = PIPECSRC;
- dspstride_reg = DSPCSTRIDE;
- dsplinoff_reg = DSPCLINOFF;
- dsptileoff_reg = DSPCTILEOFF;
- dspsize_reg = DSPCSIZE;
- dsppos_reg = DSPCPOS;
- dspsurf_reg = DSPCSURF;
- mipi_reg = MIPI_C;
- dspcntr_reg = DSPCCNTR;
- dspstatus_reg = PIPECSTAT;
- palette_reg = PALETTE_C;
-
- /* pointer to values */
- pipeconf_val = &dev_priv->savePIPECCONF;
- htot_val = &dev_priv->saveHTOTAL_C;
- hblank_val = &dev_priv->saveHBLANK_C;
- hsync_val = &dev_priv->saveHSYNC_C;
- vtot_val = &dev_priv->saveVTOTAL_C;
- vblank_val = &dev_priv->saveVBLANK_C;
- vsync_val = &dev_priv->saveVSYNC_C;
- pipesrc_val = &dev_priv->savePIPECSRC;
- dspstride_val = &dev_priv->saveDSPCSTRIDE;
- dsplinoff_val = &dev_priv->saveDSPCLINOFF;
- dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
- dspsize_val = &dev_priv->saveDSPCSIZE;
- dsppos_val = &dev_priv->saveDSPCPOS;
- dspsurf_val = &dev_priv->saveDSPCSURF;
- mipi_val = &dev_priv->saveMIPI_C;
- dspcntr_val = &dev_priv->saveDSPCCNTR;
- dspstatus_val = &dev_priv->saveDSPCSTATUS;
- palette_val = dev_priv->save_palette_c;
- break;
- default:
- DRM_ERROR("%s, invalid pipe number.\n", __func__);
- return -EINVAL;
- }
-
- /* Pipe & plane A info */
- *dpll_val = PSB_RVDC32(dpll_reg);
- *fp_val = PSB_RVDC32(fp_reg);
- *pipeconf_val = PSB_RVDC32(pipeconf_reg);
- *htot_val = PSB_RVDC32(htot_reg);
- *hblank_val = PSB_RVDC32(hblank_reg);
- *hsync_val = PSB_RVDC32(hsync_reg);
- *vtot_val = PSB_RVDC32(vtot_reg);
- *vblank_val = PSB_RVDC32(vblank_reg);
- *vsync_val = PSB_RVDC32(vsync_reg);
- *pipesrc_val = PSB_RVDC32(pipesrc_reg);
- *dspstride_val = PSB_RVDC32(dspstride_reg);
- *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
- *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
- *dspsize_val = PSB_RVDC32(dspsize_reg);
- *dsppos_val = PSB_RVDC32(dsppos_reg);
- *dspsurf_val = PSB_RVDC32(dspsurf_reg);
- *dspcntr_val = PSB_RVDC32(dspcntr_reg);
- *dspstatus_val = PSB_RVDC32(dspstatus_reg);
-
- /*save palette (gamma) */
- for (i = 0; i < 256; i++)
- palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
-
- if (pipe == 1) {
- dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
- dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
- dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
- dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
- return 0;
- }
- *mipi_val = PSB_RVDC32(mipi_reg);
- return 0;
-}
-
-/**
- * mdfld_save_cursor_overlay_registers - save cursor overlay info
- * @dev: our device
- *
- * Save the cursor and overlay register state
- */
-static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /* Save cursor regs */
- dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
- dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
- dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
-
- dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
- dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
- dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
-
- dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
- dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
- dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
-
- /* HW overlay */
- dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
- dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
- dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
- dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
- dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
- dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
- dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-
- dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
- dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
-
- return 0;
-}
-/*
- * mdfld_restore_display_registers - restore the state of a pipe
- * @dev: our device
- * @pipe: the pipe to restore
- *
- * Restore the state of a pipe to that which was saved by the register save
- * functions.
- */
-static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
-{
- /* To get panel out of ULPS mode */
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dsi_config *dsi_config = NULL;
- u32 i = 0;
- u32 dpll = 0;
- u32 timeout = 0;
- u32 reg_offset = 0;
-
- /* register */
- u32 dpll_reg = MRST_DPLL_A;
- u32 fp_reg = MRST_FPA0;
- u32 pipeconf_reg = PIPEACONF;
- u32 htot_reg = HTOTAL_A;
- u32 hblank_reg = HBLANK_A;
- u32 hsync_reg = HSYNC_A;
- u32 vtot_reg = VTOTAL_A;
- u32 vblank_reg = VBLANK_A;
- u32 vsync_reg = VSYNC_A;
- u32 pipesrc_reg = PIPEASRC;
- u32 dspstride_reg = DSPASTRIDE;
- u32 dsplinoff_reg = DSPALINOFF;
- u32 dsptileoff_reg = DSPATILEOFF;
- u32 dspsize_reg = DSPASIZE;
- u32 dsppos_reg = DSPAPOS;
- u32 dspsurf_reg = DSPASURF;
- u32 dspstatus_reg = PIPEASTAT;
- u32 mipi_reg = MIPI;
- u32 dspcntr_reg = DSPACNTR;
- u32 palette_reg = PALETTE_A;
-
- /* values */
- u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
- u32 fp_val = dev_priv->saveFPA0;
- u32 pipeconf_val = dev_priv->savePIPEACONF;
- u32 htot_val = dev_priv->saveHTOTAL_A;
- u32 hblank_val = dev_priv->saveHBLANK_A;
- u32 hsync_val = dev_priv->saveHSYNC_A;
- u32 vtot_val = dev_priv->saveVTOTAL_A;
- u32 vblank_val = dev_priv->saveVBLANK_A;
- u32 vsync_val = dev_priv->saveVSYNC_A;
- u32 pipesrc_val = dev_priv->savePIPEASRC;
- u32 dspstride_val = dev_priv->saveDSPASTRIDE;
- u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
- u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
- u32 dspsize_val = dev_priv->saveDSPASIZE;
- u32 dsppos_val = dev_priv->saveDSPAPOS;
- u32 dspsurf_val = dev_priv->saveDSPASURF;
- u32 dspstatus_val = dev_priv->saveDSPASTATUS;
- u32 mipi_val = dev_priv->saveMIPI;
- u32 dspcntr_val = dev_priv->saveDSPACNTR;
- u32 *palette_val = dev_priv->save_palette_a;
-
- switch (pipe) {
- case 0:
- dsi_config = dev_priv->dsi_configs[0];
- break;
- case 1:
- /* register */
- dpll_reg = MDFLD_DPLL_B;
- fp_reg = MDFLD_DPLL_DIV0;
- pipeconf_reg = PIPEBCONF;
- htot_reg = HTOTAL_B;
- hblank_reg = HBLANK_B;
- hsync_reg = HSYNC_B;
- vtot_reg = VTOTAL_B;
- vblank_reg = VBLANK_B;
- vsync_reg = VSYNC_B;
- pipesrc_reg = PIPEBSRC;
- dspstride_reg = DSPBSTRIDE;
- dsplinoff_reg = DSPBLINOFF;
- dsptileoff_reg = DSPBTILEOFF;
- dspsize_reg = DSPBSIZE;
- dsppos_reg = DSPBPOS;
- dspsurf_reg = DSPBSURF;
- dspcntr_reg = DSPBCNTR;
- palette_reg = PALETTE_B;
- dspstatus_reg = PIPEBSTAT;
-
- /* values */
- dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
- fp_val = dev_priv->saveFPB0;
- pipeconf_val = dev_priv->savePIPEBCONF;
- htot_val = dev_priv->saveHTOTAL_B;
- hblank_val = dev_priv->saveHBLANK_B;
- hsync_val = dev_priv->saveHSYNC_B;
- vtot_val = dev_priv->saveVTOTAL_B;
- vblank_val = dev_priv->saveVBLANK_B;
- vsync_val = dev_priv->saveVSYNC_B;
- pipesrc_val = dev_priv->savePIPEBSRC;
- dspstride_val = dev_priv->saveDSPBSTRIDE;
- dsplinoff_val = dev_priv->saveDSPBLINOFF;
- dsptileoff_val = dev_priv->saveDSPBTILEOFF;
- dspsize_val = dev_priv->saveDSPBSIZE;
- dsppos_val = dev_priv->saveDSPBPOS;
- dspsurf_val = dev_priv->saveDSPBSURF;
- dspcntr_val = dev_priv->saveDSPBCNTR;
- dspstatus_val = dev_priv->saveDSPBSTATUS;
- palette_val = dev_priv->save_palette_b;
- break;
- case 2:
- reg_offset = MIPIC_REG_OFFSET;
-
- /* register */
- pipeconf_reg = PIPECCONF;
- htot_reg = HTOTAL_C;
- hblank_reg = HBLANK_C;
- hsync_reg = HSYNC_C;
- vtot_reg = VTOTAL_C;
- vblank_reg = VBLANK_C;
- vsync_reg = VSYNC_C;
- pipesrc_reg = PIPECSRC;
- dspstride_reg = DSPCSTRIDE;
- dsplinoff_reg = DSPCLINOFF;
- dsptileoff_reg = DSPCTILEOFF;
- dspsize_reg = DSPCSIZE;
- dsppos_reg = DSPCPOS;
- dspsurf_reg = DSPCSURF;
- mipi_reg = MIPI_C;
- dspcntr_reg = DSPCCNTR;
- palette_reg = PALETTE_C;
- dspstatus_reg = PIPECSTAT;
-
- /* values */
- pipeconf_val = dev_priv->savePIPECCONF;
- htot_val = dev_priv->saveHTOTAL_C;
- hblank_val = dev_priv->saveHBLANK_C;
- hsync_val = dev_priv->saveHSYNC_C;
- vtot_val = dev_priv->saveVTOTAL_C;
- vblank_val = dev_priv->saveVBLANK_C;
- vsync_val = dev_priv->saveVSYNC_C;
- pipesrc_val = dev_priv->savePIPECSRC;
- dspstride_val = dev_priv->saveDSPCSTRIDE;
- dsplinoff_val = dev_priv->saveDSPCLINOFF;
- dsptileoff_val = dev_priv->saveDSPCTILEOFF;
- dspsize_val = dev_priv->saveDSPCSIZE;
- dsppos_val = dev_priv->saveDSPCPOS;
- dspsurf_val = dev_priv->saveDSPCSURF;
- dspstatus_val = dev_priv->saveDSPCSTATUS;
- mipi_val = dev_priv->saveMIPI_C;
- dspcntr_val = dev_priv->saveDSPCCNTR;
- palette_val = dev_priv->save_palette_c;
-
- dsi_config = dev_priv->dsi_configs[1];
- break;
- default:
- DRM_ERROR("%s, invalid pipe number.\n", __func__);
- return -EINVAL;
- }
-
- /* Make sure VGA plane is off. it initializes to on after reset!*/
- PSB_WVDC32(0x80000000, VGACNTRL);
- if (pipe == 1) {
- PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
- PSB_RVDC32(dpll_reg);
-
- PSB_WVDC32(fp_val, fp_reg);
- } else {
- dpll = PSB_RVDC32(dpll_reg);
-
- if (!(dpll & DPLL_VCO_ENABLE)) {
-
- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
- if (dpll & MDFLD_PWR_GATE_EN) {
- dpll &= ~MDFLD_PWR_GATE_EN;
- PSB_WVDC32(dpll, dpll_reg);
- udelay(500); /* FIXME: 1 ? */
- }
-
- PSB_WVDC32(fp_val, fp_reg);
- PSB_WVDC32(dpll_val, dpll_reg);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- dpll_val |= DPLL_VCO_ENABLE;
- PSB_WVDC32(dpll_val, dpll_reg);
- PSB_RVDC32(dpll_reg);
-
- /* wait for DSI PLL to lock */
- while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout++;
- }
-
- if (timeout == 20000) {
- DRM_ERROR("%s, can't lock DSIPLL.\n",
- __func__);
- return -EINVAL;
- }
- }
- }
- /* Restore mode */
- PSB_WVDC32(htot_val, htot_reg);
- PSB_WVDC32(hblank_val, hblank_reg);
- PSB_WVDC32(hsync_val, hsync_reg);
- PSB_WVDC32(vtot_val, vtot_reg);
- PSB_WVDC32(vblank_val, vblank_reg);
- PSB_WVDC32(vsync_val, vsync_reg);
- PSB_WVDC32(pipesrc_val, pipesrc_reg);
- PSB_WVDC32(dspstatus_val, dspstatus_reg);
-
- /* Set up the plane */
- PSB_WVDC32(dspstride_val, dspstride_reg);
- PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
- PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
- PSB_WVDC32(dspsize_val, dspsize_reg);
- PSB_WVDC32(dsppos_val, dsppos_reg);
- PSB_WVDC32(dspsurf_val, dspsurf_reg);
-
- if (pipe == 1) {
- PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
- PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
- PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
- PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
-
- } else {
- /* Set up pipe related registers */
- PSB_WVDC32(mipi_val, mipi_reg);
- /* Setup MIPI adapter + MIPI IP registers */
- mdfld_dsi_controller_init(dsi_config, pipe);
- msleep(20);
- }
- /* Enable the plane */
- PSB_WVDC32(dspcntr_val, dspcntr_reg);
- msleep(20);
- /* Enable the pipe */
- PSB_WVDC32(pipeconf_val, pipeconf_reg);
-
- for (i = 0; i < 256; i++)
- PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
- if (pipe == 1)
- return 0;
- if (!mdfld_panel_dpi(dev))
- mdfld_enable_te(dev, pipe);
- return 0;
-}
-
-/**
- * mdfld_restore_cursor_overlay_registers - restore cursor
- * @dev: our device
- *
- * Restore the cursor and overlay state that was saved earlier
- */
-static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /* Enable Cursor A */
- PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
- PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
- PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
-
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
-
- PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
- PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
- PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
-
- /* Restore HW overlay */
- PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
- PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
- PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
- PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
- PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
- PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
- PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
-
- PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
- PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
-
- return 0;
-}
-
-/**
- * mdfld_save_display_registers - save registers lost on suspend
- * @dev: our DRM device
- *
- * Save the state we need in order to be able to restore the interface
- * upon resume from suspend
- */
-static int mdfld_save_registers(struct drm_device *dev)
-{
- /* FIXME: We need to shut down panels here if using them
- and once the right bits are merged */
- mdfld_save_cursor_overlay_registers(dev);
- mdfld_save_display_registers(dev, 0);
- mdfld_save_display_registers(dev, 0);
- mdfld_save_display_registers(dev, 2);
- mdfld_save_display_registers(dev, 1);
- mdfld_disable_crtc(dev, 0);
- mdfld_disable_crtc(dev, 2);
- mdfld_disable_crtc(dev, 1);
- return 0;
-}
-
-/**
- * mdfld_restore_display_registers - restore lost register state
- * @dev: our DRM device
- *
- * Restore register state that was lost during suspend and resume.
- */
-static int mdfld_restore_registers(struct drm_device *dev)
-{
- mdfld_restore_display_registers(dev, 1);
- mdfld_restore_display_registers(dev, 0);
- mdfld_restore_display_registers(dev, 2);
- mdfld_restore_cursor_overlay_registers(dev);
- return 0;
-}
-
-static int mdfld_power_down(struct drm_device *dev)
-{
- /* FIXME */
- return 0;
-}
-
-static int mdfld_power_up(struct drm_device *dev)
-{
- /* FIXME */
- return 0;
-}
-
-const struct psb_ops mdfld_chip_ops = {
- .name = "Medfield",
- .accel_2d = 0,
- .pipes = 3,
- .crtcs = 2,
- .sgx_offset = MRST_SGX_OFFSET,
-
- .chip_setup = mid_chip_setup,
-
- .crtc_helper = &mdfld_helper_funcs,
- .crtc_funcs = &mdfld_intel_crtc_funcs,
-
- .output_init = mdfld_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = mdfld_backlight_init,
-#endif
-
- .init_pm = mdfld_init_pm,
- .save_regs = mdfld_save_registers,
- .restore_regs = mdfld_restore_registers,
- .power_down = mdfld_power_down,
- .power_up = mdfld_power_up,
-};
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
deleted file mode 100644
index fd211f3467c4..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dbi.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-int enable_gfx_rtpm;
-
-extern struct drm_device *gpDrmDevice;
-extern int gfxrtdelay;
-int enter_dsr;
-struct mdfld_dsi_dbi_output *gdbi_output;
-extern bool gbgfxsuspended;
-extern int enable_gfx_rtpm;
-extern int gfxrtdelay;
-
-#define MDFLD_DSR_MAX_IDLE_COUNT 2
-
-/*
- * set refreshing area
- */
-int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
- u16 x1, u16 y1, u16 x2, u16 y2)
-{
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
- u8 param[4];
- u8 cmd;
- int err;
-
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- /* Set column */
- cmd = DCS_SET_COLUMN_ADDRESS;
- param[0] = x1 >> 8;
- param[1] = x1;
- param[2] = x2 >> 8;
- param[3] = x2;
-
- err = mdfld_dsi_send_dcs(sender,
- cmd,
- param,
- 4,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
- goto err_out;
- }
-
- /* Set page */
- cmd = DCS_SET_PAGE_ADDRESS;
- param[0] = y1 >> 8;
- param[1] = y1;
- param[2] = y2 >> 8;
- param[3] = y2;
-
- err = mdfld_dsi_send_dcs(sender,
- cmd,
- param,
- 4,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
- goto err_out;
- }
-
- /*update screen*/
- err = mdfld_dsi_send_dcs(sender,
- write_mem_start,
- NULL,
- 0,
- CMD_DATA_SRC_PIPE,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
- goto err_out;
- }
- mdfld_dsi_cmds_kick_out(sender);
-err_out:
- return err;
-}
-
-/*
- * set panel's power state
- */
-int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
- int mode)
-{
- struct drm_device *dev = dbi_output->dev;
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
- u8 param = 0;
- u32 err = 0;
-
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- if (mode == DRM_MODE_DPMS_ON) {
- /* Exit sleep mode */
- err = mdfld_dsi_send_dcs(sender,
- DCS_EXIT_SLEEP_MODE,
- NULL,
- 0,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_EXIT_SLEEP_MODE);
- goto power_err;
- }
-
- /* Set display on */
- err = mdfld_dsi_send_dcs(sender,
- DCS_SET_DISPLAY_ON,
- NULL,
- 0,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_SET_DISPLAY_ON);
- goto power_err;
- }
-
- /* set tear effect on */
- err = mdfld_dsi_send_dcs(sender,
- DCS_SET_TEAR_ON,
- &param,
- 1,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- set_tear_on);
- goto power_err;
- }
-
- /**
- * FIXME: remove this later
- */
- err = mdfld_dsi_send_dcs(sender,
- DCS_WRITE_MEM_START,
- NULL,
- 0,
- CMD_DATA_SRC_PIPE,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_WRITE_MEM_START);
- goto power_err;
- }
- } else {
- /* Set tear effect off */
- err = mdfld_dsi_send_dcs(sender,
- DCS_SET_TEAR_OFF,
- NULL,
- 0,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_SET_TEAR_OFF);
- goto power_err;
- }
-
- /* Turn display off */
- err = mdfld_dsi_send_dcs(sender,
- DCS_SET_DISPLAY_OFF,
- NULL,
- 0,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_SET_DISPLAY_OFF);
- goto power_err;
- }
-
- /* Now enter sleep mode */
- err = mdfld_dsi_send_dcs(sender,
- DCS_ENTER_SLEEP_MODE,
- NULL,
- 0,
- CMD_DATA_SRC_SYSTEM_MEM,
- MDFLD_DSI_QUEUE_PACKAGE);
- if (err) {
- dev_err(dev->dev, "DCS 0x%x sent failed\n",
- DCS_ENTER_SLEEP_MODE);
- goto power_err;
- }
- }
- mdfld_dsi_cmds_kick_out(sender);
-power_err:
- return err;
-}
-
-/*
- * send a generic DCS command with a parameter list
- */
-int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
- u8 dcs, u8 *param, u32 num, u8 data_src)
-{
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
- int ret;
-
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- ret = mdfld_dsi_send_dcs(sender,
- dcs,
- param,
- num,
- data_src,
- MDFLD_DSI_SEND_PACKAGE);
-
- return ret;
-}
-
-/*
- * Enter DSR
- */
-void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
-{
- u32 reg_val;
- struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc = dbi_output->base.base.crtc;
- struct psb_intel_crtc *psb_crtc = (crtc) ?
- to_psb_intel_crtc(crtc) : NULL;
- u32 dpll_reg = MRST_DPLL_A;
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
-
- if (!dbi_output)
- return;
-
- /* FIXME check if can go */
- dev_priv->is_in_idle = true;
-
- gdbi_output = dbi_output;
- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
- return;
-
- if (pipe == 2) {
- dpll_reg = MRST_DPLL_A;
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
- /* Disable te interrupts */
- mdfld_disable_te(dev, pipe);
-
- /* Disable plane */
- reg_val = REG_READ(dspcntr_reg);
- if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
- REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
- REG_READ(dspcntr_reg);
- }
-
- /* Disable pipe */
- reg_val = REG_READ(pipeconf_reg);
- if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
- reg_val &= ~DISPLAY_PLANE_ENABLE;
- reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
- REG_WRITE(pipeconf_reg, reg_val);
- REG_READ(pipeconf_reg);
- mdfldWaitForPipeDisable(dev, pipe);
- }
-
- /* Disable DPLL */
- reg_val = REG_READ(dpll_reg);
- if (!(reg_val & DPLL_VCO_ENABLE)) {
- reg_val &= ~DPLL_VCO_ENABLE;
- REG_WRITE(dpll_reg, reg_val);
- REG_READ(dpll_reg);
- udelay(500);
- }
-
- gma_power_end(dev);
- dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
- if (pipe == 2) {
- enter_dsr = 1;
- /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
- }
-}
-
-static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe)
-{
- struct drm_device *dev = dbi_output->dev;
- struct drm_crtc *crtc = dbi_output->base.base.crtc;
- struct psb_intel_crtc *psb_crtc = (crtc) ?
- to_psb_intel_crtc(crtc) : NULL;
- u32 reg_val;
- u32 dpll_reg = MRST_DPLL_A;
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
- u32 reg_offset = 0;
-
- /*if mode setting on-going, back off*/
- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
- return;
-
- if (pipe == 2) {
- dpll_reg = MRST_DPLL_A;
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- reg_offset = MIPIC_REG_OFFSET;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- /* Enable DPLL */
- reg_val = REG_READ(dpll_reg);
- if (!(reg_val & DPLL_VCO_ENABLE)) {
- if (reg_val & MDFLD_PWR_GATE_EN) {
- reg_val &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(dpll_reg, reg_val);
- REG_READ(dpll_reg);
- udelay(500);
- }
-
- reg_val |= DPLL_VCO_ENABLE;
- REG_WRITE(dpll_reg, reg_val);
- REG_READ(dpll_reg);
- udelay(500);
-
- /* Add timeout */
- while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
- cpu_relax();
- }
-
- /* Enable pipe */
- reg_val = REG_READ(pipeconf_reg);
- if (!(reg_val & PIPEACONF_ENABLE)) {
- reg_val |= PIPEACONF_ENABLE;
- REG_WRITE(pipeconf_reg, reg_val);
- REG_READ(pipeconf_reg);
- udelay(500);
- mdfldWaitForPipeEnable(dev, pipe);
- }
-
- /* Enable plane */
- reg_val = REG_READ(dspcntr_reg);
- if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
- reg_val |= DISPLAY_PLANE_ENABLE;
- REG_WRITE(dspcntr_reg, reg_val);
- REG_READ(dspcntr_reg);
- udelay(500);
- }
-
- /* Enable TE interrupt on this pipe */
- mdfld_enable_te(dev, pipe);
- gma_power_end(dev);
-
- /*clean IN_DSR flag*/
- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-}
-
-/*
- * Exit from DSR
- */
-void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
- struct mdfld_dsi_dbi_output **dbi_output;
- int i;
- int pipe;
-
- /* FIXME can go ? */
- dev_priv->is_in_idle = false;
- dbi_output = dsr_info->dbi_outputs;
-
-#ifdef CONFIG_PM_RUNTIME
- if (!enable_gfx_rtpm) {
-/* pm_runtime_allow(&gpDrmDevice->pdev->dev); */
-/* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
- }
-#endif
-
- /* For each output, exit dsr */
- for (i = 0; i < dsr_info->dbi_output_num; i++) {
- /* If panel has been turned off, skip */
- if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
- continue;
- pipe = dbi_output[i]->channel_num ? 2 : 0;
- enter_dsr = 0;
- mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
- }
- dev_priv->dsr_fb_update |= update_src;
-}
-
-static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
-{
- if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
- return false;
- if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
- (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
- return false;
- if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
- (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
- return false;
-
- return true;
-}
-
-/* Periodically update dbi panel */
-void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
- struct mdfld_dsi_dbi_output **dbi_outputs;
- struct mdfld_dsi_dbi_output *dbi_output;
- int i;
- int can_enter_dsr = 0;
- u32 damage_mask;
-
- dbi_outputs = dsr_info->dbi_outputs;
- dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
-
- if (!dbi_output)
- return;
-
- if (pipe == 0)
- damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
- else if (pipe == 2)
- damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
- else
- return;
-
- /* If FB is damaged and panel is on update on-panel FB */
- if (damage_mask && dbi_output->dbi_panel_on) {
- dbi_output->dsr_fb_update_done = false;
-
- if (dbi_output->p_funcs->update_fb)
- dbi_output->p_funcs->update_fb(dbi_output, pipe);
-
- if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
- dev_priv->dsr_fb_update &= ~damage_mask;
-
- /*clean IN_DSR flag*/
- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-
- dbi_output->dsr_idle_count = 0;
- } else {
- dbi_output->dsr_idle_count++;
- }
-
- switch (dsr_info->dbi_output_num) {
- case 1:
- if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
- can_enter_dsr = 1;
- break;
- case 2:
- if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
- && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
- can_enter_dsr = 1;
- break;
- default:
- DRM_ERROR("Wrong DBI output number\n");
- }
-
- /* Try to enter DSR */
- if (can_enter_dsr) {
- for (i = 0; i < dsr_info->dbi_output_num; i++) {
- if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
- !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
- mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
- dbi_outputs[i]->channel_num ? 2 : 0);
-#if 0
- enter_dsr = 1;
- pr_err("%s: enter_dsr = 1\n", __func__);
-#endif
- }
- }
- /*schedule rpm suspend after gfxrtdelay*/
-#ifdef CONFIG_GFX_RTPM
- if (!dev_priv->rpm_enabled
- || !enter_dsr
- /* || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
- || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
- dev_warn(dev->dev,
- "Runtime PM schedule suspend failed, rpm %d\n",
- dev_priv->rpm_enabled);
-#endif
- }
-}
-
-int mdfld_dbi_dsr_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-
- if (!dsr_info || IS_ERR(dsr_info)) {
- dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
- GFP_KERNEL);
- if (!dsr_info) {
- dev_err(dev->dev, "No memory\n");
- return -ENOMEM;
- }
- dev_priv->dbi_dsr_info = dsr_info;
- }
- return 0;
-}
-
-void mdfld_dbi_dsr_exit(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
-
- if (dsr_info) {
- kfree(dsr_info);
- dev_priv->dbi_dsr_info = NULL;
- }
-}
-
-void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int lane_count = dsi_config->lane_count;
- u32 val = 0;
-
- dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
-
- /* Un-ready device */
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
- /* Init dsi adapter before kicking off */
- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
- /* TODO: figure out how to setup these registers */
- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
- 0x000a0014);
- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
- REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
- /* Enable all interrupts */
- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
- /* Max value: 20 clock cycles of txclkesc */
- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
- /* Min 21 txclkesc, max: ffffh */
- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
- /* Min: 7d0 max: 4e20 */
- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
- /* Set up func_prg */
- val |= lane_count;
- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
- val |= DSI_DBI_COLOR_FORMAT_OPTION2;
- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
- /* De-assert dbi_stall when half of DBI FIFO is empty */
- /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
-
- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-#if 0
-/*DBI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
- .dpms = mdfld_dsi_dbi_dpms,
- .mode_fixup = mdfld_dsi_dbi_mode_fixup,
- .prepare = mdfld_dsi_dbi_prepare,
- .mode_set = mdfld_dsi_dbi_mode_set,
- .commit = mdfld_dsi_dbi_commit,
-};
-
-/*DBI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-#endif
-
-/*
- * Init DSI DBI encoder.
- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
- * return pointer of newly allocated DBI encoder, NULL on error
- */
-struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- struct panel_funcs *p_funcs)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dsi_dbi_output *dbi_output = NULL;
- struct mdfld_dsi_config *dsi_config;
- struct drm_connector *connector = NULL;
- struct drm_encoder *encoder = NULL;
- struct drm_display_mode *fixed_mode = NULL;
- struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
- u32 data = 0;
- int pipe;
- int ret;
-
- if (!pg || !dsi_connector || !p_funcs) {
- WARN_ON(1);
- return NULL;
- }
-
- dsi_config = mdfld_dsi_get_config(dsi_connector);
- pipe = dsi_connector->pipe;
-
- /*panel hard-reset*/
- if (p_funcs->reset) {
- ret = p_funcs->reset(pipe);
- if (ret) {
- DRM_ERROR("Panel %d hard-reset failed\n", pipe);
- return NULL;
- }
- }
- /* Panel drvIC init */
- if (p_funcs->drv_ic_init)
- p_funcs->drv_ic_init(dsi_config, pipe);
-
- /* Panel power mode detect */
- ret = mdfld_dsi_get_power_mode(dsi_config,
- &data,
- MDFLD_DSI_HS_TRANSMISSION);
- if (ret) {
- DRM_ERROR("Panel %d get power mode failed\n", pipe);
- dsi_connector->status = connector_status_disconnected;
- } else {
- DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
- dsi_connector->status = connector_status_connected;
- }
-
- /*TODO: get panel info from DDB*/
-
- dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
- if (!dbi_output) {
- dev_err(dev->dev, "No memory\n");
- return NULL;
- }
-
- if (dsi_connector->pipe == 0) {
- dbi_output->channel_num = 0;
- dev_priv->dbi_output = dbi_output;
- } else if (dsi_connector->pipe == 2) {
- dbi_output->channel_num = 1;
- dev_priv->dbi_output2 = dbi_output;
- } else {
- dev_err(dev->dev, "only support 2 DSI outputs\n");
- goto out_err1;
- }
-
- dbi_output->dev = dev;
- dbi_output->p_funcs = p_funcs;
- fixed_mode = dsi_config->fixed_mode;
- dbi_output->panel_fixed_mode = fixed_mode;
-
- /* Create drm encoder object */
- connector = &dsi_connector->base.base;
- encoder = &dbi_output->base.base;
- /* Review this if we ever get MIPI-HDMI bridges or similar */
- drm_encoder_init(dev,
- encoder,
- p_funcs->encoder_funcs,
- DRM_MODE_ENCODER_LVDS);
- drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
-
- /* Attach to given connector */
- drm_mode_connector_attach_encoder(connector, encoder);
-
- /* Set possible CRTCs and clones */
- if (dsi_connector->pipe) {
- encoder->possible_crtcs = (1 << 2);
- encoder->possible_clones = (1 << 1);
- } else {
- encoder->possible_crtcs = (1 << 0);
- encoder->possible_clones = (1 << 0);
- }
-
- dev_priv->dsr_fb_update = 0;
- dev_priv->dsr_enable = false;
- dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
-
- dbi_output->first_boot = true;
- dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
-
- /* Add this output to dpu_info if in DPU mode */
- if (dpu_info && dsi_connector->status == connector_status_connected) {
- if (dsi_connector->pipe == 0)
- dpu_info->dbi_outputs[0] = dbi_output;
- else
- dpu_info->dbi_outputs[1] = dbi_output;
-
- dpu_info->dbi_output_num++;
- } else if (dsi_connector->status == connector_status_connected) {
- /* Add this output to dsr_info if not */
- if (dsi_connector->pipe == 0)
- dsr_info->dbi_outputs[0] = dbi_output;
- else
- dsr_info->dbi_outputs[1] = dbi_output;
-
- dsr_info->dbi_output_num++;
- }
- return &dbi_output->base;
-out_err1:
- kfree(dbi_output);
- return NULL;
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
deleted file mode 100644
index f0fa986fd934..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dbi.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DBI_H__
-#define __MDFLD_DSI_DBI_H__
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-/*
- * DBI encoder which inherits from mdfld_dsi_encoder
- */
-struct mdfld_dsi_dbi_output {
- struct mdfld_dsi_encoder base;
- struct drm_display_mode *panel_fixed_mode;
- u8 last_cmd;
- u8 lane_count;
- u8 channel_num;
- struct drm_device *dev;
-
- /* Backlight operations */
-
- /* DSR timer */
- u32 dsr_idle_count;
- bool dsr_fb_update_done;
-
- /* Mode setting flags */
- u32 mode_flags;
-
- /* Panel status */
- bool dbi_panel_on;
- bool first_boot;
- struct panel_funcs *p_funcs;
-
- /* DPU */
- u32 *dbi_cb_addr;
- u32 dbi_cb_phy;
- spinlock_t cb_lock;
- u32 cb_write;
-};
-
-#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \
- container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
-
-struct mdfld_dbi_dsr_info {
- int dbi_output_num;
- struct mdfld_dsi_dbi_output *dbi_outputs[2];
-
- u32 dsr_idle_count;
-};
-
-#define DBI_CB_TIMEOUT_COUNT 0xffff
-
-/* Offsets */
-#define CMD_MEM_ADDR_OFFSET 0
-
-#define CMD_DATA_SRC_SYSTEM_MEM 0
-#define CMD_DATA_SRC_PIPE 1
-
-static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output)
-{
- struct drm_device *dev = dbi_output->dev;
- u32 retry = DBI_CB_TIMEOUT_COUNT;
- int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
- int ret = 0;
-
- /* Query the dbi fifo status*/
- while (retry--) {
- if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27))
- break;
- }
-
- if (!retry) {
- DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
- ret = -EAGAIN;
- }
- return ret;
-}
-
-static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output)
-{
- struct drm_device *dev = dbi_output->dev;
- u32 retry = DBI_CB_TIMEOUT_COUNT;
- int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
- int ret = 0;
-
- /* Query the command execution status */
- while (retry--)
- if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0)))
- break;
-
- if (!retry) {
- DRM_ERROR("Timeout waiting for DBI command status\n");
- ret = -EAGAIN;
- }
-
- return ret;
-}
-
-static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output)
-{
- int ret = 0;
-
- /* Query the command execution status*/
- ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
- if (ret) {
- DRM_ERROR("Peripheral is busy\n");
- ret = -EAGAIN;
- }
- /* Query the dbi fifo status*/
- ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
- if (ret) {
- DRM_ERROR("DBI FIFO is not empty\n");
- ret = -EAGAIN;
- }
- return ret;
-}
-
-extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev, int pipe);
-extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src);
-extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe);
-extern int mdfld_dbi_dsr_init(struct drm_device *dev);
-extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
-extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- struct panel_funcs *p_funcs);
-extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
- u8 dcs, u8 *param, u32 num, u8 data_src);
-extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
- u16 x1, u16 y1, u16 x2, u16 y2);
-extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
- int mode);
-extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
- int pipe);
-
-#endif /*__MDFLD_DSI_DBI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
deleted file mode 100644
index a4e2ff442b1f..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- * Copyright © 2010-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jim Liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_dbi.h"
-
-/*
- * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
- */
-
-static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane,
- struct psb_drm_dpu_rect *damaged_rect)
-{
- int x, y;
- int new_x, new_y;
- struct psb_drm_dpu_rect *rect;
- struct psb_drm_dpu_rect *pipe_rect;
- int cursor_size;
- struct mdfld_cursor_info *cursor;
- mdfld_plane_t fb_plane;
-
- if (plane == MDFLD_CURSORA) {
- cursor = &dpu_info->cursors[0];
- x = dpu_info->cursors[0].x;
- y = dpu_info->cursors[0].y;
- cursor_size = dpu_info->cursors[0].size;
- pipe_rect = &dpu_info->damage_pipea;
- fb_plane = MDFLD_PLANEA;
- } else {
- cursor = &dpu_info->cursors[1];
- x = dpu_info->cursors[1].x;
- y = dpu_info->cursors[1].y;
- cursor_size = dpu_info->cursors[1].size;
- pipe_rect = &dpu_info->damage_pipec;
- fb_plane = MDFLD_PLANEC;
- }
- new_x = damaged_rect->x;
- new_y = damaged_rect->y;
-
- if (x == new_x && y == new_y)
- return 0;
-
- rect = &dpu_info->damaged_rects[plane];
- /* Move to right */
- if (new_x >= x) {
- if (new_y > y) {
- rect->x = x;
- rect->y = y;
- rect->width = (new_x + cursor_size) - x;
- rect->height = (new_y + cursor_size) - y;
- goto cursor_out;
- } else {
- rect->x = x;
- rect->y = new_y;
- rect->width = (new_x + cursor_size) - x;
- rect->height = (y - new_y);
- goto cursor_out;
- }
- } else {
- if (new_y > y) {
- rect->x = new_x;
- rect->y = y;
- rect->width = (x + cursor_size) - new_x;
- rect->height = new_y - y;
- goto cursor_out;
- } else {
- rect->x = new_x;
- rect->y = new_y;
- rect->width = (x + cursor_size) - new_x;
- rect->height = (y + cursor_size) - new_y;
- }
- }
-cursor_out:
- if (new_x < 0)
- cursor->x = 0;
- else if (new_x > 864)
- cursor->x = 864;
- else
- cursor->x = new_x;
-
- if (new_y < 0)
- cursor->y = 0;
- else if (new_y > 480)
- cursor->y = 480;
- else
- cursor->y = new_y;
-
- /*
- * FIXME: this is a workaround for cursor plane update,
- * remove it later!
- */
- rect->x = 0;
- rect->y = 0;
- rect->width = 864;
- rect->height = 480;
-
- mdfld_check_boundary(dpu_info, rect);
- mdfld_dpu_region_extent(pipe_rect, rect);
-
- /* Update pending status of dpu_info */
- dpu_info->pending |= (1 << plane);
- /* Update fb panel as well */
- dpu_info->pending |= (1 << fb_plane);
- return 0;
-}
-
-static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane,
- struct psb_drm_dpu_rect *damaged_rect)
-{
- struct psb_drm_dpu_rect *rect;
-
- if (plane == MDFLD_PLANEA)
- rect = &dpu_info->damage_pipea;
- else
- rect = &dpu_info->damage_pipec;
-
- mdfld_check_boundary(dpu_info, damaged_rect);
-
- /* Add fb damage area to this pipe */
- mdfld_dpu_region_extent(rect, damaged_rect);
-
- /* Update pending status of dpu_info */
- dpu_info->pending |= (1 << plane);
- return 0;
-}
-
-/* Do nothing here, right now */
-static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane,
- struct psb_drm_dpu_rect *damaged_rect)
-{
- return 0;
-}
-
-int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
- mdfld_plane_t plane,
- struct psb_drm_dpu_rect *rect)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- int ret = 0;
-
- /* DPU not in use, no damage reporting needed */
- if (dpu_info == NULL)
- return 0;
-
- spin_lock(&dpu_info->dpu_update_lock);
-
- switch (plane) {
- case MDFLD_PLANEA:
- case MDFLD_PLANEC:
- mdfld_fb_damage(dpu_info, plane, rect);
- break;
- case MDFLD_CURSORA:
- case MDFLD_CURSORC:
- mdfld_cursor_damage(dpu_info, plane, rect);
- break;
- case MDFLD_OVERLAYA:
- case MDFLD_OVERLAYC:
- mdfld_overlay_damage(dpu_info, plane, rect);
- break;
- default:
- DRM_ERROR("Invalid plane type %d\n", plane);
- ret = -EINVAL;
- }
- spin_unlock(&dpu_info->dpu_update_lock);
- return ret;
-}
-
-int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv;
- struct mdfld_dbi_dpu_info *dpu_info;
- struct mdfld_dsi_config *dsi_config;
- struct psb_drm_dpu_rect rect;
- int i;
-
- if (!dev) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- dev_priv = dev->dev_private;
- dpu_info = dev_priv->dbi_dpu_info;
-
- /* This is fine - we may be in non DPU mode */
- if (!dpu_info)
- return -EINVAL;
-
- for (i = 0; i < dpu_info->dbi_output_num; i++) {
- dsi_config = dev_priv->dsi_configs[i];
- if (dsi_config) {
- rect.x = rect.y = 0;
- rect.width = dsi_config->fixed_mode->hdisplay;
- rect.height = dsi_config->fixed_mode->vdisplay;
- mdfld_dbi_dpu_report_damage(dev,
- i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
- &rect);
- }
- }
- /* Exit DSR state */
- mdfld_dpu_exit_dsr(dev);
- return 0;
-}
-
-int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
- struct psb_drm_dpu_rect *rect)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
-
- /* If dual display mode */
- if (dpu_info->dbi_output_num == 2)
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
-
- /* Force dsi to exit DSR mode */
- mdfld_dpu_exit_dsr(dev);
- return 0;
-}
-
-static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane)
-{
- struct drm_device *dev = dpu_info->dev;
- u32 curpos_reg = CURAPOS;
- u32 curbase_reg = CURABASE;
- u32 curcntr_reg = CURACNTR;
- struct mdfld_cursor_info *cursor = &dpu_info->cursors[0];
-
- if (plane == MDFLD_CURSORC) {
- curpos_reg = CURCPOS;
- curbase_reg = CURCBASE;
- curcntr_reg = CURCCNTR;
- cursor = &dpu_info->cursors[1];
- }
-
- REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));
- REG_WRITE(curpos_reg,
- (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
- ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
- REG_WRITE(curbase_reg, REG_READ(curbase_reg));
-}
-
-static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane)
-{
- u32 pipesrc_reg = PIPEASRC;
- u32 dspsize_reg = DSPASIZE;
- u32 dspoff_reg = DSPALINOFF;
- u32 dspsurf_reg = DSPASURF;
- u32 dspstride_reg = DSPASTRIDE;
- u32 stride;
- struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea;
- struct drm_device *dev = dpu_info->dev;
-
- if (plane == MDFLD_PLANEC) {
- pipesrc_reg = PIPECSRC;
- dspsize_reg = DSPCSIZE;
- dspoff_reg = DSPCLINOFF;
- dspsurf_reg = DSPCSURF;
- dspstride_reg = DSPCSTRIDE;
- rect = &dpu_info->damage_pipec;
- }
-
- stride = REG_READ(dspstride_reg);
- /* FIXME: should I do the pipe src update here? */
- REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1));
- /* Flush plane */
- REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1));
- REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
-
- /*
- * TODO: wait for flip finished and restore the pipesrc reg,
- * or cursor will be show at a wrong position
- */
-}
-
-static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
- mdfld_plane_t plane)
-{
-}
-
-/*
- * TODO: we are still in dbi normal mode now, we will try to use partial
- * mode later.
- */
-static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output,
- struct mdfld_dbi_dpu_info *dpu_info, int pipe)
-{
- u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr;
- u32 *index;
- struct psb_drm_dpu_rect *rect = pipe ?
- (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
-
- /* FIXME: lock command buffer, this may lead to a deadlock,
- as we already hold the dpu_update_lock */
- if (!spin_trylock(&dbi_output->cb_lock)) {
- DRM_ERROR("lock command buffer failed, try again\n");
- return -EAGAIN;
- }
-
- index = &dbi_output->cb_write;
-
- if (*index) {
- DRM_ERROR("DBI command buffer unclean\n");
- return -EAGAIN;
- }
-
- /* Column address */
- *(cb_addr + ((*index)++)) = set_column_address;
- *(cb_addr + ((*index)++)) = rect->x >> 8;
- *(cb_addr + ((*index)++)) = rect->x;
- *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8;
- *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1);
-
- *index = 8;
-
- /* Page address */
- *(cb_addr + ((*index)++)) = set_page_addr;
- *(cb_addr + ((*index)++)) = rect->y >> 8;
- *(cb_addr + ((*index)++)) = rect->y;
- *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
- *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1);
-
- *index = 16;
-
- /*write memory*/
- *(cb_addr + ((*index)++)) = write_mem_start;
-
- return 0;
-}
-
-static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
-{
- u32 cmd_phy = dbi_output->dbi_cb_phy;
- u32 *index = &dbi_output->cb_write;
- int reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- struct drm_device *dev = dbi_output->dev;
-
- if (*index == 0 || !dbi_output)
- return 0;
-
- REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505);
- REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3);
-
- *index = 0;
-
- /* FIXME: unlock command buffer */
- spin_unlock(&dbi_output->cb_lock);
- return 0;
-}
-
-static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output,
- struct mdfld_dbi_dpu_info *dpu_info, int pipe)
-{
- struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- mdfld_plane_t cursor_plane = MDFLD_CURSORA;
- mdfld_plane_t fb_plane = MDFLD_PLANEA;
- mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
- int ret = 0;
- u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
-
- /* Damaged rects on this pipe */
- if (pipe) {
- cursor_plane = MDFLD_CURSORC;
- fb_plane = MDFLD_PLANEC;
- overlay_plane = MDFLD_OVERLAYC;
- plane_mask = MDFLD_PIPEC_PLANE_MASK;
- }
-
- /*update cursor which assigned to @pipe*/
- if (dpu_info->pending & (1 << cursor_plane))
- mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
-
- /*update fb which assigned to @pipe*/
- if (dpu_info->pending & (1 << fb_plane))
- mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
-
- /* TODO: update overlay */
- if (dpu_info->pending & (1 << overlay_plane))
- mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
-
- /* Flush damage area to panel fb */
- if (dpu_info->pending & plane_mask) {
- ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
- /*
- * TODO: remove b_dsr_enable later,
- * added it so that text console could boot smoothly
- */
- /* Clean pending flags on this pipe */
- if (!ret && dev_priv->dsr_enable) {
- dpu_info->pending &= ~plane_mask;
- /* Reset overlay pipe damage rect */
- mdfld_dpu_init_damage(dpu_info, pipe);
- }
- }
- return ret;
-}
-
-static int mdfld_dpu_update_fb(struct drm_device *dev)
-{
- struct drm_crtc *crtc;
- struct psb_intel_crtc *psb_crtc;
- struct mdfld_dsi_dbi_output **dbi_output;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- bool pipe_updated[2];
- unsigned long irq_flags;
- u32 dpll_reg = MRST_DPLL_A;
- u32 dspcntr_reg = DSPACNTR;
- u32 pipeconf_reg = PIPEACONF;
- u32 dsplinoff_reg = DSPALINOFF;
- u32 dspsurf_reg = DSPASURF;
- u32 mipi_state_reg = MIPIA_INTR_STAT_REG;
- u32 reg_offset = 0;
- int pipe;
- int i;
- int ret;
-
- dbi_output = dpu_info->dbi_outputs;
- pipe_updated[0] = pipe_updated[1] = false;
-
- if (!gma_power_begin(dev, true))
- return -EAGAIN;
-
- /* Try to prevent any new damage reports */
- if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags))
- return -EAGAIN;
-
- for (i = 0; i < dpu_info->dbi_output_num; i++) {
- crtc = dbi_output[i]->base.base.crtc;
- psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
-
- pipe = dbi_output[i]->channel_num ? 2 : 0;
-
- if (pipe == 2) {
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
- dsplinoff_reg = DSPCLINOFF;
- dspsurf_reg = DSPCSURF;
- reg_offset = MIPIC_REG_OFFSET;
- }
-
- if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset))
- & (1 << 27)) ||
- !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
- !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
- !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
- dev_err(dev->dev,
- "DBI FIFO is busy, DSI %d state %x\n",
- pipe,
- REG_READ(mipi_state_reg + reg_offset));
- continue;
- }
-
- /*
- * If DBI output is in a exclusive state then the pipe
- * change won't be updated
- */
- if (dbi_output[i]->dbi_panel_on &&
- !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
- !(psb_crtc &&
- psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
- !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
- ret = mdfld_dpu_update_pipe(dbi_output[i],
- dpu_info, dbi_output[i]->channel_num ? 2 : 0);
- if (!ret)
- pipe_updated[i] = true;
- }
- }
-
- for (i = 0; i < dpu_info->dbi_output_num; i++)
- if (pipe_updated[i])
- mdfld_dbi_flush_cb(dbi_output[i],
- dbi_output[i]->channel_num ? 2 : 0);
-
- spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
- gma_power_end(dev);
- return 0;
-}
-
-static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe)
-{
- struct drm_device *dev = dbi_output->dev;
- struct drm_crtc *crtc = dbi_output->base.base.crtc;
- struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc)
- : NULL;
- u32 reg_val;
- u32 dpll_reg = MRST_DPLL_A;
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
- u32 dspbase_reg = DSPABASE;
- u32 dspsurf_reg = DSPASURF;
- u32 reg_offset = 0;
-
- if (!dbi_output)
- return 0;
-
- /* If mode setting on-going, back off */
- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
- return -EAGAIN;
-
- if (pipe == 2) {
- dpll_reg = MRST_DPLL_A;
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- dspbase_reg = MDFLD_DSPCBASE;
- dspsurf_reg = DSPCSURF;
-
- reg_offset = MIPIC_REG_OFFSET;
- }
-
- if (!gma_power_begin(dev, true))
- return -EAGAIN;
-
- /* Enable DPLL */
- reg_val = REG_READ(dpll_reg);
- if (!(reg_val & DPLL_VCO_ENABLE)) {
-
- if (reg_val & MDFLD_PWR_GATE_EN) {
- reg_val &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(dpll_reg, reg_val);
- REG_READ(dpll_reg);
- udelay(500);
- }
-
- reg_val |= DPLL_VCO_ENABLE;
- REG_WRITE(dpll_reg, reg_val);
- REG_READ(dpll_reg);
- udelay(500);
-
- /* FIXME: add timeout */
- while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
- cpu_relax();
- }
-
- /* Enable pipe */
- reg_val = REG_READ(pipeconf_reg);
- if (!(reg_val & PIPEACONF_ENABLE)) {
- reg_val |= PIPEACONF_ENABLE;
- REG_WRITE(pipeconf_reg, reg_val);
- REG_READ(pipeconf_reg);
- udelay(500);
- mdfldWaitForPipeEnable(dev, pipe);
- }
-
- /* Enable plane */
- reg_val = REG_READ(dspcntr_reg);
- if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
- reg_val |= DISPLAY_PLANE_ENABLE;
- REG_WRITE(dspcntr_reg, reg_val);
- REG_READ(dspcntr_reg);
- udelay(500);
- }
-
- gma_power_end(dev);
-
- /* Clean IN_DSR flag */
- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
-
- return 0;
-}
-
-int mdfld_dpu_exit_dsr(struct drm_device *dev)
-{
- struct mdfld_dsi_dbi_output **dbi_output;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- int i;
- int pipe;
-
- dbi_output = dpu_info->dbi_outputs;
-
- for (i = 0; i < dpu_info->dbi_output_num; i++) {
- /* If this output is not in DSR mode, don't call exit dsr */
- if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)
- __mdfld_dbi_exit_dsr(dbi_output[i],
- dbi_output[i]->channel_num ? 2 : 0);
- }
-
- /* Enable TE interrupt */
- for (i = 0; i < dpu_info->dbi_output_num; i++) {
- /* If this output is not in DSR mode, don't call exit dsr */
- pipe = dbi_output[i]->channel_num ? 2 : 0;
- if (dbi_output[i]->dbi_panel_on && pipe) {
- mdfld_disable_te(dev, 0);
- mdfld_enable_te(dev, 2);
- } else if (dbi_output[i]->dbi_panel_on && !pipe) {
- mdfld_disable_te(dev, 2);
- mdfld_enable_te(dev, 0);
- }
- }
- return 0;
-}
-
-static int mdfld_dpu_enter_dsr(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- struct mdfld_dsi_dbi_output **dbi_output;
- int i;
-
- dbi_output = dpu_info->dbi_outputs;
-
- for (i = 0; i < dpu_info->dbi_output_num; i++) {
- /* If output is off or already in DSR state, don't re-enter */
- if (dbi_output[i]->dbi_panel_on &&
- !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
- mdfld_dsi_dbi_enter_dsr(dbi_output[i],
- dbi_output[i]->channel_num ? 2 : 0);
- }
- }
-
- return 0;
-}
-
-static void mdfld_dbi_dpu_timer_func(unsigned long data)
-{
- struct drm_device *dev = (struct drm_device *)data;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- struct timer_list *dpu_timer = &dpu_info->dpu_timer;
- unsigned long flags;
-
- if (dpu_info->pending) {
- dpu_info->idle_count = 0;
- /* Update panel fb with damaged area */
- mdfld_dpu_update_fb(dev);
- } else {
- dpu_info->idle_count++;
- }
-
- if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
- mdfld_dpu_enter_dsr(dev);
- /* Stop timer by return */
- return;
- }
-
- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
- if (!timer_pending(dpu_timer)) {
- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
- add_timer(dpu_timer);
- }
- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-}
-
-void mdfld_dpu_update_panel(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
- if (dpu_info->pending) {
- dpu_info->idle_count = 0;
-
- /*update panel fb with damaged area*/
- mdfld_dpu_update_fb(dev);
- } else {
- dpu_info->idle_count++;
- }
-
- if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
- /*enter dsr*/
- mdfld_dpu_enter_dsr(dev);
- }
-}
-
-static int mdfld_dbi_dpu_timer_init(struct drm_device *dev,
- struct mdfld_dbi_dpu_info *dpu_info)
-{
- struct timer_list *dpu_timer = &dpu_info->dpu_timer;
- unsigned long flags;
-
- spin_lock_init(&dpu_info->dpu_timer_lock);
- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
-
- init_timer(dpu_timer);
-
- dpu_timer->data = (unsigned long)dev;
- dpu_timer->function = mdfld_dbi_dpu_timer_func;
- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
-
- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-
- return 0;
-}
-
-void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info)
-{
- struct timer_list *dpu_timer = &dpu_info->dpu_timer;
- unsigned long flags;
-
- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
- if (!timer_pending(dpu_timer)) {
- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
- add_timer(dpu_timer);
- }
- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
-}
-
-int mdfld_dbi_dpu_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
- if (!dpu_info || IS_ERR(dpu_info)) {
- dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info),
- GFP_KERNEL);
- if (!dpu_info) {
- DRM_ERROR("No memory\n");
- return -ENOMEM;
- }
- dev_priv->dbi_dpu_info = dpu_info;
- }
-
- dpu_info->dev = dev;
-
- dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
- dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
-
- /*init dpu_update_lock*/
- spin_lock_init(&dpu_info->dpu_update_lock);
-
- /*init dpu refresh timer*/
- mdfld_dbi_dpu_timer_init(dev, dpu_info);
-
- /*init pipe damage area*/
- mdfld_dpu_init_damage(dpu_info, 0);
- mdfld_dpu_init_damage(dpu_info, 2);
-
- return 0;
-}
-
-void mdfld_dbi_dpu_exit(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
-
- if (!dpu_info)
- return;
-
- del_timer_sync(&dpu_info->dpu_timer);
- kfree(dpu_info);
- dev_priv->dbi_dpu_info = NULL;
-}
-
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
deleted file mode 100644
index 42367ed48c08..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DBI_DPU_H__
-#define __MDFLD_DSI_DBI_DPU_H__
-
-#include "mdfld_dsi_dbi.h"
-
-typedef enum {
- MDFLD_PLANEA,
- MDFLD_PLANEC,
- MDFLD_CURSORA,
- MDFLD_CURSORC,
- MDFLD_OVERLAYA,
- MDFLD_OVERLAYC,
- MDFLD_PLANE_NUM,
-} mdfld_plane_t;
-
-#define MDFLD_PIPEA_PLANE_MASK 0x15
-#define MDFLD_PIPEC_PLANE_MASK 0x2A
-
-struct mdfld_cursor_info {
- int x, y;
- int size;
-};
-
-#define MDFLD_CURSOR_SIZE 64
-
-/*
- * enter DSR mode if screen has no update for 2 frames.
- */
-#define MDFLD_MAX_IDLE_COUNT 2
-
-struct mdfld_dbi_dpu_info {
- struct drm_device *dev;
- /* Lock */
- spinlock_t dpu_update_lock;
-
- /* Cursor postion */
- struct mdfld_cursor_info cursors[2];
-
- /* Damaged area for each plane */
- struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
-
- /* Final damaged area */
- struct psb_drm_dpu_rect damage_pipea;
- struct psb_drm_dpu_rect damage_pipec;
-
- /* Pending */
- u32 pending;
-
- /* DPU timer */
- struct timer_list dpu_timer;
- spinlock_t dpu_timer_lock;
-
- /* DPU idle count */
- u32 idle_count;
-
- /* DSI outputs */
- struct mdfld_dsi_dbi_output *dbi_outputs[2];
- int dbi_output_num;
-};
-
-static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin,
- struct psb_drm_dpu_rect *rect)
-{
- int x1, y1, x2, y2;
-
- x1 = origin->x + origin->width;
- y1 = origin->y + origin->height;
-
- x2 = rect->x + rect->width;
- y2 = rect->y + rect->height;
-
- origin->x = min(origin->x, rect->x);
- origin->y = min(origin->y, rect->y);
- origin->width = max(x1, x2) - origin->x;
- origin->height = max(y1, y2) - origin->y;
-
- return 0;
-}
-
-static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info,
- struct psb_drm_dpu_rect *rect)
-{
- if (rect->x < 0)
- rect->x = 0;
- if (rect->y < 0)
- rect->y = 0;
-
- if (rect->x + rect->width > 864)
- rect->width = 864 - rect->x;
- if (rect->y + rect->height > 480)
- rect->height = 480 - rect->height;
-
- if (!rect->width)
- rect->width = 1;
- if (!rect->height)
- rect->height = 1;
-}
-
-static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info,
- int pipe)
-{
- struct psb_drm_dpu_rect *rect;
-
- if (pipe == 0)
- rect = &dpu_info->damage_pipea;
- else
- rect = &dpu_info->damage_pipec;
-
- rect->x = 864;
- rect->y = 480;
- rect->width = -864;
- rect->height = -480;
-}
-
-extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
- struct psb_drm_dpu_rect *rect);
-extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
- mdfld_plane_t plane,
- struct psb_drm_dpu_rect *rect);
-extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev);
-extern int mdfld_dpu_exit_dsr(struct drm_device *dev);
-extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info);
-extern int mdfld_dbi_dpu_init(struct drm_device *dev);
-extern void mdfld_dbi_dpu_exit(struct drm_device *dev);
-extern void mdfld_dpu_update_panel(struct drm_device *dev);
-
-#endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c
deleted file mode 100644
index e685f1217baa..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dpi.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-
-static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
- int timeout = 0;
-
- if (pipe == 2)
- gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
- int timeout = 0;
-
- if (pipe == 2)
- gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
- udelay(100);
- timeout++;
- }
- if (timeout == 20000)
- dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
- int timeout = 0;
-
- if (pipe == 2)
- gen_fifo_stat_reg += MIPIC_REG_OFFSET;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
- != DPI_FIFO_EMPTY)) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
-{
- u32 intr_stat_reg = MIPIA_INTR_STAT_REG;
- int timeout = 0;
-
- if (pipe == 2)
- intr_stat_reg += MIPIC_REG_OFFSET;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
-}
-
-
-/* ************************************************************************* *\
- * FUNCTION: mdfld_dsi_tpo_ic_init
- *
- * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
- * restore_display_registers. since this function does not
- * acquire the mutex, it is important that the calling function
- * does!
-\* ************************************************************************* */
-void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- u32 dcsChannelNumber = dsi_config->channel_num;
- u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG;
- u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
- u32 gen_ctrl_val = GEN_LONG_WRITE;
-
- if (pipe == 2) {
- gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
- gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
- }
-
- gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
-
- /* Flip page order */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00008036);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
- /* 0xF0 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5af0);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* Write protection key */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5af1);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xFC */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5afc);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xB7 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x770000b7);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000044);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
-
- /* 0xB6 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000a0ab6);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xF2 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x081010f2);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x4a070708);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000000c5);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xF8 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x024003f8);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x01030a04);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x0e020220);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000004);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
-
- /* 0xE2 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x398fc3e2);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x0000916f);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
-
- /* 0xB0 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000000b0);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
- /* 0xF4 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x240242f4);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x78ee2002);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2a071050);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x507fee10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x10300710);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
-
- /* 0xBA */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x19fe07ba);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x101c0a31);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000010);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xBB */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x28ff07bb);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x24280a31);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000034);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xFB */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535d05fb);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1b1a2130);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x221e180e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x131d2120);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535d0508);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1c1a2131);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x231f160d);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x111b2220);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535c2008);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1f1d2433);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2c251a10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2c34372d);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000023);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
- /* 0xFA */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x525c0bfa);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1c1c232f);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2623190e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x18212625);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x545d0d0e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1e1d2333);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x26231a10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1a222725);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x545d280f);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x21202635);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x31292013);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x31393d33);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000029);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
- /* Set DM */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000100f7);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-}
-
-static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
- int num_lane, int bpp)
-{
- return (u16)((pixel_clock_count * bpp) / (num_lane * 8));
-}
-
-/*
- * Calculate the dpi time basing on a given drm mode @mode
- * return 0 on success.
- * FIXME: I was using proposed mode value for calculation, may need to
- * use crtc mode values later
- */
-int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
- struct mdfld_dsi_dpi_timing *dpi_timing,
- int num_lane, int bpp)
-{
- int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
- int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
-
- if(!mode || !dpi_timing) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- pclk_hactive = mode->hdisplay;
- pclk_hfp = mode->hsync_start - mode->hdisplay;
- pclk_hsync = mode->hsync_end - mode->hsync_start;
- pclk_hbp = mode->htotal - mode->hsync_end;
-
- pclk_vactive = mode->vdisplay;
- pclk_vfp = mode->vsync_start - mode->vdisplay;
- pclk_vsync = mode->vsync_end - mode->vsync_start;
- pclk_vbp = mode->vtotal - mode->vsync_end;
-
- /*
- * byte clock counts were calculated by following formula
- * bclock_count = pclk_count * bpp / num_lane / 8
- */
- dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
- dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
- dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
- dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
- dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
- dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
- dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
-
- return 0;
-}
-
-void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int lane_count = dsi_config->lane_count;
- struct mdfld_dsi_dpi_timing dpi_timing;
- struct drm_display_mode *mode = dsi_config->mode;
- u32 val = 0;
-
- /*un-ready device*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
- /*init dsi adapter before kicking off*/
- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
- /*enable all interrupts*/
- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-
-
- /*set up func_prg*/
- val |= lane_count;
- val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
-
- switch(dsi_config->bpp) {
- case 16:
- val |= DSI_DPI_COLOR_FORMAT_RGB565;
- break;
- case 18:
- val |= DSI_DPI_COLOR_FORMAT_RGB666;
- break;
- case 24:
- val |= DSI_DPI_COLOR_FORMAT_RGB888;
- break;
- default:
- DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
- }
- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),
- (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
-
- /*max value: 20 clock cycles of txclkesc*/
- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
-
- /*min 21 txclkesc, max: ffffh*/
- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
-
- REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
-
- /*set DPI timing registers*/
- mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
-
- REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-
- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-
- /*min: 7d0 max: 4e20*/
- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
-
- /*set up video mode*/
- val = 0;
- val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
- REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-
- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-
- /*TODO: figure out how to setup these registers*/
- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-
- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
- /*set device ready*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
-{
- struct drm_device *dev = output->dev;
- u32 reg_offset = 0;
-
- if(output->panel_on)
- return;
-
- if(pipe)
- reg_offset = MIPIC_REG_OFFSET;
-
- /* clear special packet sent bit */
- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
- }
-
- /*send turn on package*/
- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
-
- /*wait for SPL_PKG_SENT interrupt*/
- mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
-
- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
- }
-
- output->panel_on = 1;
-
- /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
- /* if(pipe == 2) */
- /* dev_priv->dpi_panel_on2 = true; */
- /* else if (pipe == 0) */
- /* dev_priv->dpi_panel_on = true; */
-}
-
-static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
-{
- struct drm_device *dev = output->dev;
- u32 reg_offset = 0;
-
- /*if output is on, or mode setting didn't happen, ignore this*/
- if((!output->panel_on) || output->first_boot) {
- output->first_boot = 0;
- return;
- }
-
- if(pipe)
- reg_offset = MIPIC_REG_OFFSET;
-
- /* Wait for dpi fifo to empty */
- mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
-
- /* Clear the special packet interrupt bit if set */
- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
- }
-
- if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
- dev_warn(dev->dev, "try to send the same package again, abort!");
- goto shutdown_out;
- }
-
- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
-
-shutdown_out:
- output->panel_on = 0;
- output->first_boot = 0;
-
- /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
- /* if(pipe == 2) */
- /* dev_priv->dpi_panel_on2 = false; */
- /* else if (pipe == 0) */
- /* dev_priv->dpi_panel_on = false; */
- /* #ifdef CONFIG_PM_RUNTIME*/
- /* if (drm_psb_ospm && !enable_gfx_rtpm) { */
- /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */
- /* schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */
- /* } */
- /*if (enable_gfx_rtpm) */
- /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
- /* #endif */
-}
-
-void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 mipi_reg = MIPI;
- u32 pipeconf_reg = PIPEACONF;
-
- if(pipe) {
- mipi_reg = MIPI_C;
- pipeconf_reg = PIPECCONF;
- }
-
- /* Start up display island if it was shutdown */
- if (!gma_power_begin(dev, true))
- return;
-
- if(on) {
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID){
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- } else {
- /* Enable mipi port */
- REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31)));
- REG_READ(mipi_reg);
-
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- mdfld_dsi_tpo_ic_init(dsi_config, pipe);
- }
-
- if(pipe == 2) {
- dev_priv->dpi_panel_on2 = true;
- }
- else {
- dev_priv->dpi_panel_on = true;
- }
-
- } else {
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- } else {
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- /* Disable mipi port */
- REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31)));
- REG_READ(mipi_reg);
- }
-
- if(pipe == 2)
- dev_priv->dpi_panel_on2 = false;
- else
- dev_priv->dpi_panel_on = false;
- }
- gma_power_end(dev);
-}
-
-void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
-{
- dev_dbg(encoder->dev->dev, "DPMS %s\n",
- (mode == DRM_MODE_DPMS_ON ? "on":"off"));
-
- if (mode == DRM_MODE_DPMS_ON)
- mdfld_dsi_dpi_set_power(encoder, true);
- else {
- mdfld_dsi_dpi_set_power(encoder, false);
-#if 0 /* FIXME */
-#ifdef CONFIG_PM_RUNTIME
- if (enable_gfx_rtpm)
- pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
-#endif
-#endif
- }
-}
-
-bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
-
- if(fixed_mode) {
- adjusted_mode->hdisplay = fixed_mode->hdisplay;
- adjusted_mode->hsync_start = fixed_mode->hsync_start;
- adjusted_mode->hsync_end = fixed_mode->hsync_end;
- adjusted_mode->htotal = fixed_mode->htotal;
- adjusted_mode->vdisplay = fixed_mode->vdisplay;
- adjusted_mode->vsync_start = fixed_mode->vsync_start;
- adjusted_mode->vsync_end = fixed_mode->vsync_end;
- adjusted_mode->vtotal = fixed_mode->vtotal;
- adjusted_mode->clock = fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
- }
-
- return true;
-}
-
-void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)
-{
- mdfld_dsi_dpi_set_power(encoder, false);
-}
-
-void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
-{
- mdfld_dsi_dpi_set_power(encoder, true);
-}
-
-void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
-
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
- u32 mipi_reg = MIPI;
- u32 reg_offset = 0;
-
- u32 pipeconf = dev_priv->pipeconf;
- u32 dspcntr = dev_priv->dspcntr;
- u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-
- dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n",
- mode->hdisplay, mode->vdisplay, pipe);
-
- if(pipe) {
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- mipi_reg = MIPI_C;
- reg_offset = MIPIC_REG_OFFSET;
- } else {
- mipi |= 2;
- }
-
- if (!gma_power_begin(dev, true))
- return;
-
- /* Set up mipi port FIXME: do at init time */
- REG_WRITE(mipi_reg, mipi);
- REG_READ(mipi_reg);
-
- /* Set up DSI controller DPI interface */
- mdfld_dsi_dpi_controller_init(dsi_config, pipe);
-
- if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
- /* Turn on DPI interface */
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- }
-
- /* Set up pipe */
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
-
- /* Set up display plane */
- REG_WRITE(dspcntr_reg, dspcntr);
- REG_READ(dspcntr_reg);
-
- msleep(20); /* FIXME: this should wait for vblank */
-
- dev_dbg(dev->dev, "State %x, power %d\n",
- REG_READ(MIPIA_INTR_STAT_REG + reg_offset),
- dpi_output->panel_on);
-
- if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
- /* Init driver ic */
- mdfld_dsi_tpo_ic_init(dsi_config, pipe);
- /* Init backlight */
- mdfld_dsi_brightness_init(dsi_config, pipe);
- }
- gma_power_end(dev);
-}
-
-
-/*
- * Init DSI DPI encoder.
- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
- * return pointer of newly allocated DPI encoder, NULL on error
- */
-struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- struct panel_funcs *p_funcs)
-{
- struct mdfld_dsi_dpi_output *dpi_output = NULL;
- struct mdfld_dsi_config *dsi_config;
- struct drm_connector *connector = NULL;
- struct drm_encoder *encoder = NULL;
- struct drm_display_mode *fixed_mode = NULL;
- int pipe;
- u32 data;
- int ret;
-
- if (!dsi_connector || !p_funcs) {
- WARN_ON(1);
- return NULL;
- }
-
- dsi_config = mdfld_dsi_get_config(dsi_connector);
- pipe = dsi_connector->pipe;
-
- /* Panel hard-reset */
- if (p_funcs->reset) {
- ret = p_funcs->reset(pipe);
- if (ret) {
- DRM_ERROR("Panel %d hard-reset failed\n", pipe);
- return NULL;
- }
- }
-
- /* Panel drvIC init */
- if (p_funcs->drv_ic_init)
- p_funcs->drv_ic_init(dsi_config, pipe);
-
- /* Panel power mode detect */
- ret = mdfld_dsi_get_power_mode(dsi_config,
- &data,
- MDFLD_DSI_LP_TRANSMISSION);
- if (ret) {
- DRM_ERROR("Panel %d get power mode failed\n", pipe);
- dsi_connector->status = connector_status_disconnected;
- } else {
- DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
- dsi_connector->status = connector_status_connected;
- }
-
- dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
- if(!dpi_output) {
- dev_err(dev->dev, "No memory for dsi_dpi_output\n");
- return NULL;
- }
-
- if(dsi_connector->pipe)
- dpi_output->panel_on = 0;
- else
- dpi_output->panel_on = 0;
-
- dpi_output->dev = dev;
- dpi_output->p_funcs = p_funcs;
- dpi_output->first_boot = 1;
-
- /* Get fixed mode */
- dsi_config = mdfld_dsi_get_config(dsi_connector);
- fixed_mode = dsi_config->fixed_mode;
-
- /* Create drm encoder object */
- connector = &dsi_connector->base.base;
- encoder = &dpi_output->base.base;
- /*
- * On existing hardware this will be a panel of some form,
- * if future devices also have HDMI bridges this will need
- * revisiting
- */
- drm_encoder_init(dev,
- encoder,
- p_funcs->encoder_funcs,
- DRM_MODE_ENCODER_LVDS);
- drm_encoder_helper_add(encoder,
- p_funcs->encoder_helper_funcs);
-
- /* Attach to given connector */
- drm_mode_connector_attach_encoder(connector, encoder);
-
- /* Set possible crtcs and clones */
- if(dsi_connector->pipe) {
- encoder->possible_crtcs = (1 << 2);
- encoder->possible_clones = (1 << 1);
- } else {
- encoder->possible_crtcs = (1 << 0);
- encoder->possible_clones = (1 << 0);
- }
- return &dpi_output->base;
-}
-
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h
deleted file mode 100644
index ed92d45ee74a..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_dpi.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DPI_H__
-#define __MDFLD_DSI_DPI_H__
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-struct mdfld_dsi_dpi_timing {
- u16 hsync_count;
- u16 hbp_count;
- u16 hfp_count;
- u16 hactive_count;
- u16 vsync_count;
- u16 vbp_count;
- u16 vfp_count;
-};
-
-struct mdfld_dsi_dpi_output {
- struct mdfld_dsi_encoder base;
- struct drm_device *dev;
-
- int panel_on;
- int first_boot;
-
- struct panel_funcs *p_funcs;
-};
-
-#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \
- container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
-
-extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
- struct mdfld_dsi_dpi_timing *dpi_timing,
- int num_lane, int bpp);
-extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- struct panel_funcs *p_funcs);
-
-/* Medfield DPI helper functions */
-extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
-extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
- int pipe);
-extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config,
- int pipe);
-#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
deleted file mode 100644
index 3f979db2c3a5..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include <asm/intel_scu_ipc.h>
-#include "mdfld_dsi_pkg_sender.h"
-#include <linux/pm_runtime.h>
-#include <linux/moduleparam.h>
-
-#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
-
-static int CABC_control = 1;
-static int LABC_control = 1;
-
-module_param (CABC_control, int, 0644);
-module_param (LABC_control, int, 0644);
-
-/**
- * make these MCS command global
- * we don't need 'movl' everytime we send them.
- * FIXME: these datas were provided by OEM, we should get them from GCT.
- **/
-static u32 mdfld_dbi_mcs_hysteresis[] = {
- 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x000000ff,
-};
-
-static u32 mdfld_dbi_mcs_display_profile[] = {
- 0x50281450, 0x0000c882, 0x00000000, 0x00000000,
- 0x00000000,
-};
-
-static u32 mdfld_dbi_mcs_kbbc_profile[] = {
- 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
-};
-
-static u32 mdfld_dbi_mcs_gamma_profile[] = {
- 0x81111158, 0x88888888, 0x88888888,
-};
-
-/*
- * write hysteresis values.
- */
-static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
- mdfld_dsi_send_mcs_long_hs(sender,
- mdfld_dbi_mcs_hysteresis,
- 17,
- MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write display profile values.
- */
-static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
- mdfld_dsi_send_mcs_long_hs(sender,
- mdfld_dbi_mcs_display_profile,
- 5,
- MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write KBBC profile values.
- */
-static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
- mdfld_dsi_send_mcs_long_hs(sender,
- mdfld_dbi_mcs_kbbc_profile,
- 4,
- MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * write gamma setting.
- */
-static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
- mdfld_dsi_send_mcs_long_hs(sender,
- mdfld_dbi_mcs_gamma_profile,
- 3,
- MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * Check and see if the generic control or data buffer is empty and ready.
- */
-void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
-{
- u32 GEN_BF_time_out_count = 0;
-
- /* Check MIPI Adatper command registers */
- for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
- {
- if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
- break;
- udelay (100);
- }
-
- if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
- dev_err(dev->dev,
- "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
- gen_fifo_stat_reg);
-}
-
-/*
- * Manage the DSI MIPI keyboard and display brightness.
- * FIXME: this is exported to OSPM code. should work out an specific
- * display interface to OSPM.
- */
-void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
- struct drm_device *dev = sender->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 gen_ctrl_val;
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
- /* Set default display backlight value to 85% (0xd8)*/
- mdfld_dsi_send_mcs_short_hs(sender,
- write_display_brightness,
- 0xd8,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
-
- /* Set minimum brightness setting of CABC function to 20% (0x33)*/
- mdfld_dsi_send_mcs_short_hs(sender,
- write_cabc_min_bright,
- 0x33,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
-
- mdfld_dsi_write_hysteresis(dsi_config, pipe);
- mdfld_dsi_write_display_profile (dsi_config, pipe);
- mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
- mdfld_dsi_write_gamma_setting (dsi_config, pipe);
-
- /* Enable backlight or/and LABC */
- gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
- if (LABC_control == 1 || CABC_control == 1)
- gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
-
- if (LABC_control == 1)
- gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
-
- dev_priv->mipi_ctrl_display = gen_ctrl_val;
-
- mdfld_dsi_send_mcs_short_hs(sender,
- write_ctrl_display,
- (u8)gen_ctrl_val,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
-
- if (CABC_control == 0)
- return;
- mdfld_dsi_send_mcs_short_hs(sender,
- write_ctrl_cabc,
- UI_IMAGE,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
-}
-
-/*
- * Manage the mipi display brightness.
- * TODO: refine this interface later
- */
-void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
-{
- struct mdfld_dsi_pkg_sender *sender;
- struct drm_psb_private *dev_priv;
- struct mdfld_dsi_config *dsi_config;
- u32 gen_ctrl_val;
- int p_type;
-
- if (!dev || (pipe != 0 && pipe != 2)) {
- dev_err(dev->dev, "Invalid parameter\n");
- return;
- }
-
- p_type = mdfld_get_panel_type(dev, 0);
-
- dev_priv = dev->dev_private;
-
- if(pipe)
- dsi_config = dev_priv->dsi_configs[1];
- else
- dsi_config = dev_priv->dsi_configs[0];
-
- sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
-
- gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
-
- dev_dbg(dev->dev,
- "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val);
-
- if(p_type == TMD_VID || p_type == TMD_CMD){
- /* Set display backlight value */
- mdfld_dsi_send_mcs_short_hs(sender,
- tmd_write_display_brightness,
- (u8)gen_ctrl_val,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
- } else {
- /* Set display backlight value */
- mdfld_dsi_send_mcs_short_hs(sender,
- write_display_brightness,
- (u8)gen_ctrl_val,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
-
-
- /* Enable backlight control */
- if (level == 0)
- gen_ctrl_val = 0;
- else
- gen_ctrl_val = dev_priv->mipi_ctrl_display;
-
- mdfld_dsi_send_mcs_short_hs(sender,
- write_ctrl_display,
- (u8)gen_ctrl_val,
- 1,
- MDFLD_DSI_SEND_PACKAGE);
- }
-}
-
-/*
- * shut down DSI controller
- */
-void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct drm_device * dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int retry = 100;
-
- if (!dsi_config) {
- WARN_ON(1);
- return;
- }
-
- dev = dsi_config->dev;
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))
- goto shutdown_out;
-
- /* Send shut down package, clean packet send bit first */
- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset),
- (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
- }
-
- /*send shut down package in HS*/
- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
-
-
- /*
- * make sure shut down is sent.
- * FIXME: add max retry counter
- */
- while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
- retry--;
-
- if(!retry) {
- dev_err(dev->dev, "timeout\n");
- break;
- }
- }
-
- /*sleep 1 ms to ensure shutdown finished*/
- msleep(100);
-
- /*un-ready device*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
- (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
-
-shutdown_out:
- gma_power_end(dev);
-}
-
-void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct drm_device * dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int retry = 100;
-
-
- if (!dsi_config) {
- WARN_ON(1);
- return;
- }
-
- dev = dsi_config->dev;
- dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))
- goto startup_out;
-
- /*if config DPI, turn on DPI interface*/
- if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
- }
-
- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
-
- /*
- * make sure shut down is sent.
- * FIXME: add max retry counter
- */
- while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
- retry--;
- if(!retry) {
- dev_err(dev->dev, "timeout\n");
- break;
- }
- }
-
- msleep(100);
- }
-
- /*set device ready*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
- (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
-
-startup_out:
- gma_power_end(dev);
-}
-
-
-static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
- u8 dcs,
- u32 *data,
- u8 transmission)
-{
- struct mdfld_dsi_pkg_sender *sender
- = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if (!sender || !data) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- if (transmission == MDFLD_DSI_HS_TRANSMISSION)
- return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
- else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
- return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
- else
- return -EINVAL;
-}
-
-int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
- u32 *mode,
- u8 transmission)
-{
- if (!dsi_config || !mode) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
-}
-
-int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
- u32 *result,
- u8 transmission)
-{
- if (!dsi_config || !result) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
- transmission);
-}
-
-/*
- * NOTE: this function was used by OSPM.
- * TODO: will be removed later, should work out display interfaces for OSPM
- */
-void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
- WARN_ON(1);
- return;
- }
-
- if(dsi_config->type)
- mdfld_dsi_dpi_controller_init(dsi_config, pipe);
- else
- mdfld_dsi_controller_dbi_init(dsi_config, pipe);
-}
-
-static void mdfld_dsi_connector_save(struct drm_connector * connector)
-{
-}
-
-static void mdfld_dsi_connector_restore(struct drm_connector * connector)
-{
-}
-
-static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
-{
- struct psb_intel_output *psb_output
- = to_psb_intel_output(connector);
- struct mdfld_dsi_connector *dsi_connector
- = MDFLD_DSI_CONNECTOR(psb_output);
- return dsi_connector->status;
-}
-
-static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- struct drm_encoder *encoder = connector->encoder;
-
- if (!strcmp(property->name, "scaling mode") && encoder) {
- struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
- bool bTransitionFromToCentered;
- uint64_t curValue;
-
- if (!psb_crtc)
- goto set_prop_error;
-
- switch (value) {
- case DRM_MODE_SCALE_FULLSCREEN:
- break;
- case DRM_MODE_SCALE_NO_SCALE:
- break;
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- goto set_prop_error;
- }
-
- if (drm_connector_property_get_value(connector, property, &curValue))
- goto set_prop_error;
-
- if (curValue == value)
- goto set_prop_done;
-
- if (drm_connector_property_set_value(connector, property, value))
- goto set_prop_error;
-
- bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
- (value == DRM_MODE_SCALE_NO_SCALE);
-
- if (psb_crtc->saved_mode.hdisplay != 0 &&
- psb_crtc->saved_mode.vdisplay != 0) {
- if (bTransitionFromToCentered) {
- if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
- encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
- goto set_prop_error;
- } else {
- struct drm_encoder_helper_funcs *pEncHFuncs = encoder->helper_private;
- pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
- &psb_crtc->saved_adjusted_mode);
- }
- }
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- } else if (!strcmp(property->name, "backlight") && encoder) {
- struct drm_psb_private *dev_priv = encoder->dev->dev_private;
- struct backlight_device *psb_bd = dev_priv->backlight_device;
- dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
- if (drm_connector_property_set_value(connector, property, value))
- goto set_prop_error;
- else {
- dev_dbg(encoder->dev->dev,
- "set brightness to %d", (int)value);
- if (psb_bd) {
- psb_bd->props.brightness = value;
- backlight_update_status(psb_bd);
- }
- }
-#endif
- }
-set_prop_done:
- return 0;
-set_prop_error:
- return -1;
-}
-
-static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output * psb_output = to_psb_intel_output(connector);
- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
- struct mdfld_dsi_pkg_sender * sender;
-
- if(!dsi_connector)
- return;
-
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
-
- sender = dsi_connector->pkg_sender;
-
- mdfld_dsi_pkg_sender_destroy(sender);
-
- kfree(dsi_connector);
-}
-
-static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
-{
- struct psb_intel_output * psb_output = to_psb_intel_output(connector);
- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
- struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
- struct drm_display_mode * dup_mode = NULL;
- struct drm_device * dev = connector->dev;
-
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
-
- if(fixed_mode) {
- dev_dbg(dev->dev, "fixed_mode %dx%d\n",
- fixed_mode->hdisplay, fixed_mode->vdisplay);
-
- dup_mode = drm_mode_duplicate(dev, fixed_mode);
- drm_mode_probed_add(connector, dup_mode);
- return 1;
- }
- dev_err(dev->dev, "Didn't get any modes!\n");
- return 0;
-}
-
-static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
-{
- struct psb_intel_output * psb_output = to_psb_intel_output(connector);
- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
- struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
-
- dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
- mode, fixed_mode);
-
- if(mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- if(mode->flags & DRM_MODE_FLAG_INTERLACE)
- return MODE_NO_INTERLACE;
-
- /**
- * FIXME: current DC has no fitting unit, reject any mode setting request
- * will figure out a way to do up-scaling(pannel fitting) later.
- **/
- if(fixed_mode) {
- if(mode->hdisplay != fixed_mode->hdisplay)
- return MODE_PANEL;
-
- if(mode->vdisplay != fixed_mode->vdisplay)
- return MODE_PANEL;
- }
- dev_dbg(connector->dev->dev, "mode ok\n");
-
- return MODE_OK;
-}
-
-static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
-{
-#ifdef CONFIG_PM_RUNTIME
- struct drm_device * dev = connector->dev;
- struct drm_psb_private * dev_priv = dev->dev_private;
- bool panel_on, panel_on2;
-#endif
- /* First, execute DPMS */
- drm_helper_connector_dpms(connector, mode);
-
-#ifdef CONFIG_PM_RUNTIME
- if(mdfld_panel_dpi(dev)) {
- /* DPI panel */
- panel_on = dev_priv->dpi_panel_on;
- panel_on2 = dev_priv->dpi_panel_on2;
- } else {
- /* DBI panel */
- panel_on = dev_priv->dbi_panel_on;
- panel_on2 = dev_priv->dbi_panel_on2;
- }
-
- /* Then check all display panels + monitors status */
- /* Make sure that the Display (B) sub-system status isn't i3 when
- * R/W the DC register, otherwise "Fabric error" issue would occur
- * during S0i3 state. */
- if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
- & HDMIB_PORT_EN)) {
- /* Request rpm idle */
- if(dev_priv->rpm_enabled)
- pm_request_idle(&dev->pdev->dev);
- }
- /*
- * if rpm wasn't enabled yet, try to allow it
- * FIXME: won't enable rpm for DPI since DPI
- * CRTC setting is a little messy now.
- * Enable it later!
- */
-#if 0
- if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
- ospm_runtime_pm_allow(dev);
-#endif
-#endif
-}
-
-static struct drm_encoder *mdfld_dsi_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct psb_intel_output * psb_output = to_psb_intel_output(connector);
- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
- struct mdfld_dsi_encoder * encoder = NULL;
-
- if(dsi_config->type == MDFLD_DSI_ENCODER_DBI)
- encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
- else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
- encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
-
- dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
-
- if(!encoder) {
- dev_err(connector->dev->dev,
- "Invalid encoder for type %d\n", dsi_config->type);
- return NULL;
- }
- dsi_config->encoder = encoder;
- return &encoder->base;
-}
-
-/* DSI connector funcs */
-static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
- .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
- .save = mdfld_dsi_connector_save,
- .restore = mdfld_dsi_connector_restore,
- .detect = mdfld_dsi_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = mdfld_dsi_connector_set_property,
- .destroy = mdfld_dsi_connector_destroy,
-};
-
-/* DSI connector helper funcs */
-static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
- .get_modes = mdfld_dsi_connector_get_modes,
- .mode_valid = mdfld_dsi_connector_mode_valid,
- .best_encoder = mdfld_dsi_connector_best_encoder,
-};
-
-static int mdfld_dsi_get_default_config(struct drm_device * dev,
- struct mdfld_dsi_config * config, int pipe)
-{
- if(!dev || !config) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- config->bpp = 24;
- config->type = mdfld_panel_dpi(dev);
- config->lane_count = 2;
- config->channel_num = 0;
- /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
- } else {
- config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
- }
-
- return 0;
-}
-
-/*
- * Returns the panel fixed mode from configuration.
- */
-struct drm_display_mode *
-mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false;
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode) {
- dev_err(dev->dev, "Out of memory for mode\n");
- return NULL;
- }
- if (use_gct) {
- dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay + \
- ((ti->hsync_offset_hi << 8) | \
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start + \
- ((ti->hsync_pulse_width_hi << 8) | \
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
- ti->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay + \
- ((ti->vblank_hi << 8) | ti->vblank_lo);
- mode->clock = ti->pixel_clock * 10;
- } else {
- if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- mode->hdisplay = 480;
- mode->vdisplay = 854;
- mode->hsync_start = 487;
- mode->hsync_end = 490;
- mode->htotal = 499;
- mode->vsync_start = 861;
- mode->vsync_end = 865;
- mode->vtotal = 873;
- mode->clock = 33264;
- } else {
- mode->hdisplay = 864;
- mode->vdisplay = 480;
- mode->hsync_start = 873;
- mode->hsync_end = 876;
- mode->htotal = 887;
- mode->vsync_start = 487;
- mode->vsync_end = 490;
- mode->vtotal = 499;
- mode->clock = 33264;
- }
- } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
- mode->hdisplay = 864;
- mode->vdisplay = 480;
- mode->hsync_start = 872;
- mode->hsync_end = 876;
- mode->htotal = 884;
- mode->vsync_start = 482;
- mode->vsync_end = 494;
- mode->vtotal = 486;
- mode->clock = 25777;
-
- }
- }
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-int mdfld_dsi_panel_reset(int pipe)
-{
- unsigned gpio;
- int ret = 0;
-
- switch (pipe) {
- case 0:
- gpio = 128;
- break;
- case 2:
- gpio = 34;
- break;
- default:
- DRM_ERROR("Invalid output\n");
- return -EINVAL;
- }
-
- ret = gpio_request(gpio, "gfx");
- if (ret) {
- DRM_ERROR("gpio_rqueset failed\n");
- return ret;
- }
-
- ret = gpio_direction_output(gpio, 1);
- if (ret) {
- DRM_ERROR("gpio_direction_output failed\n");
- goto gpio_error;
- }
-
- gpio_get_value(128);
-
-gpio_error:
- if (gpio_is_valid(gpio))
- gpio_free(gpio);
-
- return ret;
-}
-
-/*
- * MIPI output init
- * @dev drm device
- * @pipe pipe number. 0 or 2
- * @config
- *
- * Do the initialization of a MIPI output, including create DRM mode objects
- * initialization of DSI output on @pipe
- */
-void mdfld_dsi_output_init(struct drm_device *dev,
- int pipe,
- struct mdfld_dsi_config *config,
- struct panel_funcs* p_cmd_funcs,
- struct panel_funcs* p_vid_funcs)
-{
- struct mdfld_dsi_config * dsi_config;
- struct mdfld_dsi_connector * dsi_connector;
- struct psb_intel_output * psb_output;
- struct drm_connector * connector;
- struct mdfld_dsi_encoder * encoder;
- struct drm_psb_private * dev_priv = dev->dev_private;
- struct panel_info dsi_panel_info;
- u32 width_mm, height_mm;
-
- dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
-
- if(!dev || ((pipe != 0) && (pipe != 2))) {
- WARN_ON(1);
- return;
- }
-
- /*create a new connetor*/
- dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
- if(!dsi_connector) {
- DRM_ERROR("No memory");
- return;
- }
-
- dsi_connector->pipe = pipe;
-
- /*set DSI config*/
- if(config) {
- dsi_config = config;
- } else {
- dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
- if(!dsi_config) {
- dev_err(dev->dev,
- "cannot allocate memory for DSI config\n");
- goto dsi_init_err0;
- }
-
- mdfld_dsi_get_default_config(dev, dsi_config, pipe);
- }
-
- dsi_connector->private = dsi_config;
-
- dsi_config->changed = 1;
- dsi_config->dev = dev;
-
- /* Init fixed mode basing on DSI config type */
- if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
- dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
- if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
- goto dsi_init_err0;
- } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
- dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
- if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
- goto dsi_init_err0;
- }
-
- width_mm = dsi_panel_info.width_mm;
- height_mm = dsi_panel_info.height_mm;
-
- dsi_config->mode = dsi_config->fixed_mode;
- dsi_config->connector = dsi_connector;
-
- if(!dsi_config->fixed_mode) {
- dev_err(dev->dev, "No pannel fixed mode was found\n");
- goto dsi_init_err0;
- }
-
- if(pipe && dev_priv->dsi_configs[0]) {
- dsi_config->dvr_ic_inited = 0;
- dev_priv->dsi_configs[1] = dsi_config;
- } else if(pipe == 0) {
- dsi_config->dvr_ic_inited = 1;
- dev_priv->dsi_configs[0] = dsi_config;
- } else {
- dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
- goto dsi_init_err0;
- }
-
- /*init drm connector object*/
- psb_output = &dsi_connector->base;
-
- psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
-
- connector = &psb_output->base;
- /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
- drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
- drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
-
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->display_info.width_mm = width_mm;
- connector->display_info.height_mm = height_mm;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- /* Attach properties */
- drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
- drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
-
- /* Init DSI package sender on this output */
- if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
- DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
- goto dsi_init_err0;
- }
-
- /* Init DBI & DPI encoders */
- if (p_cmd_funcs) {
- encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
- if(!encoder) {
- dev_err(dev->dev, "Create DBI encoder failed\n");
- goto dsi_init_err1;
- }
- encoder->private = dsi_config;
- dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
- }
-
- if(p_vid_funcs) {
- encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
- if(!encoder) {
- dev_err(dev->dev, "Create DPI encoder failed\n");
- goto dsi_init_err1;
- }
- encoder->private = dsi_config;
- dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
- }
-
- drm_sysfs_connector_add(connector);
- return;
-
- /*TODO: add code to destroy outputs on error*/
-dsi_init_err1:
- /*destroy sender*/
- mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
-
- drm_connector_cleanup(connector);
- kfree(dsi_config->fixed_mode);
- kfree(dsi_config);
-dsi_init_err0:
- kfree(dsi_connector);
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
deleted file mode 100644
index 4699267efd60..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_output.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_OUTPUT_H__
-#define __MDFLD_DSI_OUTPUT_H__
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include "mdfld_output.h"
-
-#include <asm/mrst.h>
-
-
-static inline struct mdfld_dsi_config *
- mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
-{
- if (!connector)
- return NULL;
- return (struct mdfld_dsi_config *)connector->private;
-}
-
-static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
-{
- struct mdfld_dsi_connector *dsi_connector;
-
- if (!config)
- return NULL;
-
- dsi_connector = config->connector;
-
- if (!dsi_connector)
- return NULL;
-
- return dsi_connector->pkg_sender;
-}
-
-static inline struct mdfld_dsi_config *
- mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
-{
- if (!encoder)
- return NULL;
- return (struct mdfld_dsi_config *)encoder->private;
-}
-
-static inline struct mdfld_dsi_connector *
- mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_config *config;
-
- if (!encoder)
- return NULL;
-
- config = mdfld_dsi_encoder_get_config(encoder);
- if (!config)
- return NULL;
-
- return config->connector;
-}
-
-static inline void *mdfld_dsi_encoder_get_pkg_sender(
- struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_config *dsi_config;
-
- dsi_config = mdfld_dsi_encoder_get_config(encoder);
- if (!dsi_config)
- return NULL;
-
- return mdfld_dsi_get_pkg_sender(dsi_config);
-}
-
-static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_connector *connector;
-
- if (!encoder)
- return -1;
-
- connector = mdfld_dsi_encoder_get_connector(encoder);
- if (!connector)
- return -1;
-
- return connector->pipe;
-}
-
-extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
- u32 gen_fifo_stat_reg, u32 fifo_stat);
-extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
- int pipe);
-extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
- int level);
-extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe,
- struct mdfld_dsi_config *config,
- struct panel_funcs *p_cmd_funcs,
- struct panel_funcs *p_vid_funcs);
-extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
- int pipe);
-extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
- u32 *mode,
- u8 transmission);
-extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
- u32 *result,
- u8 transmission);
-extern int mdfld_dsi_panel_reset(int pipe);
-
-#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
deleted file mode 100644
index 9b96a5c9abcd..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
+++ /dev/null
@@ -1,1484 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include <linux/freezer.h>
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-
-#define MDFLD_DSI_DBI_FIFO_TIMEOUT 100
-#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE 512
-#define MDFLD_DSI_READ_MAX_COUNT 5000
-
-static const char * const dsi_errors[] = {
- "RX SOT Error",
- "RX SOT Sync Error",
- "RX EOT Sync Error",
- "RX Escape Mode Entry Error",
- "RX LP TX Sync Error",
- "RX HS Receive Timeout Error",
- "RX False Control Error",
- "RX ECC Single Bit Error",
- "RX ECC Multibit Error",
- "RX Checksum Error",
- "RX DSI Data Type Not Recognised",
- "RX DSI VC ID Invalid",
- "TX False Control Error",
- "TX ECC Single Bit Error",
- "TX ECC Multibit Error",
- "TX Checksum Error",
- "TX DSI Data Type Not Recognised",
- "TX DSI VC ID invalid",
- "High Contention",
- "Low contention",
- "DPI FIFO Under run",
- "HS TX Timeout",
- "LP RX Timeout",
- "Turn Around ACK Timeout",
- "ACK With No Error",
- "RX Invalid TX Length",
- "RX Prot Violation",
- "HS Generic Write FIFO Full",
- "LP Generic Write FIFO Full",
- "Generic Read Data Avail",
- "Special Packet Sent",
- "Tearing Effect",
-};
-
-static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
- u32 mask)
-{
- struct drm_device *dev = sender->dev;
- u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
- int retry = 0xffff;
-
- while (retry--) {
- if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
- return 0;
- udelay(100);
- }
- dev_err(dev->dev, "fifo is NOT empty 0x%08x\n",
- REG_READ(gen_fifo_stat_reg));
- return -EIO;
-}
-
-static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18)
- | (1 << 26) | (1 << 27) | (1 << 28));
-}
-
-static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26));
-}
-
-static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18));
-}
-
-static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (1 << 27));
-}
-
-static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
-{
- u32 intr_stat_reg = sender->mipi_intr_stat_reg;
- struct drm_device *dev = sender->dev;
-
- switch (mask) {
- case (1 << 0):
- case (1 << 1):
- case (1 << 2):
- case (1 << 3):
- case (1 << 4):
- case (1 << 5):
- case (1 << 6):
- case (1 << 7):
- case (1 << 8):
- case (1 << 9):
- case (1 << 10):
- case (1 << 11):
- case (1 << 12):
- case (1 << 13):
- break;
- case (1 << 14):
- /*wait for all fifo empty*/
- /*wait_for_all_fifos_empty(sender)*/;
- break;
- case (1 << 15):
- break;
- case (1 << 16):
- break;
- case (1 << 17):
- break;
- case (1 << 18):
- case (1 << 19):
- /*wait for contention recovery time*/
- /*mdelay(10);*/
- /*wait for all fifo empty*/
- if (0)
- wait_for_all_fifos_empty(sender);
- break;
- case (1 << 20):
- break;
- case (1 << 21):
- /*wait for all fifo empty*/
- /*wait_for_all_fifos_empty(sender);*/
- break;
- case (1 << 22):
- break;
- case (1 << 23):
- case (1 << 24):
- case (1 << 25):
- case (1 << 26):
- case (1 << 27):
- /* HS Gen fifo full */
- REG_WRITE(intr_stat_reg, mask);
- wait_for_hs_fifos_empty(sender);
- break;
- case (1 << 28):
- /* LP Gen fifo full\n */
- REG_WRITE(intr_stat_reg, mask);
- wait_for_lp_fifos_empty(sender);
- break;
- case (1 << 29):
- case (1 << 30):
- case (1 << 31):
- break;
- }
-
- if (mask & REG_READ(intr_stat_reg))
- dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask);
-
- return 0;
-}
-
-static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
-{
- struct drm_device *dev = sender->dev;
- u32 intr_stat_reg = sender->mipi_intr_stat_reg;
- u32 mask;
- u32 intr_stat;
- int i;
- int err = 0;
-
- intr_stat = REG_READ(intr_stat_reg);
-
- for (i = 0; i < 32; i++) {
- mask = (0x00000001UL) << i;
- if (intr_stat & mask) {
- dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]);
- err = handle_dsi_error(sender, mask);
- if (err)
- dev_err(dev->dev, "Cannot handle error\n");
- }
- }
- return err;
-}
-
-static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender)
-{
- struct drm_device *dev = sender->dev;
- u32 retry = 0xffff;
- u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
-
- /* Query the command execution status */
- while (retry--) {
- if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0)))
- break;
- }
-
- if (!retry) {
- dev_err(dev->dev, "Timeout waiting for DBI Command status\n");
- return -EAGAIN;
- }
- return 0;
-}
-
-/*
- * NOTE: this interface is abandoned expect for write_mem_start DCS
- * other DCS are sent via generic pkg interfaces
- */
-static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- struct drm_device *dev = sender->dev;
- struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg;
- u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg;
- u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
- u32 cb_phy = sender->dbi_cb_phy;
- u32 index = 0;
- u8 *cb = (u8 *)sender->dbi_cb_addr;
- int i;
- int ret;
-
- if (!sender->dbi_pkg_support) {
- dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n");
- return -ENOTSUPP;
- }
-
- /*wait for DBI fifo empty*/
- wait_for_dbi_fifo_empty(sender);
-
- *(cb + (index++)) = dcs_pkg->cmd;
- if (dcs_pkg->param_num) {
- for (i = 0; i < dcs_pkg->param_num; i++)
- *(cb + (index++)) = *(dcs_pkg->param + i);
- }
-
- REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num));
- REG_WRITE(dbi_cmd_addr_reg,
- (cb_phy << CMD_MEM_ADDR_OFFSET)
- | (1 << 0)
- | ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0));
-
- ret = dbi_cmd_sent(sender);
- if (ret) {
- dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd);
- return -EAGAIN;
- }
- return 0;
-}
-
-static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- struct drm_device *dev = sender->dev;
- u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
- u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
- u32 gen_ctrl_val = 0;
- struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg;
-
- gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS;
- gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
- gen_ctrl_val |= pkg->pkg_type;
- gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS;
-
- if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
- /* wait for hs fifo empty */
- /* wait_for_hs_fifos_empty(sender); */
- /* Send pkg */
- REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
- } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
- /* wait_for_lp_fifos_empty(sender); */
- /* Send pkg*/
- REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
- } else {
- dev_err(dev->dev, "Unknown transmission type %d\n",
- pkg->transmission_type);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- struct drm_device *dev = sender->dev;
- u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
- u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg;
- u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
- u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg;
- u32 gen_ctrl_val = 0;
- u32 *dp;
- int i;
- struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg;
-
- dp = long_pkg->data;
-
- /*
- * Set up word count for long pkg
- * FIXME: double check word count field.
- * currently, using the byte counts of the payload as the word count.
- * ------------------------------------------------------------
- * | DI | WC | ECC| PAYLOAD |CHECKSUM|
- * ------------------------------------------------------------
- */
- gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS;
- gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
- gen_ctrl_val |= pkg->pkg_type;
-
- if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
- /* Wait for hs ctrl and data fifos to be empty */
- /* wait_for_hs_fifos_empty(sender); */
- for (i = 0; i < long_pkg->len; i++)
- REG_WRITE(hs_gen_data_reg, *(dp + i));
- REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
- } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
- /* wait_for_lp_fifos_empty(sender); */
- for (i = 0; i < long_pkg->len; i++)
- REG_WRITE(lp_gen_data_reg, *(dp + i));
- REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
- } else {
- dev_err(dev->dev, "Unknown transmission type %d\n",
- pkg->transmission_type);
- return -EINVAL;
- }
-
- return 0;
-
-}
-
-static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- return __send_short_pkg(sender, pkg);
-}
-
-static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- return __send_long_pkg(sender, pkg);
-}
-
-static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- return __send_short_pkg(sender, pkg);
-}
-
-static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- return __send_long_pkg(sender, pkg);
-}
-
-static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- u8 cmd;
- u8 *data;
-
- switch (pkg->pkg_type) {
- case MDFLD_DSI_PKG_DCS:
- cmd = pkg->pkg.dcs_pkg.cmd;
- break;
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
- cmd = pkg->pkg.short_pkg.cmd;
- break;
- case MDFLD_DSI_PKG_MCS_LONG_WRITE:
- data = (u8 *)pkg->pkg.long_pkg.data;
- cmd = *data;
- break;
- default:
- return 0;
- }
-
- /* This prevents other package sending while doing msleep */
- sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
-
- /* Check panel mode v.s. sending command */
- if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) &&
- cmd != exit_sleep_mode) {
- dev_err(sender->dev->dev,
- "sending 0x%x when panel sleep in\n", cmd);
- sender->status = MDFLD_DSI_PKG_SENDER_FREE;
- return -EINVAL;
- }
-
- /* Wait for 120 milliseconds in case exit_sleep_mode just be sent */
- if (cmd == DCS_ENTER_SLEEP_MODE) {
- /*TODO: replace it with msleep later*/
- mdelay(120);
- }
- return 0;
-}
-
-static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- u8 cmd;
- u8 *data;
-
- switch (pkg->pkg_type) {
- case MDFLD_DSI_PKG_DCS:
- cmd = pkg->pkg.dcs_pkg.cmd;
- break;
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
- cmd = pkg->pkg.short_pkg.cmd;
- break;
- case MDFLD_DSI_PKG_MCS_LONG_WRITE:
- data = (u8 *)pkg->pkg.long_pkg.data;
- cmd = *data;
- break;
- default:
- return 0;
- }
-
- /* Update panel status */
- if (cmd == DCS_ENTER_SLEEP_MODE) {
- sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
- /*TODO: replace it with msleep later*/
- mdelay(120);
- } else if (cmd == DCS_EXIT_SLEEP_MODE) {
- sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
- /*TODO: replace it with msleep later*/
- mdelay(120);
- } else if (unlikely(cmd == DCS_SOFT_RESET)) {
- /*TODO: replace it with msleep later*/
- mdelay(5);
- }
- sender->status = MDFLD_DSI_PKG_SENDER_FREE;
- return 0;
-
-}
-
-static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- int ret;
-
- if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
- dev_err(sender->dev->dev, "sender is busy\n");
- return -EAGAIN;
- }
-
- ret = send_pkg_prepare(sender, pkg);
- if (ret) {
- dev_err(sender->dev->dev, "send_pkg_prepare error\n");
- return ret;
- }
-
- switch (pkg->pkg_type) {
- case MDFLD_DSI_PKG_DCS:
- ret = send_dcs_pkg(sender, pkg);
- break;
- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0:
- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1:
- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2:
- case MDFLD_DSI_PKG_GEN_READ_0:
- case MDFLD_DSI_PKG_GEN_READ_1:
- case MDFLD_DSI_PKG_GEN_READ_2:
- ret = send_gen_short_pkg(sender, pkg);
- break;
- case MDFLD_DSI_PKG_GEN_LONG_WRITE:
- ret = send_gen_long_pkg(sender, pkg);
- break;
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
- case MDFLD_DSI_PKG_MCS_READ:
- ret = send_mcs_short_pkg(sender, pkg);
- break;
- case MDFLD_DSI_PKG_MCS_LONG_WRITE:
- ret = send_mcs_long_pkg(sender, pkg);
- break;
- default:
- dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n",
- pkg->pkg_type);
- ret = -EINVAL;
- }
- send_pkg_done(sender, pkg);
- return ret;
-}
-
-static int send_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- int err ;
-
- /* Handle DSI error */
- err = dsi_error_handler(sender);
- if (err) {
- dev_err(sender->dev->dev, "Error handling failed\n");
- err = -EAGAIN;
- goto send_pkg_err;
- }
-
- /* Send pkg */
- err = do_send_pkg(sender, pkg);
- if (err) {
- dev_err(sender->dev->dev, "sent pkg failed\n");
- err = -EAGAIN;
- goto send_pkg_err;
- }
-
- /* FIXME: should I query complete and fifo empty here? */
-send_pkg_err:
- return err;
-}
-
-static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked(
- struct mdfld_dsi_pkg_sender *sender)
-{
- struct mdfld_dsi_pkg *pkg;
-
- if (list_empty(&sender->free_list)) {
- dev_err(sender->dev->dev, "No free pkg left\n");
- return NULL;
- }
- pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry);
- /* Detach from free list */
- list_del_init(&pkg->entry);
- return pkg;
-}
-
-static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg)
-{
- memset(pkg, 0, sizeof(struct mdfld_dsi_pkg));
- INIT_LIST_HEAD(&pkg->entry);
- list_add_tail(&pkg->entry, &sender->free_list);
-}
-
-static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender,
- struct psb_gtt *pg, int pipe)
-{
- unsigned long phys;
- void *virt_addr = NULL;
-
- switch (pipe) {
- case 0:
- /* FIXME: Doesn't this collide with stolen space ? */
- phys = pg->gtt_phys_start - 0x1000;
- break;
- case 2:
- phys = pg->gtt_phys_start - 0x800;
- break;
- default:
- dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe);
- return -EINVAL;
- }
-
- virt_addr = ioremap_nocache(phys, 0x800);
- if (!virt_addr) {
- dev_err(sender->dev->dev, "Map DBI command buffer error\n");
- return -ENOMEM;
- }
- sender->dbi_cb_phy = phys;
- sender->dbi_cb_addr = virt_addr;
- return 0;
-}
-
-static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender)
-{
- if (sender && sender->dbi_cb_addr)
- iounmap(sender->dbi_cb_addr);
-}
-
-static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg,
- int delay)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
-
- if (!delay) {
- send_pkg(sender, pkg);
- pkg_sender_put_pkg_locked(sender, pkg);
- } else {
- /* Queue it */
- list_add_tail(&pkg->entry, &sender->pkg_list);
- }
- spin_unlock_irqrestore(&sender->lock, flags);
-}
-
-static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
-
- while (!list_empty(&sender->pkg_list)) {
- pkg = list_first_entry(&sender->pkg_list,
- struct mdfld_dsi_pkg, entry);
- send_pkg(sender, pkg);
- list_del_init(&pkg->entry);
- pkg_sender_put_pkg_locked(sender, pkg);
- }
-
- spin_unlock_irqrestore(&sender->lock, flags);
-}
-
-static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, u8 transmission, int delay)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
- pkg = pkg_sender_get_pkg_locked(sender);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No memory\n");
- return -ENOMEM;
- }
- pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE;
- pkg->transmission_type = transmission;
- pkg->pkg.long_pkg.data = data;
- pkg->pkg.long_pkg.len = len;
- INIT_LIST_HEAD(&pkg->entry);
-
- pkg_sender_queue_pkg(sender, pkg, delay);
- return 0;
-}
-
-static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u8 param, u8 param_num,
- u8 transmission,
- int delay)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
- pkg = pkg_sender_get_pkg_locked(sender);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No memory\n");
- return -ENOMEM;
- }
-
- if (param_num) {
- pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1;
- pkg->pkg.short_pkg.param = param;
- } else {
- pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0;
- pkg->pkg.short_pkg.param = 0;
- }
- pkg->transmission_type = transmission;
- pkg->pkg.short_pkg.cmd = cmd;
- INIT_LIST_HEAD(&pkg->entry);
-
- pkg_sender_queue_pkg(sender, pkg, delay);
- return 0;
-}
-
-static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num,
- u8 transmission,
- int delay)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
- pkg = pkg_sender_get_pkg_locked(sender);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No pkg memory\n");
- return -ENOMEM;
- }
-
- switch (param_num) {
- case 0:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0;
- pkg->pkg.short_pkg.cmd = 0;
- pkg->pkg.short_pkg.param = 0;
- break;
- case 1:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1;
- pkg->pkg.short_pkg.cmd = param0;
- pkg->pkg.short_pkg.param = 0;
- break;
- case 2:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2;
- pkg->pkg.short_pkg.cmd = param0;
- pkg->pkg.short_pkg.param = param1;
- break;
- }
-
- pkg->transmission_type = transmission;
- INIT_LIST_HEAD(&pkg->entry);
-
- pkg_sender_queue_pkg(sender, pkg, delay);
- return 0;
-}
-
-static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, u8 transmission, int delay)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
- pkg = pkg_sender_get_pkg_locked(sender);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No pkg memory\n");
- return -ENOMEM;
- }
-
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE;
- pkg->transmission_type = transmission;
- pkg->pkg.long_pkg.data = data;
- pkg->pkg.long_pkg.len = len;
-
- INIT_LIST_HEAD(&pkg->entry);
-
- pkg_sender_queue_pkg(sender, pkg, delay);
-
- return 0;
-}
-
-static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender,
- struct mdfld_dsi_pkg *pkg,
- u32 *data,
- u16 len)
-{
- unsigned long flags;
- struct drm_device *dev = sender->dev;
- int i;
- u32 gen_data_reg;
- int retry = MDFLD_DSI_READ_MAX_COUNT;
- u8 transmission = pkg->transmission_type;
-
- /*
- * do reading.
- * 0) send out generic read request
- * 1) polling read data avail interrupt
- * 2) read data
- */
- spin_lock_irqsave(&sender->lock, flags);
-
- REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29);
-
- if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29)))
- DRM_ERROR("Can NOT clean read data valid interrupt\n");
-
- /*send out read request*/
- send_pkg(sender, pkg);
-
- pkg_sender_put_pkg_locked(sender, pkg);
-
- /*polling read data avail interrupt*/
- while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) {
- udelay(100);
- retry--;
- }
-
- if (!retry) {
- spin_unlock_irqrestore(&sender->lock, flags);
- return -ETIMEDOUT;
- }
-
- REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29));
-
- /*read data*/
- if (transmission == MDFLD_DSI_HS_TRANSMISSION)
- gen_data_reg = sender->mipi_hs_gen_data_reg;
- else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
- gen_data_reg = sender->mipi_lp_gen_data_reg;
- else {
- DRM_ERROR("Unknown transmission");
- spin_unlock_irqrestore(&sender->lock, flags);
- return -EINVAL;
- }
-
- for (i=0; i<len; i++)
- *(data + i) = REG_READ(gen_data_reg);
-
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender,
- u8 param0,
- u8 param1,
- u8 param_num,
- u32 *data,
- u16 len,
- u8 transmission)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
-
- pkg = pkg_sender_get_pkg_locked(sender);
-
- spin_unlock_irqrestore(&sender->lock,flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No pkg memory\n");
- return -ENOMEM;
- }
-
- switch (param_num) {
- case 0:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0;
- pkg->pkg.short_pkg.cmd = 0;
- pkg->pkg.short_pkg.param = 0;
- break;
- case 1:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1;
- pkg->pkg.short_pkg.cmd = param0;
- pkg->pkg.short_pkg.param = 0;
- break;
- case 2:
- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2;
- pkg->pkg.short_pkg.cmd = param0;
- pkg->pkg.short_pkg.param = param1;
- break;
- }
-
- pkg->transmission_type = transmission;
-
- INIT_LIST_HEAD(&pkg->entry);
-
- return __read_panel_data(sender, pkg, data, len);
-}
-
-static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd,
- u32 *data,
- u16 len,
- u8 transmission)
-{
- struct mdfld_dsi_pkg *pkg;
- unsigned long flags;
-
- spin_lock_irqsave(&sender->lock, flags);
-
- pkg = pkg_sender_get_pkg_locked(sender);
-
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(sender->dev->dev, "No pkg memory\n");
- return -ENOMEM;
- }
-
- pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ;
- pkg->pkg.short_pkg.cmd = cmd;
- pkg->pkg.short_pkg.param = 0;
-
- pkg->transmission_type = transmission;
-
- INIT_LIST_HEAD(&pkg->entry);
-
- return __read_panel_data(sender, pkg, data, len);
-}
-
-void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct drm_device * dev = dsi_config->dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int lane_count = dsi_config->lane_count;
- u32 val = 0;
-
- /*un-ready device*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
- /*init dsi adapter before kicking off*/
- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
- /*TODO: figure out how to setup these registers*/
- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014);
- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
- REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
- /*enable all interrupts*/
- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
- /*max value: 20 clock cycles of txclkesc*/
- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
- /*min 21 txclkesc, max: ffffh*/
- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
- /*min: 7d0 max: 4e20*/
- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
- /*set up max return packet size*/
- REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset),
- MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
-
- /*set up func_prg*/
- val |= lane_count;
- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
- val |= DSI_DBI_COLOR_FORMAT_OPTION2;
- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- struct drm_device * dev = dsi_config->dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int lane_count = dsi_config->lane_count;
- struct mdfld_dsi_dpi_timing dpi_timing;
- struct drm_display_mode * mode = dsi_config->mode;
- u32 val = 0;
-
- /*un-ready device*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
- /*init dsi adapter before kicking off*/
- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
- /*enable all interrupts*/
- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
-
- /*set up func_prg*/
- val |= lane_count;
- val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
-
- switch(dsi_config->bpp) {
- case 16:
- val |= DSI_DPI_COLOR_FORMAT_RGB565;
- break;
- case 18:
- val |= DSI_DPI_COLOR_FORMAT_RGB666;
- break;
- case 24:
- val |= DSI_DPI_COLOR_FORMAT_RGB888;
- break;
- default:
- DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
- }
-
- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),
- (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
-
- /*max value: 20 clock cycles of txclkesc*/
- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
-
- /*min 21 txclkesc, max: ffffh*/
- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
-
- REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
-
- /*set DPI timing registers*/
- mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
-
- REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-
- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
-
- /*min: 7d0 max: 4e20*/
- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
-
- /*set up video mode*/
- val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
- REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
-
- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
-
- /*TODO: figure out how to setup these registers*/
- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-
- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
-
- /*set device ready*/
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
-{
- if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
- DRM_ERROR("Invalid parameters\n");
- return;
- }
-
- if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
- dsi_controller_dpi_init(dsi_config, pipe);
- else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
- dsi_controller_dbi_init(dsi_config, pipe);
- else
- DRM_ERROR("Bad DSI encoder type\n");
-}
-
-void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
-{
- process_pkg_list(sender);
-}
-
-int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender,
- u8 dcs, u8 *param, u32 param_num, u8 data_src,
- int delay)
-{
- struct mdfld_dsi_pkg *pkg;
- u32 cb_phy = sender->dbi_cb_phy;
- struct drm_device *dev = sender->dev;
- u32 index = 0;
- u8 *cb = (u8 *)sender->dbi_cb_addr;
- unsigned long flags;
- int retry;
- u8 *dst = NULL;
- u32 len;
-
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- if (!sender->dbi_pkg_support) {
- dev_err(dev->dev, "No DBI pkg sending on this sender\n");
- return -ENOTSUPP;
- }
-
- if (param_num > MDFLD_MAX_DCS_PARAM) {
- dev_err(dev->dev, "Sender only supports up to %d DCS params\n",
- MDFLD_MAX_DCS_PARAM);
- return -EINVAL;
- }
-
- /*
- * If dcs is write_mem_start, send it directly using DSI adapter
- * interface
- */
- if (dcs == DCS_WRITE_MEM_START) {
- if (!spin_trylock(&sender->lock))
- return -EAGAIN;
-
- /*
- * query whether DBI FIFO is empty,
- * if not wait it becoming empty
- */
- retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
- while (retry &&
- !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) {
- udelay(500);
- retry--;
- }
-
- /* If DBI FIFO timeout, drop this frame */
- if (!retry) {
- spin_unlock(&sender->lock);
- return 0;
- }
-
- *(cb + (index++)) = write_mem_start;
-
- REG_WRITE(sender->mipi_cmd_len_reg, 1);
- REG_WRITE(sender->mipi_cmd_addr_reg,
- cb_phy | (1 << 0) | (1 << 1));
-
- retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
- while (retry &&
- (REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) {
- udelay(1);
- retry--;
- }
-
- spin_unlock(&sender->lock);
- return 0;
- }
-
- /* Get a free pkg */
- spin_lock_irqsave(&sender->lock, flags);
- pkg = pkg_sender_get_pkg_locked(sender);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- if (!pkg) {
- dev_err(dev->dev, "No packages memory\n");
- return -ENOMEM;
- }
-
- dst = pkg->pkg.dcs_pkg.param;
- memcpy(dst, param, param_num);
-
- pkg->pkg_type = MDFLD_DSI_PKG_DCS;
- pkg->transmission_type = MDFLD_DSI_DCS;
- pkg->pkg.dcs_pkg.cmd = dcs;
- pkg->pkg.dcs_pkg.param_num = param_num;
- pkg->pkg.dcs_pkg.data_src = data_src;
-
- INIT_LIST_HEAD(&pkg->entry);
-
- if (param_num == 0)
- return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay);
- else if (param_num == 1)
- return mdfld_dsi_send_mcs_short_hs(sender, dcs,
- param[0], 1, delay);
- else if (param_num > 1) {
- len = (param_num + 1) / 4;
- if ((param_num + 1) % 4)
- len++;
- return mdfld_dsi_send_mcs_long_hs(sender,
- (u32 *)&pkg->pkg.dcs_pkg, len, delay);
- }
- return 0;
-}
-
-int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u8 param, u8 param_num, int delay)
-{
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
- MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u8 param, u8 param_num, int delay)
-{
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
- MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
- u32 *data,
- u32 len,
- int delay)
-{
- if (!sender || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
- return mdfld_dsi_send_mcs_long(sender, data, len,
- MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
- u32 *data,
- u32 len,
- int delay)
-{
- if (!sender || !data || !len) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_mcs_long(sender, data, len,
- MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, int delay)
-{
- if (!sender) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
- MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, int delay)
-{
- if (!sender || param_num < 0 || param_num > 2) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
- MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
- u32 *data,
- u32 len,
- int delay)
-{
- if (!sender || !data || !len) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_gen_long(sender, data, len,
- MDFLD_DSI_HS_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
- u32 *data,
- u32 len,
- int delay)
-{
- if (!sender || !data || !len) {
- WARN_ON(1);
- return -EINVAL;
- }
- return mdfld_dsi_send_gen_long(sender, data, len,
- MDFLD_DSI_LP_TRANSMISSION, delay);
-}
-
-int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 param0,
- u8 param1,
- u8 param_num,
- u32 *data,
- u16 len)
-{
- if (!sender || !data || param_num < 0 || param_num > 2
- || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_read_gen(sender, param0, param1, param_num,
- data, len, MDFLD_DSI_HS_TRANSMISSION);
-
-}
-
-int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 param0,
- u8 param1,
- u8 param_num,
- u32 *data,
- u16 len)
-{
- if (!sender || !data || param_num < 0 || param_num > 2
- || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_read_gen(sender, param0, param1, param_num,
- data, len, MDFLD_DSI_LP_TRANSMISSION);
-}
-
-int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd,
- u32 *data,
- u16 len)
-{
- if (!sender || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_read_mcs(sender, cmd, data, len,
- MDFLD_DSI_HS_TRANSMISSION);
-}
-
-int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd,
- u32 *data,
- u16 len)
-{
- if (!sender || !data || !len) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- return mdfld_dsi_read_mcs(sender, cmd, data, len,
- MDFLD_DSI_LP_TRANSMISSION);
-}
-
-int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
- int pipe)
-{
- int ret;
- struct mdfld_dsi_pkg_sender *pkg_sender;
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_get_config(dsi_connector);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = &dev_priv->gtt;
- int i;
- struct mdfld_dsi_pkg *pkg, *tmp;
- u32 mipi_val = 0;
-
- if (!dsi_connector) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- pkg_sender = dsi_connector->pkg_sender;
-
- if (!pkg_sender || IS_ERR(pkg_sender)) {
- pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
- GFP_KERNEL);
- if (!pkg_sender) {
- dev_err(dev->dev, "Create DSI pkg sender failed\n");
- return -ENOMEM;
- }
-
- dsi_connector->pkg_sender = (void *)pkg_sender;
- }
-
- pkg_sender->dev = dev;
- pkg_sender->dsi_connector = dsi_connector;
- pkg_sender->pipe = pipe;
- pkg_sender->pkg_num = 0;
- pkg_sender->panel_mode = 0;
- pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
-
- /* Init dbi command buffer*/
-
- if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
- pkg_sender->dbi_pkg_support = 1;
- ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
- if (ret) {
- dev_err(dev->dev, "DBI command buffer map failed\n");
- goto mapping_err;
- }
- }
-
- /* Init regs */
- if (pipe == 0) {
- pkg_sender->dpll_reg = MRST_DPLL_A;
- pkg_sender->dspcntr_reg = DSPACNTR;
- pkg_sender->pipeconf_reg = PIPEACONF;
- pkg_sender->dsplinoff_reg = DSPALINOFF;
- pkg_sender->dspsurf_reg = DSPASURF;
- pkg_sender->pipestat_reg = PIPEASTAT;
-
- pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG;
- pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG;
- pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG;
- pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG;
- pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
- pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
- pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG;
- pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG;
- pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG;
- pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG;
- } else if (pipe == 2) {
- pkg_sender->dpll_reg = MRST_DPLL_A;
- pkg_sender->dspcntr_reg = DSPCCNTR;
- pkg_sender->pipeconf_reg = PIPECCONF;
- pkg_sender->dsplinoff_reg = DSPCLINOFF;
- pkg_sender->dspsurf_reg = DSPCSURF;
- pkg_sender->pipestat_reg = PIPECSTAT;
-
- pkg_sender->mipi_intr_stat_reg =
- MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_lp_gen_data_reg =
- MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_hs_gen_data_reg =
- MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_lp_gen_ctrl_reg =
- MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_hs_gen_ctrl_reg =
- MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_gen_fifo_stat_reg =
- MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_data_addr_reg =
- MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_data_len_reg =
- MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_cmd_addr_reg =
- MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET;
- pkg_sender->mipi_cmd_len_reg =
- MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET;
- }
-
- /* Init pkg list */
- INIT_LIST_HEAD(&pkg_sender->pkg_list);
- INIT_LIST_HEAD(&pkg_sender->free_list);
-
- spin_lock_init(&pkg_sender->lock);
-
- /* Allocate free pkg pool */
- for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) {
- pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL);
- if (!pkg) {
- dev_err(dev->dev, "Out of memory allocating pkg pool");
- ret = -ENOMEM;
- goto pkg_alloc_err;
- }
- INIT_LIST_HEAD(&pkg->entry);
- list_add_tail(&pkg->entry, &pkg_sender->free_list);
- }
-
- /*
- * For video mode, don't enable DPI timing output here,
- * will init the DPI timing output during mode setting.
- */
- if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
- mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
- else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
- mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
- | TE_TRIGGER_GPIO_PIN;
- else
- DRM_ERROR("Bad DSI encoder type\n");
-
- if (pipe == 0) {
- mipi_val |= 0x2;
- REG_WRITE(MIPI, mipi_val);
- REG_READ(MIPI);
- } else if (pipe == 2) {
- REG_WRITE(MIPI_C, mipi_val);
- REG_READ(MIPI_C);
- }
-
- /*do dsi controller init*/
- dsi_controller_init(dsi_config, pipe);
-
- return 0;
-
-pkg_alloc_err:
- list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) {
- list_del(&pkg->entry);
- kfree(pkg);
- }
-
- /* Free mapped command buffer */
- mdfld_dbi_cb_destroy(pkg_sender);
-mapping_err:
- kfree(pkg_sender);
- dsi_connector->pkg_sender = NULL;
- return ret;
-}
-
-void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
-{
- struct mdfld_dsi_pkg *pkg, *tmp;
-
- if (!sender || IS_ERR(sender))
- return;
-
- /* Free pkg pool */
- list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) {
- list_del(&pkg->entry);
- kfree(pkg);
- }
- /* Free pkg list */
- list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) {
- list_del(&pkg->entry);
- kfree(pkg);
- }
- mdfld_dbi_cb_destroy(sender); /* free mapped command buffer */
- kfree(sender);
-}
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
deleted file mode 100644
index f24abc700684..000000000000
--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jackie Li<yaodong.li@intel.com>
- */
-#ifndef __MDFLD_DSI_PKG_SENDER_H__
-#define __MDFLD_DSI_PKG_SENDER_H__
-
-#include <linux/kthread.h>
-
-#define MDFLD_MAX_DCS_PARAM 8
-#define MDFLD_MAX_PKG_NUM 2048
-
-enum {
- MDFLD_DSI_PKG_DCS,
- MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03,
- MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13,
- MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23,
- MDFLD_DSI_PKG_GEN_READ_0 = 0x04,
- MDFLD_DSI_PKG_GEN_READ_1 = 0x14,
- MDFLD_DSI_PKG_GEN_READ_2 = 0x24,
- MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29,
- MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05,
- MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15,
- MDFLD_DSI_PKG_MCS_READ = 0x06,
- MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39,
-};
-
-enum {
- MDFLD_DSI_LP_TRANSMISSION,
- MDFLD_DSI_HS_TRANSMISSION,
- MDFLD_DSI_DCS,
-};
-
-enum {
- MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
-};
-
-enum {
- MDFLD_DSI_PKG_SENDER_FREE = 0x0,
- MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
-};
-
-enum {
- MDFLD_DSI_SEND_PACKAGE,
- MDFLD_DSI_QUEUE_PACKAGE,
-};
-
-struct mdfld_dsi_gen_short_pkg {
- u8 cmd;
- u8 param;
-};
-
-struct mdfld_dsi_gen_long_pkg {
- u32 *data;
- u32 len;
-};
-
-struct mdfld_dsi_dcs_pkg {
- u8 cmd;
- u8 param[MDFLD_MAX_DCS_PARAM];
- u32 param_num;
- u8 data_src;
-};
-
-struct mdfld_dsi_pkg {
- u8 pkg_type;
- u8 transmission_type;
-
- union {
- struct mdfld_dsi_gen_short_pkg short_pkg;
- struct mdfld_dsi_gen_long_pkg long_pkg;
- struct mdfld_dsi_dcs_pkg dcs_pkg;
- } pkg;
-
- struct list_head entry;
-};
-
-struct mdfld_dsi_pkg_sender {
- struct drm_device *dev;
- struct mdfld_dsi_connector *dsi_connector;
- u32 status;
-
- u32 panel_mode;
-
- int pipe;
-
- spinlock_t lock;
- struct list_head pkg_list;
- struct list_head free_list;
-
- u32 pkg_num;
-
- int dbi_pkg_support;
-
- u32 dbi_cb_phy;
- void *dbi_cb_addr;
-
- /* Registers */
- u32 dpll_reg;
- u32 dspcntr_reg;
- u32 pipeconf_reg;
- u32 pipestat_reg;
- u32 dsplinoff_reg;
- u32 dspsurf_reg;
-
- u32 mipi_intr_stat_reg;
- u32 mipi_lp_gen_data_reg;
- u32 mipi_hs_gen_data_reg;
- u32 mipi_lp_gen_ctrl_reg;
- u32 mipi_hs_gen_ctrl_reg;
- u32 mipi_gen_fifo_stat_reg;
- u32 mipi_data_addr_reg;
- u32 mipi_data_len_reg;
- u32 mipi_cmd_addr_reg;
- u32 mipi_cmd_len_reg;
-};
-
-/* DCS definitions */
-#define DCS_SOFT_RESET 0x01
-#define DCS_ENTER_SLEEP_MODE 0x10
-#define DCS_EXIT_SLEEP_MODE 0x11
-#define DCS_SET_DISPLAY_OFF 0x28
-#define DCS_SET_DISPLAY_ON 0x29
-#define DCS_SET_COLUMN_ADDRESS 0x2a
-#define DCS_SET_PAGE_ADDRESS 0x2b
-#define DCS_WRITE_MEM_START 0x2c
-#define DCS_SET_TEAR_OFF 0x34
-#define DCS_SET_TEAR_ON 0x35
-
-extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
- int pipe);
-extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
-extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs,
- u8 *param, u32 param_num, u8 data_src, int delay);
-extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u8 param, u8 param_num, int delay);
-extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u8 param, u8 param_num, int delay);
-extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, int delay);
-extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, int delay);
-extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, int delay);
-extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
- u32 *data, u32 len, int delay);
-
-extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
-extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
-extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u32 *data, u16 len);
-extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
- u8 cmd, u32 *data, u16 len);
-
-extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender);
-
-#endif /* __MDFLD_DSI_PKG_SENDER_H__ */
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
deleted file mode 100644
index 0b37b7b6b02a..000000000000
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ /dev/null
@@ -1,1404 +0,0 @@
-/*
- * Copyright © 2006-2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include "framebuffer.h"
-#include "psb_intel_display.h"
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_dbi_dpu.h"
-
-#include <linux/pm_runtime.h>
-
-#ifdef MIN
-#undef MIN
-#endif
-
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-
-/* Hardcoded currently */
-static int ksel = KSEL_CRYSTAL_19;
-
-extern void mdfld_save_display(struct drm_device *dev);
-extern bool gbgfxsuspended;
-
-struct psb_intel_range_t {
- int min, max;
-};
-
-struct mdfld_limit_t {
- struct psb_intel_range_t dot, m, p1;
-};
-
-struct mdfld_intel_clock_t {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
-};
-
-
-
-#define COUNT_MAX 0x10000000
-
-void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
-{
- int count, temp;
- u32 pipeconf_reg = PIPEACONF;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- pipeconf_reg = PIPEBCONF;
- break;
- case 2:
- pipeconf_reg = PIPECCONF;
- break;
- default:
- DRM_ERROR("Illegal Pipe Number. \n");
- return;
- }
-
- /* FIXME JLIU7_PO */
- psb_intel_wait_for_vblank(dev);
- return;
-
- /* Wait for for the pipe disable to take effect. */
- for (count = 0; count < COUNT_MAX; count++) {
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_PIPE_STATE) == 0)
- break;
- }
-}
-
-void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
-{
- int count, temp;
- u32 pipeconf_reg = PIPEACONF;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- pipeconf_reg = PIPEBCONF;
- break;
- case 2:
- pipeconf_reg = PIPECCONF;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- /* FIXME JLIU7_PO */
- psb_intel_wait_for_vblank(dev);
- return;
-
- /* Wait for for the pipe enable to take effect. */
- for (count = 0; count < COUNT_MAX; count++) {
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_PIPE_STATE) == 1)
- break;
- }
-}
-
-
-static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t control = CURACNTR;
- uint32_t base = CURABASE;
- uint32_t temp;
- size_t addr = 0;
- struct gtt_range *gt;
- struct drm_gem_object *obj;
- int ret;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- control = CURBCNTR;
- base = CURBBASE;
- break;
- case 2:
- control = CURCCNTR;
- base = CURCBASE;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number. \n");
- return -EINVAL;
- }
-
-#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
- if (pipe != 0)
- return 0;
-#endif
- /* if we want to turn of the cursor ignore width and height */
- if (!handle) {
- dev_dbg(dev->dev, "cursor off\n");
- /* turn off the cursor */
- temp = 0;
- temp |= CURSOR_MODE_DISABLE;
-
- if (gma_power_begin(dev, true)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, 0);
- gma_power_end(dev);
- }
- /* Unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = NULL;
- }
- return 0;
- }
-
- /* Currently we only support 64x64 cursors */
- if (width != 64 || height != 64) {
- DRM_ERROR("we currently only support 64x64 cursors\n");
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
-
- if (obj->size < width * height * 4) {
- dev_dbg(dev->dev, "buffer is to small\n");
- return -ENOMEM;
- }
-
- gt = container_of(obj, struct gtt_range, gem);
-
- /* Pin the memory into the GTT */
- ret = psb_gtt_pin(gt);
- if (ret) {
- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
- return ret;
- }
-
-
- addr = gt->offset; /* Or resource.start ??? */
-
- psb_intel_crtc->cursor_addr = addr;
-
- temp = 0;
- /* set the pipe for the cursor */
- temp |= (pipe << 28);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
- if (gma_power_begin(dev, true)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
- /* unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = obj;
- }
- return 0;
-}
-
-static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
- struct psb_drm_dpu_rect rect;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t pos = CURAPOS;
- uint32_t base = CURABASE;
- uint32_t temp = 0;
- uint32_t addr;
-
- switch (pipe) {
- case 0:
- if (dpu_info) {
- rect.x = x;
- rect.y = y;
-
- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
- mdfld_dpu_exit_dsr(dev);
- } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0);
- break;
- case 1:
- pos = CURBPOS;
- base = CURBBASE;
- break;
- case 2:
- if (dpu_info) {
- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
- mdfld_dpu_exit_dsr(dev);
- } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2);
- pos = CURCPOS;
- base = CURCBASE;
- break;
- default:
- DRM_ERROR("Illegal Pipe Number. \n");
- return -EINVAL;
- }
-
-#if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */
- if (pipe != 0)
- return 0;
-#endif
- if (x < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
- x = -x;
- }
- if (y < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
- y = -y;
- }
-
- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
- addr = psb_intel_crtc->cursor_addr;
-
- if (gma_power_begin(dev, true)) {
- REG_WRITE(pos, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
-
- return 0;
-}
-
-const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
- .cursor_set = mdfld_intel_crtc_cursor_set,
- .cursor_move = mdfld_intel_crtc_cursor_move,
- .gamma_set = psb_intel_crtc_gamma_set,
- .set_config = drm_crtc_helper_set_config,
- .destroy = psb_intel_crtc_destroy,
-};
-
-static struct drm_device globle_dev;
-
-void mdfld__intel_plane_set_alpha(int enable)
-{
- struct drm_device *dev = &globle_dev;
- int dspcntr_reg = DSPACNTR;
- u32 dspcntr;
-
- dspcntr = REG_READ(dspcntr_reg);
-
- if (enable) {
- dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
- dspcntr |= DISPPLANE_32BPP;
- } else {
- dspcntr &= ~DISPPLANE_32BPP;
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- }
-
- REG_WRITE(dspcntr_reg, dspcntr);
-}
-
-int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_i915_master_private *master_priv; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- unsigned long start, offset;
- int dsplinoff = DSPALINOFF;
- int dspsurf = DSPASURF;
- int dspstride = DSPASTRIDE;
- int dspcntr_reg = DSPACNTR;
- u32 dspcntr;
- int ret = 0;
-
- memcpy(&globle_dev, dev, sizeof(struct drm_device));
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_err(dev->dev, "No FB bound\n");
- goto psb_intel_pipe_cleaner;
- }
-
- switch (pipe) {
- case 0:
- dsplinoff = DSPALINOFF;
- break;
- case 1:
- dsplinoff = DSPBLINOFF;
- dspsurf = DSPBSURF;
- dspstride = DSPBSTRIDE;
- dspcntr_reg = DSPBCNTR;
- break;
- case 2:
- dsplinoff = DSPCLINOFF;
- dspsurf = DSPCSURF;
- dspstride = DSPCSTRIDE;
- dspcntr_reg = DSPCCNTR;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return -EINVAL;
- }
-
- ret = psb_gtt_pin(psbfb->gtt);
- if (ret < 0)
- goto psb_intel_pipe_set_base_exit;
-
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(dspstride, crtc->fb->pitches[0]);
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- goto psb_intel_pipe_set_base_exit;
- }
- REG_WRITE(dspcntr_reg, dspcntr);
-
- dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
- start, offset, x, y);
-
- REG_WRITE(dsplinoff, offset);
- REG_READ(dsplinoff);
- REG_WRITE(dspsurf, start);
- REG_READ(dspsurf);
-
-psb_intel_pipe_cleaner:
- /* If there was a previous display we can now unpin it */
- if (old_fb)
- psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
-}
-
-/**
- * Disable the pipe, plane and pll.
- *
- */
-void mdfld_disable_crtc (struct drm_device *dev, int pipe)
-{
- int dpll_reg = MRST_DPLL_A;
- int dspcntr_reg = DSPACNTR;
- int dspbase_reg = MRST_DSPABASE;
- int pipeconf_reg = PIPEACONF;
- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
- u32 temp;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- dpll_reg = MDFLD_DPLL_B;
- dspcntr_reg = DSPBCNTR;
- dspbase_reg = DSPBSURF;
- pipeconf_reg = PIPEBCONF;
- break;
- case 2:
- dpll_reg = MRST_DPLL_A;
- dspcntr_reg = DSPCCNTR;
- dspbase_reg = MDFLD_DSPCBASE;
- pipeconf_reg = PIPECCONF;
- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number. \n");
- return;
- }
-
- if (pipe != 1)
- mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
- /* Disable display plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(dspcntr_reg,
- temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
- }
-
- /* FIXME_JLIU7 MDFLD_PO revisit */
- /* Wait for vblank for the disable to take effect */
-/* MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); */
-
- /* Next, disable display pipes */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- temp &= ~PIPEACONF_ENABLE;
- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
- REG_WRITE(pipeconf_reg, temp);
- REG_READ(pipeconf_reg);
-
- /* Wait for for the pipe disable to take effect. */
- mdfldWaitForPipeDisable(dev, pipe);
- }
-
- temp = REG_READ(dpll_reg);
- if (temp & DPLL_VCO_ENABLE) {
- if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
- || (pipe == 1)){
- temp &= ~(DPLL_VCO_ENABLE);
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* Wait for the clocks to turn off. */
- /* FIXME_MDFLD PO may need more delay */
- udelay(500);
-
- if (!(temp & MDFLD_PWR_GATE_EN)) {
- /* gating power of DPLL */
- REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(5000);
- }
- }
- }
-
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- int dpll_reg = MRST_DPLL_A;
- int dspcntr_reg = DSPACNTR;
- int dspbase_reg = MRST_DSPABASE;
- int pipeconf_reg = PIPEACONF;
- u32 pipestat_reg = PIPEASTAT;
- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
- u32 pipeconf = dev_priv->pipeconf;
- u32 dspcntr = dev_priv->dspcntr;
- u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG;
- u32 temp;
- bool enabled;
- int timeout = 0;
-
- if (!gma_power_begin(dev, true))
- return;
-
- /* Ignore if system is already in DSR and in suspended state. */
- if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){
- if(dev_priv->rpm_enabled && pipe == 1){
- // dev_priv->is_mipi_on = false;
- pm_request_idle(&dev->pdev->dev);
- }
- return;
- }else if(mode == 0) {
- //do not need to set gbdispstatus=true in crtc.
- //this will be set in encoder such as mdfld_dsi_dbi_dpms
- //gbdispstatus = true;
- }
-
-/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
-/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- dpll_reg = DPLL_B;
- dspcntr_reg = DSPBCNTR;
- dspbase_reg = MRST_DSPBBASE;
- pipeconf_reg = PIPEBCONF;
- pipeconf = dev_priv->pipeconf1;
- dspcntr = dev_priv->dspcntr1;
- dpll_reg = MDFLD_DPLL_B;
- break;
- case 2:
- dpll_reg = MRST_DPLL_A;
- dspcntr_reg = DSPCCNTR;
- dspbase_reg = MDFLD_DSPCBASE;
- pipeconf_reg = PIPECCONF;
- pipestat_reg = PIPECSTAT;
- pipeconf = dev_priv->pipeconf2;
- dspcntr = dev_priv->dspcntr2;
- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
- mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- /* Enable the DPLL */
- temp = REG_READ(dpll_reg);
-
- if ((temp & DPLL_VCO_ENABLE) == 0) {
- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
- if (temp & MDFLD_PWR_GATE_EN) {
- temp &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(dpll_reg, temp);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
-
- /**
- * wait for DSI PLL to lock
- * NOTE: only need to poll status of pipe 0 and pipe 1,
- * since both MIPI pipes share the same PLL.
- */
- while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout ++;
- }
- }
-
- /* Enable the plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
- REG_WRITE(dspcntr_reg,
- temp | DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- }
-
- /* Enable the pipe */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) == 0) {
- REG_WRITE(pipeconf_reg, pipeconf);
-
- /* Wait for for the pipe enable to take effect. */
- mdfldWaitForPipeEnable(dev, pipe);
- }
-
- /*workaround for sighting 3741701 Random X blank display*/
- /*perform w/a in video mode only on pipe A or C*/
- if ((pipe == 0 || pipe == 2) &&
- (mdfld_panel_dpi(dev) == true)) {
- REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
- msleep(100);
- if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
- printk(KERN_ALERT "OK");
- } else {
- printk(KERN_ALERT "STUCK!!!!");
- /*shutdown controller*/
- temp = REG_READ(dspcntr_reg);
- REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
- REG_WRITE(0xb048, 1);
- msleep(100);
- temp = REG_READ(pipeconf_reg);
- temp &= ~PIPEACONF_ENABLE;
- REG_WRITE(pipeconf_reg, temp);
- msleep(100); /*wait for pipe disable*/
- /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
- printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
- REG_WRITE(mipi_enable_reg, 0);
- msleep(100);
- printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
- printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
- REG_WRITE(0xb004, REG_READ(0xb004));
- /* try to bring the controller back up again*/
- REG_WRITE(mipi_enable_reg, 1);
- temp = REG_READ(dspcntr_reg);
- REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
- REG_WRITE(0xb048, 2);
- msleep(100);
- temp = REG_READ(pipeconf_reg);
- temp |= PIPEACONF_ENABLE;
- REG_WRITE(pipeconf_reg, temp);
- }
- }
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
- if (pipe != 1)
- mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Disable display plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(dspcntr_reg,
- temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
- }
-
- /* FIXME_JLIU7 MDFLD_PO revisit */
- /* Wait for vblank for the disable to take effect */
-// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev);
-
- /* Next, disable display pipes */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- temp &= ~PIPEACONF_ENABLE;
- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
- REG_WRITE(pipeconf_reg, temp);
-// REG_WRITE(pipeconf_reg, 0);
- REG_READ(pipeconf_reg);
-
- /* Wait for for the pipe disable to take effect. */
- mdfldWaitForPipeDisable(dev, pipe);
- }
-
- temp = REG_READ(dpll_reg);
- if (temp & DPLL_VCO_ENABLE) {
- if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
- || (pipe == 1)){
- temp &= ~(DPLL_VCO_ENABLE);
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* Wait for the clocks to turn off. */
- /* FIXME_MDFLD PO may need more delay */
- udelay(500);
-#if 0 /* MDFLD_PO_JLIU7 */
- if (!(temp & MDFLD_PWR_GATE_EN)) {
- /* gating power of DPLL */
- REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(5000);
- }
-#endif /* MDFLD_PO_JLIU7 */
- }
- }
- break;
- }
-
- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
-#if 0 /* JB: Add vblank support later */
- if (enabled)
- dev_priv->vblank_pipe |= (1 << pipe);
- else
- dev_priv->vblank_pipe &= ~(1 << pipe);
-#endif
-
- gma_power_end(dev);
-}
-
-
-#define MDFLD_LIMT_DPLL_19 0
-#define MDFLD_LIMT_DPLL_25 1
-#define MDFLD_LIMT_DPLL_83 2
-#define MDFLD_LIMT_DPLL_100 3
-#define MDFLD_LIMT_DSIPLL_19 4
-#define MDFLD_LIMT_DSIPLL_25 5
-#define MDFLD_LIMT_DSIPLL_83 6
-#define MDFLD_LIMT_DSIPLL_100 7
-
-#define MDFLD_DOT_MIN 19750 /* FIXME_MDFLD JLIU7 need to find out min & max for MDFLD */
-#define MDFLD_DOT_MAX 120000
-#define MDFLD_DPLL_M_MIN_19 113
-#define MDFLD_DPLL_M_MAX_19 155
-#define MDFLD_DPLL_P1_MIN_19 2
-#define MDFLD_DPLL_P1_MAX_19 10
-#define MDFLD_DPLL_M_MIN_25 101
-#define MDFLD_DPLL_M_MAX_25 130
-#define MDFLD_DPLL_P1_MIN_25 2
-#define MDFLD_DPLL_P1_MAX_25 10
-#define MDFLD_DPLL_M_MIN_83 64
-#define MDFLD_DPLL_M_MAX_83 64
-#define MDFLD_DPLL_P1_MIN_83 2
-#define MDFLD_DPLL_P1_MAX_83 2
-#define MDFLD_DPLL_M_MIN_100 64
-#define MDFLD_DPLL_M_MAX_100 64
-#define MDFLD_DPLL_P1_MIN_100 2
-#define MDFLD_DPLL_P1_MAX_100 2
-#define MDFLD_DSIPLL_M_MIN_19 131
-#define MDFLD_DSIPLL_M_MAX_19 175
-#define MDFLD_DSIPLL_P1_MIN_19 3
-#define MDFLD_DSIPLL_P1_MAX_19 8
-#define MDFLD_DSIPLL_M_MIN_25 97
-#define MDFLD_DSIPLL_M_MAX_25 140
-#define MDFLD_DSIPLL_P1_MIN_25 3
-#define MDFLD_DSIPLL_P1_MAX_25 9
-#define MDFLD_DSIPLL_M_MIN_83 33
-#define MDFLD_DSIPLL_M_MAX_83 92
-#define MDFLD_DSIPLL_P1_MIN_83 2
-#define MDFLD_DSIPLL_P1_MAX_83 3
-#define MDFLD_DSIPLL_M_MIN_100 97
-#define MDFLD_DSIPLL_M_MAX_100 140
-#define MDFLD_DSIPLL_P1_MIN_100 3
-#define MDFLD_DSIPLL_P1_MAX_100 9
-
-static const struct mdfld_limit_t mdfld_limits[] = {
- { /* MDFLD_LIMT_DPLL_19 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
- },
- { /* MDFLD_LIMT_DPLL_25 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
- },
- { /* MDFLD_LIMT_DPLL_83 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
- },
- { /* MDFLD_LIMT_DPLL_100 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
- },
- { /* MDFLD_LIMT_DSIPLL_19 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
- },
- { /* MDFLD_LIMT_DSIPLL_25 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
- },
- { /* MDFLD_LIMT_DSIPLL_83 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
- },
- { /* MDFLD_LIMT_DSIPLL_100 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
- },
-};
-
-#define MDFLD_M_MIN 21
-#define MDFLD_M_MAX 180
-static const u32 mdfld_m_converts[] = {
-/* M configuration table from 9-bit LFSR table */
- 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
- 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
- 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
- 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
- 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
- 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
- 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
- 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
- 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
- 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
- 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
- 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
- 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
- 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
- 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
- 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
-};
-
-static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc)
-{
- const struct mdfld_limit_t *limit = NULL;
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
- else if (ksel == KSEL_BYPASS_25)
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
- else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
- } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
- else if (ksel == KSEL_BYPASS_25)
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
- else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
- } else {
- limit = NULL;
- dev_err(dev->dev, "mdfld_limit Wrong display type.\n");
- }
-
- return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock)
-{
- clock->dot = (refclk * clock->m) / clock->p1;
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given refclk,
- * or FALSE. Divisor values are the actual divisors for
- */
-static bool
-mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
- struct mdfld_intel_clock_t *best_clock)
-{
- struct mdfld_intel_clock_t clock;
- const struct mdfld_limit_t *limit = mdfld_limit(crtc);
- int err = target;
-
- memset(best_clock, 0, sizeof(*best_clock));
-
- for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
- for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- mdfld_clock(refclk, &clock);
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- return err != target;
-}
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int mdfld_panel_fitter_pipe(struct drm_device *dev)
-{
- u32 pfit_control;
-
- pfit_control = REG_READ(PFIT_CONTROL);
-
- /* See if the panel fitter is in use */
- if ((pfit_control & PFIT_ENABLE) == 0)
- return -1;
- return (pfit_control >> 29) & 3;
-}
-
-static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = psb_intel_crtc->pipe;
- int fp_reg = MRST_FPA0;
- int dpll_reg = MRST_DPLL_A;
- int dspcntr_reg = DSPACNTR;
- int pipeconf_reg = PIPEACONF;
- int htot_reg = HTOTAL_A;
- int hblank_reg = HBLANK_A;
- int hsync_reg = HSYNC_A;
- int vtot_reg = VTOTAL_A;
- int vblank_reg = VBLANK_A;
- int vsync_reg = VSYNC_A;
- int dspsize_reg = DSPASIZE;
- int dsppos_reg = DSPAPOS;
- int pipesrc_reg = PIPEASRC;
- u32 *pipeconf = &dev_priv->pipeconf;
- u32 *dspcntr = &dev_priv->dspcntr;
- int refclk = 0;
- int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
- struct mdfld_intel_clock_t clock;
- bool ok;
- u32 dpll = 0, fp = 0;
- bool is_crt = false, is_lvds = false, is_tv = false;
- bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct psb_intel_output *psb_intel_output = NULL;
- uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
- struct drm_encoder *encoder;
- struct drm_connector *connector;
- int timeout = 0;
-
- dev_dbg(dev->dev, "pipe = 0x%x \n", pipe);
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- fp_reg = FPB0;
- dpll_reg = DPLL_B;
- dspcntr_reg = DSPBCNTR;
- pipeconf_reg = PIPEBCONF;
- htot_reg = HTOTAL_B;
- hblank_reg = HBLANK_B;
- hsync_reg = HSYNC_B;
- vtot_reg = VTOTAL_B;
- vblank_reg = VBLANK_B;
- vsync_reg = VSYNC_B;
- dspsize_reg = DSPBSIZE;
- dsppos_reg = DSPBPOS;
- pipesrc_reg = PIPEBSRC;
- pipeconf = &dev_priv->pipeconf1;
- dspcntr = &dev_priv->dspcntr1;
- fp_reg = MDFLD_DPLL_DIV0;
- dpll_reg = MDFLD_DPLL_B;
- break;
- case 2:
- dpll_reg = MRST_DPLL_A;
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
- htot_reg = HTOTAL_C;
- hblank_reg = HBLANK_C;
- hsync_reg = HSYNC_C;
- vtot_reg = VTOTAL_C;
- vblank_reg = VBLANK_C;
- vsync_reg = VSYNC_C;
- dspsize_reg = DSPCSIZE;
- dsppos_reg = DSPCPOS;
- pipesrc_reg = PIPECSRC;
- pipeconf = &dev_priv->pipeconf2;
- dspcntr = &dev_priv->dspcntr2;
- break;
- default:
- DRM_ERROR("Illegal Pipe Number. \n");
- return 0;
- }
-
- dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
- adjusted_mode->hdisplay);
- dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
- adjusted_mode->vdisplay);
- dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
- adjusted_mode->hsync_start);
- dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
- adjusted_mode->hsync_end);
- dev_dbg(dev->dev, "adjusted_htotal = %d\n",
- adjusted_mode->htotal);
- dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
- adjusted_mode->vsync_start);
- dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
- adjusted_mode->vsync_end);
- dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
- adjusted_mode->vtotal);
- dev_dbg(dev->dev, "adjusted_clock = %d\n",
- adjusted_mode->clock);
- dev_dbg(dev->dev, "hdisplay = %d\n",
- mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay = %d\n",
- mode->vdisplay);
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
- memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
-
- list_for_each_entry(connector, &mode_config->connector_list, head) {
-
- encoder = connector->encoder;
-
- if(!encoder)
- continue;
-
- if (encoder->crtc != crtc)
- continue;
-
- psb_intel_output = to_psb_intel_output(connector);
-
- dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type);
-
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_LVDS:
- is_lvds = true;
- break;
- case INTEL_OUTPUT_TVOUT:
- is_tv = true;
- break;
- case INTEL_OUTPUT_ANALOG:
- is_crt = true;
- break;
- case INTEL_OUTPUT_MIPI:
- is_mipi = true;
- break;
- case INTEL_OUTPUT_MIPI2:
- is_mipi2 = true;
- break;
- case INTEL_OUTPUT_HDMI:
- is_hdmi = true;
- break;
- }
- }
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Disable the panel fitter if it was on our pipe */
- if (mdfld_panel_fitter_pipe(dev) == pipe)
- REG_WRITE(PFIT_CONTROL, 0);
-
- /* pipesrc and dspsize control the size that is scaled from,
- * which should always be the user's requested size.
- */
- if (pipe == 1) {
- /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
- * width/height and souce image size registers with the adjusted mode for pipe B. */
-
- /* The defined sprite rectangle must always be completely contained within the displayable
- * area of the screen image (frame buffer). */
- REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
- | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
- /* Set the CRTC with encoder mode. */
- REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
- | (mode->crtc_vdisplay - 1));
- } else {
- REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
- REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
- }
-
- REG_WRITE(dsppos_reg, 0);
-
- if (psb_intel_output)
- drm_connector_property_get_value(&psb_intel_output->base,
- dev->mode_config.scaling_mode_property, &scalingType);
-
- if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
- /*
- * Medfield doesn't have register support for centering so
- * we need to mess with the h/vblank and h/vsync start and
- * ends to get central
- */
- int offsetX = 0, offsetY = 0;
-
- offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
- offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-
- REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
- ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
- ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
- ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
- ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
- } else {
- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
- ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
- ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
- ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
- ((adjusted_mode->crtc_vsync_end - 1) << 16));
- }
-
- /* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs =
- crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
-
- /* setup pipeconf */
- *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
-
- /* Set up the display plane register */
- *dspcntr = REG_READ(dspcntr_reg);
- *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
- *dspcntr |= DISPLAY_PLANE_ENABLE;
-/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_BOTTOM; */
-/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_GAMMA_ENABLE; */
-
- if (is_mipi2)
- {
- goto mrst_crtc_mode_set_exit;
- }
-/* FIXME JLIU7 Add MDFLD HDMI supports */
-/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
-/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
- clk = adjusted_mode->clock;
-
- if (is_hdmi) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
- {
- refclk = 19200;
-
- if (is_mipi || is_mipi2)
- {
- clk_n = 1, clk_p2 = 8;
- } else if (is_hdmi) {
- clk_n = 1, clk_p2 = 10;
- }
- } else if (ksel == KSEL_BYPASS_25) {
- refclk = 25000;
-
- if (is_mipi || is_mipi2)
- {
- clk_n = 1, clk_p2 = 8;
- } else if (is_hdmi) {
- clk_n = 1, clk_p2 = 10;
- }
- } else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
- refclk = 83000;
-
- if (is_mipi || is_mipi2)
- {
- clk_n = 4, clk_p2 = 8;
- } else if (is_hdmi) {
- clk_n = 4, clk_p2 = 10;
- }
- } else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
- refclk = 100000;
- if (is_mipi || is_mipi2)
- {
- clk_n = 4, clk_p2 = 8;
- } else if (is_hdmi) {
- clk_n = 4, clk_p2 = 10;
- }
- }
-
- if (is_mipi)
- clk_byte = dev_priv->bpp / 8;
- else if (is_mipi2)
- clk_byte = dev_priv->bpp2 / 8;
-
- clk_tmp = clk * clk_n * clk_p2 * clk_byte;
-
- dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
- dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
-
- ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
-
- if (!ok) {
- dev_err(dev->dev,
- "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
- } else {
- m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
-
- dev_dbg(dev->dev, "dot clock = %d,"
- "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
- clock.p1, m_conv);
- }
-
- dpll = REG_READ(dpll_reg);
-
- if (dpll & DPLL_VCO_ENABLE) {
- dpll &= ~DPLL_VCO_ENABLE;
- REG_WRITE(dpll_reg, dpll);
- REG_READ(dpll_reg);
-
- /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- /* reset M1, N1 & P1 */
- REG_WRITE(fp_reg, 0);
- dpll &= ~MDFLD_P1_MASK;
- REG_WRITE(dpll_reg, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
- if (dpll & MDFLD_PWR_GATE_EN) {
- dpll &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(dpll_reg, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- dpll = 0;
-
-#if 0 /* FIXME revisit later */
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) {
- dpll &= ~MDFLD_INPUT_REF_SEL;
- } else if (ksel == KSEL_BYPASS_83_100) {
- dpll |= MDFLD_INPUT_REF_SEL;
- }
-#endif /* FIXME revisit later */
-
- if (is_hdmi)
- dpll |= MDFLD_VCO_SEL;
-
- fp = (clk_n / 2) << 16;
- fp |= m_conv;
-
- /* compute bitmask from p1 value */
- dpll |= (1 << (clock.p1 - 2)) << 17;
-
-#if 0 /* 1080p30 & 720p */
- dpll = 0x00050000;
- fp = 0x000001be;
-#endif
-#if 0 /* 480p */
- dpll = 0x02010000;
- fp = 0x000000d2;
-#endif
- } else {
-#if 0 /*DBI_TPO_480x864*/
- dpll = 0x00020000;
- fp = 0x00000156;
-#endif /* DBI_TPO_480x864 */ /* get from spec. */
-
- dpll = 0x00800000;
- fp = 0x000000c1;
-}
-
- REG_WRITE(fp_reg, fp);
- REG_WRITE(dpll_reg, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- dpll |= DPLL_VCO_ENABLE;
- REG_WRITE(dpll_reg, dpll);
- REG_READ(dpll_reg);
-
- /* wait for DSI PLL to lock */
- while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout ++;
- }
-
- if (is_mipi)
- goto mrst_crtc_mode_set_exit;
-
- dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi);
-
- REG_WRITE(pipeconf_reg, *pipeconf);
- REG_READ(pipeconf_reg);
-
- /* Wait for for the pipe enable to take effect. */
-//FIXME_JLIU7 HDMI mrstWaitForPipeEnable(dev);
-
- REG_WRITE(dspcntr_reg, *dspcntr);
- psb_intel_wait_for_vblank(dev);
-
-mrst_crtc_mode_set_exit:
-
- gma_power_end(dev);
-
- return 0;
-}
-
-static void mdfld_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void mdfld_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
- .dpms = mdfld_crtc_dpms,
- .mode_fixup = mdfld_crtc_mode_fixup,
- .mode_set = mdfld_crtc_mode_set,
- .mode_set_base = mdfld__intel_pipe_set_base,
- .prepare = mdfld_crtc_prepare,
- .commit = mdfld_crtc_commit,
-};
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h
deleted file mode 100644
index a7ad65472491..000000000000
--- a/drivers/staging/gma500/mdfld_msic.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jim Liu <jim.liu@intel.com>
- */
-
-#define MSIC_PCI_DEVICE_ID 0x831
-
-int msic_regsiter_driver(void);
-int msic_unregister_driver(void);
-extern void hpd_notify_um(void);
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
deleted file mode 100644
index eabf53d58f92..000000000000
--- a/drivers/staging/gma500/mdfld_output.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-
-#include "displays/tpo_cmd.h"
-#include "displays/tpo_vid.h"
-#include "displays/tmd_cmd.h"
-#include "displays/tmd_vid.h"
-#include "displays/pyr_cmd.h"
-#include "displays/pyr_vid.h"
-/* #include "displays/hdmi.h" */
-
-static int mdfld_dual_mipi;
-static int mdfld_hdmi;
-static int mdfld_dpu;
-
-module_param(mdfld_dual_mipi, int, 0600);
-MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration");
-module_param(mdfld_hdmi, int, 0600);
-MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI");
-module_param(mdfld_dpu, int, 0600);
-MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU");
-
-/* For now a single type per device is all we cope with */
-int mdfld_get_panel_type(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- return dev_priv->panel_id;
-}
-
-int mdfld_panel_dpi(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- switch (dev_priv->panel_id) {
- case TMD_VID:
- case TPO_VID:
- case PYR_VID:
- return true;
- case TMD_CMD:
- case TPO_CMD:
- case PYR_CMD:
- default:
- return false;
- }
-}
-
-static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
-{
- struct panel_funcs *p_cmd_funcs;
- struct panel_funcs *p_vid_funcs;
-
- /* Oh boy ... FIXME */
- p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
- if (p_cmd_funcs == NULL)
- return -ENODEV;
- p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
- if (p_vid_funcs == NULL) {
- kfree(p_cmd_funcs);
- return -ENODEV;
- }
-
- switch (p_type) {
- case TPO_CMD:
- tpo_cmd_init(dev, p_cmd_funcs);
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
- break;
- case TPO_VID:
- tpo_vid_init(dev, p_vid_funcs);
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
- break;
- case TMD_CMD:
- /*tmd_cmd_init(dev, p_cmd_funcs); */
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
- break;
- case TMD_VID:
- tmd_vid_init(dev, p_vid_funcs);
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
- break;
- case PYR_CMD:
- pyr_cmd_init(dev, p_cmd_funcs);
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
- break;
- case PYR_VID:
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
- break;
- case TPO: /* TPO panel supports both cmd & vid interfaces */
- tpo_cmd_init(dev, p_cmd_funcs);
- tpo_vid_init(dev, p_vid_funcs);
- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs,
- p_vid_funcs);
- break;
- case TMD:
- break;
- case PYR:
- break;
-#if 0
- case HDMI:
- dev_dbg(dev->dev, "Initializing HDMI");
- mdfld_hdmi_init(dev, &dev_priv->mode_dev);
- break;
-#endif
- default:
- dev_err(dev->dev, "Unsupported interface %d", p_type);
- return -ENODEV;
- }
- return 0;
-}
-
-int mdfld_output_init(struct drm_device *dev)
-{
- int type;
-
- /* MIPI panel 1 */
- type = mdfld_get_panel_type(dev, 0);
- dev_info(dev->dev, "panel 1: type is %d\n", type);
- init_panel(dev, 0, type);
-
- if (mdfld_dual_mipi) {
- /* MIPI panel 2 */
- type = mdfld_get_panel_type(dev, 2);
- dev_info(dev->dev, "panel 2: type is %d\n", type);
- init_panel(dev, 2, type);
- }
- if (mdfld_hdmi)
- /* HDMI panel */
- init_panel(dev, 0, HDMI);
- return 0;
-}
-
-void mdfld_output_setup(struct drm_device *dev)
-{
- /* FIXME: this is not the right place for this stuff ! */
- if (IS_MFLD(dev)) {
- if (mdfld_dpu)
- mdfld_dbi_dpu_init(dev);
- else
- mdfld_dbi_dsr_init(dev);
- }
-}
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
deleted file mode 100644
index daf33e7df9d5..000000000000
--- a/drivers/staging/gma500/mdfld_output.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef MDFLD_OUTPUT_H
-#define MDFLD_OUTPUT_H
-
-int mdfld_output_init(struct drm_device *dev);
-int mdfld_panel_dpi(struct drm_device *dev);
-int mdfld_get_panel_type(struct drm_device *dev, int pipe);
-void mdfld_disable_crtc (struct drm_device *dev, int pipe);
-
-extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
-extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
-
-extern void mdfld_output_setup(struct drm_device *dev);
-
-#endif
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
deleted file mode 100644
index 523f2d8fe4f1..000000000000
--- a/drivers/staging/gma500/mdfld_pyr_cmd.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/pyr_cmd.h"
-
-static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode) {
- dev_err(dev->dev, "Out of memory\n");
- return NULL;
- }
-
- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
- dev_dbg(dev->dev, "clock is %d\n", mode->clock);
-
- mode->hdisplay = 480;
- mode->vdisplay = 864;
- mode->hsync_start = 487;
- mode->hsync_end = 490;
- mode->htotal = 499;
- mode->vsync_start = 874;
- mode->vsync_end = 878;
- mode->vtotal = 886;
- mode->clock = 25777;
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
-
- if (fixed_mode) {
- adjusted_mode->hdisplay = fixed_mode->hdisplay;
- adjusted_mode->hsync_start = fixed_mode->hsync_start;
- adjusted_mode->hsync_end = fixed_mode->hsync_end;
- adjusted_mode->htotal = fixed_mode->htotal;
- adjusted_mode->vdisplay = fixed_mode->vdisplay;
- adjusted_mode->vsync_start = fixed_mode->vsync_start;
- adjusted_mode->vsync_end = fixed_mode->vsync_end;
- adjusted_mode->vtotal = fixed_mode->vtotal;
- adjusted_mode->clock = fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
- kfree(fixed_mode);
- }
- return true;
-}
-
-static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
-{
- int ret = 0;
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 reg_offset = 0;
- int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
-
- dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
- on ? "On" : "Off",
- dbi_output->dbi_panel_on ? "True" : "False");
-
- if (pipe == 2) {
- if (on)
- dev_priv->dual_mipi = true;
- else
- dev_priv->dual_mipi = false;
-
- reg_offset = MIPIC_REG_OFFSET;
- } else {
- if (!on)
- dev_priv->dual_mipi = false;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
-
- if (on) {
- if (dbi_output->dbi_panel_on)
- goto out_err;
-
- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
- if (ret) {
- dev_err(dev->dev, "power on error\n");
- goto out_err;
- }
-
- dbi_output->dbi_panel_on = true;
-
- if (pipe == 2) {
- dev_priv->dbi_panel_on2 = true;
- } else {
- dev_priv->dbi_panel_on = true;
- mdfld_enable_te(dev, 0);
- }
- } else {
- if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
- goto out_err;
-
- dbi_output->dbi_panel_on = false;
- dbi_output->first_boot = false;
-
- if (pipe == 2) {
- dev_priv->dbi_panel_on2 = false;
- mdfld_disable_te(dev, 2);
- } else {
- dev_priv->dbi_panel_on = false;
- mdfld_disable_te(dev, 0);
-
- if (dev_priv->dbi_panel_on2)
- mdfld_enable_te(dev, 2);
- }
-
- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
- if (ret) {
- dev_err(dev->dev, "power on error\n");
- goto out_err;
- }
- }
-
-out_err:
- gma_power_end(dev);
-
- if (ret)
- dev_err(dev->dev, "failed\n");
-}
-
-static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
- int lane_count = dsi_config->lane_count;
- u32 val = 0;
-
- dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
-
- /* Un-ready device */
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
-
- /* Init dsi adapter before kicking off */
- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
-
- /* TODO: figure out how to setup these registers */
- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
- 0x000a0014);
- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
-
- /* Enable all interrupts */
- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
- /* Max value: 20 clock cycles of txclkesc */
- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
- /* Min 21 txclkesc, max: ffffh */
- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
- /* Min: 7d0 max: 4e20 */
- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
-
- /* Set up func_prg */
- val |= lane_count;
- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
- val |= DSI_DBI_COLOR_FORMAT_OPTION2;
- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
-
- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
-
- /* De-assert dbi_stall when half of DBI FIFO is empty */
- /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
-
- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
-}
-
-static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- int ret = 0;
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dsi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
- int pipe = dsi_connector->pipe;
- u8 param = 0;
-
- /* Regs */
- u32 mipi_reg = MIPI;
- u32 dspcntr_reg = DSPACNTR;
- u32 pipeconf_reg = PIPEACONF;
- u32 reg_offset = 0;
-
- /* Values */
- u32 dspcntr_val = dev_priv->dspcntr;
- u32 pipeconf_val = dev_priv->pipeconf;
- u32 h_active_area = mode->hdisplay;
- u32 v_active_area = mode->vdisplay;
- u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
- TE_TRIGGER_GPIO_PIN);
-
- dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
-
- dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
- dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
-
- if (pipe == 2) {
- mipi_reg = MIPI_C;
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
-
- reg_offset = MIPIC_REG_OFFSET;
-
- dspcntr_val = dev_priv->dspcntr2;
- pipeconf_val = dev_priv->pipeconf2;
- } else {
- mipi_val |= 0x2; /* Two lanes for port A and C respectively */
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- /* Set up pipe related registers */
- REG_WRITE(mipi_reg, mipi_val);
- REG_READ(mipi_reg);
-
- pyr_dsi_controller_dbi_init(dsi_config, pipe);
-
- msleep(20);
-
- REG_WRITE(dspcntr_reg, dspcntr_val);
- REG_READ(dspcntr_reg);
-
- /* 20ms delay before sending exit_sleep_mode */
- msleep(20);
-
- /* Send exit_sleep_mode DCS */
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
- 0, CMD_DATA_SRC_SYSTEM_MEM);
- if (ret) {
- dev_err(dev->dev, "sent exit_sleep_mode faild\n");
- goto out_err;
- }
-
- /*send set_tear_on DCS*/
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
- &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
- if (ret) {
- dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
- goto out_err;
- }
-
- /* Do some init stuff */
- mdfld_dsi_brightness_init(dsi_config, pipe);
- mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
- REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
- REG_READ(pipeconf_reg);
-
- /* TODO: this looks ugly, try to move it to CRTC mode setting */
- if (pipe == 2)
- dev_priv->pipeconf2 |= PIPEACONF_DSR;
- else
- dev_priv->pipeconf |= PIPEACONF_DSR;
-
- dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg));
-
- ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
- h_active_area - 1, v_active_area - 1);
- if (ret) {
- dev_err(dev->dev, "update area failed\n");
- goto out_err;
- }
-
-out_err:
- gma_power_end(dev);
-
- if (ret)
- dev_err(dev->dev, "mode set failed\n");
- else
- dev_dbg(dev->dev, "mode set done successfully\n");
-}
-
-static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-
- dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
- dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
-
- pyr_dsi_dbi_set_power(encoder, false);
-}
-
-static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_drm_dpu_rect rect;
-
- pyr_dsi_dbi_set_power(encoder, true);
-
- dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
-
- rect.x = rect.y = 0;
- rect.width = 864;
- rect.height = 480;
-
- if (dbi_output->channel_num == 1) {
- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
- /* If DPU enabled report a fullscreen damage */
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
- } else {
- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
- }
- dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
-}
-
-static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct drm_device *dev = dbi_output->dev;
-
- dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
-
- if (mode == DRM_MODE_DPMS_ON)
- pyr_dsi_dbi_set_power(encoder, true);
- else
- pyr_dsi_dbi_set_power(encoder, false);
-}
-
-/*
- * Update the DBI MIPI Panel Frame Buffer.
- */
-static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
- struct drm_device *dev = dbi_output->dev;
- struct drm_crtc *crtc = dbi_output->base.base.crtc;
- struct psb_intel_crtc *psb_crtc = (crtc) ?
- to_psb_intel_crtc(crtc) : NULL;
-
- u32 dpll_reg = MRST_DPLL_A;
- u32 dspcntr_reg = DSPACNTR;
- u32 pipeconf_reg = PIPEACONF;
- u32 dsplinoff_reg = DSPALINOFF;
- u32 dspsurf_reg = DSPASURF;
- u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
- u32 reg_offset = 0;
-
- u32 intr_status;
- u32 fifo_stat_reg_val;
- u32 dpll_reg_val;
- u32 dspcntr_reg_val;
- u32 pipeconf_reg_val;
-
- /* If mode setting on-going, back off */
- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
- !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
- return;
-
- /*
- * Look for errors here. In particular we're checking for whatever
- * error status might have appeared during the last frame transmit
- * (memory write).
- *
- * Normally, the bits we're testing here would be set infrequently,
- * if at all. However, one panel (at least) returns at least one
- * error bit on most frames. So we've disabled the kernel message
- * for now.
- *
- * Still clear whatever error bits are set, except don't clear the
- * ones that would make the Penwell DSI controller reset if we
- * cleared them.
- */
- intr_status = REG_READ(INTR_STAT_REG);
- if ((intr_status & 0x26FFFFFF) != 0) {
- /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
- intr_status &= 0x26F3FFFF;
- REG_WRITE(INTR_STAT_REG, intr_status);
- }
-
- if (pipe == 2) {
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
- dsplinoff_reg = DSPCLINOFF;
- dspsurf_reg = DSPCSURF;
-
- hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
-
- reg_offset = MIPIC_REG_OFFSET;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
- dpll_reg_val = REG_READ(dpll_reg);
- dspcntr_reg_val = REG_READ(dspcntr_reg);
- pipeconf_reg_val = REG_READ(pipeconf_reg);
-
- if (!(fifo_stat_reg_val & (1 << 27)) ||
- (dpll_reg_val & DPLL_VCO_ENABLE) ||
- !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
- !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
- goto update_fb_out0;
- }
-
- /* Refresh plane changes */
- REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
- REG_READ(dspsurf_reg);
-
- mdfld_dsi_send_dcs(sender,
- write_mem_start,
- NULL,
- 0,
- CMD_DATA_SRC_PIPE,
- MDFLD_DSI_SEND_PACKAGE);
-
- /*
- * The idea here is to transmit a Generic Read command after the
- * Write Memory Start/Continue commands finish. This asks for
- * the panel to return an "ACK No Errors," or (if it has errors
- * to report) an Error Report. This allows us to monitor the
- * panel's perception of the health of the DSI.
- */
- mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
- REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
-
- dbi_output->dsr_fb_update_done = true;
-update_fb_out0:
- gma_power_end(dev);
-}
-
-/*
- * TODO: will be removed later, should work out display interfaces for power
- */
-void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- if (!dsi_config || (pipe != 0 && pipe != 2)) {
- WARN_ON(1);
- return;
- }
- pyr_dsi_controller_dbi_init(dsi_config, pipe);
-}
-
-static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = PYR_PANEL_WIDTH;
- pi->height_mm = PYR_PANEL_HEIGHT;
-
- return 0;
-}
-
-/* PYR DBI encoder helper funcs */
-static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
- .dpms = pyr_dsi_dbi_dpms,
- .mode_fixup = pyr_dsi_dbi_mode_fixup,
- .prepare = pyr_dsi_dbi_prepare,
- .mode_set = pyr_dsi_dbi_mode_set,
- .commit = pyr_dsi_dbi_commit,
-};
-
-/* PYR DBI encoder funcs */
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
- p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
- p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
- p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
- p_funcs->update_fb = pyr_dsi_dbi_update_fb;
- p_funcs->get_panel_info = pyr_cmd_get_panel_info;
-}
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c
deleted file mode 100644
index affdc09c6769..000000000000
--- a/drivers/staging/gma500/mdfld_tmd_vid.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Jim Liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- * Gideon Eaton <eaton.
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tmd_vid.h"
-
-/* FIXME: static ? */
-struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false; /*Disable GCT for now*/
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode) {
- dev_err(dev->dev, "Out of memory\n");
- return NULL;
- }
-
- if (use_gct) {
- dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay +
- ((ti->hsync_offset_hi << 8) |
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start +
- ((ti->hsync_pulse_width_hi << 8) |
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 8) |
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
- ti->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay +
- ((ti->vblank_hi << 8) | ti->vblank_lo);
- mode->clock = ti->pixel_clock * 10;
-
- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
- dev_dbg(dev->dev, "clock is %d\n", mode->clock);
- } else {
- mode->hdisplay = 480;
- mode->vdisplay = 854;
- mode->hsync_start = 487;
- mode->hsync_end = 490;
- mode->htotal = 499;
- mode->vsync_start = 861;
- mode->vsync_end = 865;
- mode->vtotal = 873;
- mode->clock = 33264;
- }
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static int tmd_vid_get_panel_info(struct drm_device *dev,
- int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = TMD_PANEL_WIDTH;
- pi->height_mm = TMD_PANEL_HEIGHT;
-
- return 0;
-}
-
-/*
- * mdfld_init_TMD_MIPI - initialise a TMD interface
- * @dsi_config: configuration
- * @pipe: pipe to configure
- *
- * This function is called only by mrst_dsi_mode_set and
- * restore_display_registers. since this function does not
- * acquire the mutex, it is important that the calling function
- * does!
- */
-
-
-static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- static u32 tmd_cmd_mcap_off[] = {0x000000b2};
- static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
- static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
- static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
- static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
- static u32 tmd_cmd_set_mode[] = {0x000000b3};
- static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
- static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
- static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
- static u32 tmd_cmd_set_video_mode[] = {0x00000153};
- /*no auto_bl,need add in furture*/
- static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
- static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
-
- struct mdfld_dsi_pkg_sender *sender
- = mdfld_dsi_get_pkg_sender(dsi_config);
-
- DRM_INFO("Enter mdfld init TMD MIPI display.\n");
-
- if (!sender) {
- DRM_ERROR("Cannot get sender\n");
- return;
- }
-
- if (dsi_config->dvr_ic_inited)
- return;
-
- msleep(3);
-
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
- mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0);
- mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0);
-
- dsi_config->dvr_ic_inited = 1;
-}
-
-/* TMD DPI encoder helper funcs */
-static const struct drm_encoder_helper_funcs
- mdfld_tpo_dpi_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-/* TMD DPI encoder funcs */
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
- if (!dev || !p_funcs) {
- dev_err(dev->dev, "Invalid parameters\n");
- return;
- }
-
- p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
- p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
- p_funcs->get_config_mode = &tmd_vid_get_config_mode;
- p_funcs->update_fb = NULL;
- p_funcs->get_panel_info = tmd_vid_get_panel_info;
- p_funcs->reset = mdfld_dsi_panel_reset;
- p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
-}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
deleted file mode 100644
index c7f7c9c19bc1..000000000000
--- a/drivers/staging/gma500/mdfld_tpo_cmd.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Copyright (c) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicensen
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_dbi_dpu.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tpo_cmd.h"
-
-static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false;
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- if (use_gct) {
- dev_dbg(dev->dev, "gct find MIPI panel.\n");
-
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay + \
- ((ti->hsync_offset_hi << 8) | \
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start + \
- ((ti->hsync_pulse_width_hi << 8) | \
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
- ti->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay + \
- ((ti->vblank_hi << 8) | ti->vblank_lo);
- mode->clock = ti->pixel_clock * 10;
-
- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
- dev_dbg(dev->dev, "clock is %d\n", mode->clock);
- } else {
- mode->hdisplay = 864;
- mode->vdisplay = 480;
- mode->hsync_start = 872;
- mode->hsync_end = 876;
- mode->htotal = 884;
- mode->vsync_start = 482;
- mode->vsync_end = 494;
- mode->vtotal = 486;
- mode->clock = 25777;
- }
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev);
-
- if (fixed_mode) {
- adjusted_mode->hdisplay = fixed_mode->hdisplay;
- adjusted_mode->hsync_start = fixed_mode->hsync_start;
- adjusted_mode->hsync_end = fixed_mode->hsync_end;
- adjusted_mode->htotal = fixed_mode->htotal;
- adjusted_mode->vdisplay = fixed_mode->vdisplay;
- adjusted_mode->vsync_start = fixed_mode->vsync_start;
- adjusted_mode->vsync_end = fixed_mode->vsync_end;
- adjusted_mode->vtotal = fixed_mode->vtotal;
- adjusted_mode->clock = fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
- kfree(fixed_mode);
- }
- return true;
-}
-
-static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
-{
- int ret = 0;
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 reg_offset = 0;
- int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
- u32 data = 0;
-
- dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
- pipe, on ? "On" : "Off",
- dbi_output->dbi_panel_on ? "True" : "False");
-
- if (pipe == 2) {
- if (on)
- dev_priv->dual_mipi = true;
- else
- dev_priv->dual_mipi = false;
- reg_offset = MIPIC_REG_OFFSET;
- } else {
- if (!on)
- dev_priv->dual_mipi = false;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- if (on) {
- if (dbi_output->dbi_panel_on)
- goto out_err;
-
- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
- if (ret) {
- dev_err(dev->dev, "power on error\n");
- goto out_err;
- }
-
- dbi_output->dbi_panel_on = true;
-
- if (pipe == 2)
- dev_priv->dbi_panel_on2 = true;
- else
- dev_priv->dbi_panel_on = true;
- mdfld_enable_te(dev, pipe);
- } else {
- if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
- goto out_err;
-
- dbi_output->dbi_panel_on = false;
- dbi_output->first_boot = false;
-
- if (pipe == 2)
- dev_priv->dbi_panel_on2 = false;
- else
- dev_priv->dbi_panel_on = false;
-
- mdfld_disable_te(dev, pipe);
-
- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
- if (ret) {
- dev_err(dev->dev, "power on error\n");
- goto out_err;
- }
- }
-
- /*
- * FIXME: this is a WA for TPO panel crash on DPMS on & off around
- * 83 times. the root cause of this issue is that Booster in
- * drvIC crashed. Add this WA so that we can resume the driver IC
- * once we found that booster has a fault
- */
- mdfld_dsi_get_power_mode(dsi_config,
- &data,
- MDFLD_DSI_HS_TRANSMISSION);
-
- if (on && data && !(data & (1 << 7))) {
- /* Soft reset */
- mdfld_dsi_send_dcs(sender,
- DCS_SOFT_RESET,
- NULL,
- 0,
- CMD_DATA_SRC_PIPE,
- MDFLD_DSI_SEND_PACKAGE);
-
- /* Init drvIC */
- if (dbi_output->p_funcs->drv_ic_init)
- dbi_output->p_funcs->drv_ic_init(dsi_config,
- pipe);
- }
-
-out_err:
- gma_power_end(dev);
- if (ret)
- dev_err(dev->dev, "failed\n");
-}
-
-
-static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- int ret = 0;
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dsi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
- int pipe = dsi_connector->pipe;
- u8 param = 0;
-
- /* Regs */
- u32 mipi_reg = MIPI;
- u32 dspcntr_reg = DSPACNTR;
- u32 pipeconf_reg = PIPEACONF;
- u32 reg_offset = 0;
-
- /* Values */
- u32 dspcntr_val = dev_priv->dspcntr;
- u32 pipeconf_val = dev_priv->pipeconf;
- u32 h_active_area = mode->hdisplay;
- u32 v_active_area = mode->vdisplay;
- u32 mipi_val;
-
- mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
- TE_TRIGGER_GPIO_PIN);
-
- dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
-
- dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
- dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
-
- if (pipe == 2) {
- mipi_reg = MIPI_C;
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
-
- reg_offset = MIPIC_REG_OFFSET;
-
- dspcntr_val = dev_priv->dspcntr2;
- pipeconf_val = dev_priv->pipeconf2;
- } else {
- mipi_val |= 0x2; /*two lanes for port A and C respectively*/
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- REG_WRITE(dspcntr_reg, dspcntr_val);
- REG_READ(dspcntr_reg);
-
- /* 20ms delay before sending exit_sleep_mode */
- msleep(20);
-
- /* Send exit_sleep_mode DCS */
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE,
- NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
- if (ret) {
- dev_err(dev->dev, "sent exit_sleep_mode faild\n");
- goto out_err;
- }
-
- /* Send set_tear_on DCS */
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON,
- &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
- if (ret) {
- dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
- goto out_err;
- }
-
- /* Do some init stuff */
- REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
- REG_READ(pipeconf_reg);
-
- /* TODO: this looks ugly, try to move it to CRTC mode setting*/
- if (pipe == 2)
- dev_priv->pipeconf2 |= PIPEACONF_DSR;
- else
- dev_priv->pipeconf |= PIPEACONF_DSR;
-
- dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg));
-
- ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
- h_active_area - 1, v_active_area - 1);
- if (ret) {
- dev_err(dev->dev, "update area failed\n");
- goto out_err;
- }
-
-out_err:
- gma_power_end(dev);
-
- if (ret)
- dev_err(dev->dev, "mode set failed\n");
-}
-
-static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output
- = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
-
- dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
- dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
-
- mdfld_dsi_dbi_set_power(encoder, false);
-}
-
-static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output =
- MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_drm_dpu_rect rect;
-
- mdfld_dsi_dbi_set_power(encoder, true);
- dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
-
- rect.x = rect.y = 0;
- rect.width = 864;
- rect.height = 480;
-
- if (dbi_output->channel_num == 1) {
- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
- /*if dpu enabled report a fullscreen damage*/
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
- } else {
- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
- }
- dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
-}
-
-static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
- struct mdfld_dsi_dbi_output *dbi_output
- = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- static bool bdispoff;
-
- dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
-
- if (mode == DRM_MODE_DPMS_ON) {
- /*
- * FIXME: in case I am wrong!
- * we don't need to exit dsr here to wake up plane/pipe/pll
- * if everything goes right, hw_begin will resume them all
- * during set_power.
- */
- if (bdispoff /* FIXME && gbgfxsuspended */) {
- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
- bdispoff = false;
- dev_priv->dispstatus = true;
- }
-
- mdfld_dsi_dbi_set_power(encoder, true);
- /* FIXME if (gbgfxsuspended)
- gbgfxsuspended = false; */
- } else {
- /*
- * I am not sure whether this is the perfect place to
- * turn rpm on since we still have a lot of CRTC turnning
- * on work to do.
- */
- bdispoff = true;
- dev_priv->dispstatus = false;
- mdfld_dsi_dbi_set_power(encoder, false);
- }
-}
-
-
-/*
- * Update the DBI MIPI Panel Frame Buffer.
- */
-static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe)
-{
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
- struct drm_device *dev = dbi_output->dev;
- struct drm_crtc *crtc = dbi_output->base.base.crtc;
- struct psb_intel_crtc *psb_crtc = (crtc) ?
- to_psb_intel_crtc(crtc) : NULL;
- u32 dpll_reg = MRST_DPLL_A;
- u32 dspcntr_reg = DSPACNTR;
- u32 pipeconf_reg = PIPEACONF;
- u32 dsplinoff_reg = DSPALINOFF;
- u32 dspsurf_reg = DSPASURF;
- u32 reg_offset = 0;
-
- /* If mode setting on-going, back off */
- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
- !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
- return;
-
- if (pipe == 2) {
- dspcntr_reg = DSPCCNTR;
- pipeconf_reg = PIPECCONF;
- dsplinoff_reg = DSPCLINOFF;
- dspsurf_reg = DSPCSURF;
- reg_offset = MIPIC_REG_OFFSET;
- }
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
-
- /* Check DBI FIFO status */
- if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
- !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
- !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
- goto update_fb_out0;
-
- /* Refresh plane changes */
- REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
- REG_READ(dspsurf_reg);
-
- mdfld_dsi_send_dcs(sender,
- DCS_WRITE_MEM_START,
- NULL,
- 0,
- CMD_DATA_SRC_PIPE,
- MDFLD_DSI_SEND_PACKAGE);
-
- dbi_output->dsr_fb_update_done = true;
-update_fb_out0:
- gma_power_end(dev);
-}
-
-static int tpo_cmd_get_panel_info(struct drm_device *dev,
- int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = TPO_PANEL_WIDTH;
- pi->height_mm = TPO_PANEL_HEIGHT;
-
- return 0;
-}
-
-
-/* TPO DBI encoder helper funcs */
-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
- .dpms = mdfld_dsi_dbi_dpms,
- .mode_fixup = mdfld_dsi_dbi_mode_fixup,
- .prepare = mdfld_dsi_dbi_prepare,
- .mode_set = mdfld_dsi_dbi_mode_set,
- .commit = mdfld_dsi_dbi_commit,
-};
-
-/* TPO DBI encoder funcs */
-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
- p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
- p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
- p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
- p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
- p_funcs->get_panel_info = tpo_cmd_get_panel_info;
- p_funcs->reset = mdfld_dsi_panel_reset;
- p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
-}
diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c
deleted file mode 100644
index 954901751760..000000000000
--- a/drivers/staging/gma500/mdfld_tpo_vid.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dbi.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-#include "mdfld_dsi_pkg_sender.h"
-
-#include "displays/tpo_vid.h"
-
-static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false;
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode) {
- dev_err(dev->dev, "out of memory\n");
- return NULL;
- }
-
- if (use_gct) {
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay + \
- ((ti->hsync_offset_hi << 8) | \
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start + \
- ((ti->hsync_pulse_width_hi << 8) | \
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
- ti->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay + \
- ((ti->vblank_hi << 8) | ti->vblank_lo);
- mode->clock = ti->pixel_clock * 10;
-
- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
- dev_dbg(dev->dev, "clock is %d\n", mode->clock);
- } else {
- mode->hdisplay = 864;
- mode->vdisplay = 480;
- mode->hsync_start = 873;
- mode->hsync_end = 876;
- mode->htotal = 887;
- mode->vsync_start = 487;
- mode->vsync_end = 490;
- mode->vtotal = 499;
- mode->clock = 33264;
- }
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static int tpo_vid_get_panel_info(struct drm_device *dev,
- int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = TPO_PANEL_WIDTH;
- pi->height_mm = TPO_PANEL_HEIGHT;
-
- return 0;
-}
-
-/*TPO DPI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs
- mdfld_tpo_dpi_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-/*TPO DPI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
-{
- if (!dev || !p_funcs) {
- dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n");
- return;
- }
-
- p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
- p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
- p_funcs->get_config_mode = &tpo_vid_get_config_mode;
- p_funcs->update_fb = NULL;
- p_funcs->get_panel_info = tpo_vid_get_panel_info;
-}
diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h
deleted file mode 100644
index 09e9687431f1..000000000000
--- a/drivers/staging/gma500/medfield.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Medfield DSI controller registers */
-
-#define MIPIA_DEVICE_READY_REG 0xb000
-#define MIPIA_INTR_STAT_REG 0xb004
-#define MIPIA_INTR_EN_REG 0xb008
-#define MIPIA_DSI_FUNC_PRG_REG 0xb00c
-#define MIPIA_HS_TX_TIMEOUT_REG 0xb010
-#define MIPIA_LP_RX_TIMEOUT_REG 0xb014
-#define MIPIA_TURN_AROUND_TIMEOUT_REG 0xb018
-#define MIPIA_DEVICE_RESET_TIMER_REG 0xb01c
-#define MIPIA_DPI_RESOLUTION_REG 0xb020
-#define MIPIA_DBI_FIFO_THROTTLE_REG 0xb024
-#define MIPIA_HSYNC_COUNT_REG 0xb028
-#define MIPIA_HBP_COUNT_REG 0xb02c
-#define MIPIA_HFP_COUNT_REG 0xb030
-#define MIPIA_HACTIVE_COUNT_REG 0xb034
-#define MIPIA_VSYNC_COUNT_REG 0xb038
-#define MIPIA_VBP_COUNT_REG 0xb03c
-#define MIPIA_VFP_COUNT_REG 0xb040
-#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG 0xb044
-#define MIPIA_DPI_CONTROL_REG 0xb048
-#define MIPIA_DPI_DATA_REG 0xb04c
-#define MIPIA_INIT_COUNT_REG 0xb050
-#define MIPIA_MAX_RETURN_PACK_SIZE_REG 0xb054
-#define MIPIA_VIDEO_MODE_FORMAT_REG 0xb058
-#define MIPIA_EOT_DISABLE_REG 0xb05c
-#define MIPIA_LP_BYTECLK_REG 0xb060
-#define MIPIA_LP_GEN_DATA_REG 0xb064
-#define MIPIA_HS_GEN_DATA_REG 0xb068
-#define MIPIA_LP_GEN_CTRL_REG 0xb06c
-#define MIPIA_HS_GEN_CTRL_REG 0xb070
-#define MIPIA_GEN_FIFO_STAT_REG 0xb074
-#define MIPIA_HS_LS_DBI_ENABLE_REG 0xb078
-#define MIPIA_DPHY_PARAM_REG 0xb080
-#define MIPIA_DBI_BW_CTRL_REG 0xb084
-#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG 0xb088
-
-#define DSI_DEVICE_READY (0x1)
-#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1)
-#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1)
-#define DSI_POWER_STATE_ULPS_OFFSET (0x1)
-
-
-#define DSI_ONE_DATA_LANE (0x1)
-#define DSI_TWO_DATA_LANE (0x2)
-#define DSI_THREE_DATA_LANE (0X3)
-#define DSI_FOUR_DATA_LANE (0x4)
-#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3)
-#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5)
-#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7)
-#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13)
-
-#define DSI_INTR_STATE_RXSOTERROR 1
-
-#define DSI_INTR_STATE_SPL_PKG_SENT (1 << 30)
-#define DSI_INTR_STATE_TE (1 << 31)
-
-#define DSI_HS_TX_TIMEOUT_MASK (0xffffff)
-
-#define DSI_LP_RX_TIMEOUT_MASK (0xffffff)
-
-#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f)
-
-#define DSI_RESET_TIMER_MASK (0xffff)
-
-#define DSI_DBI_FIFO_WM_HALF (0x0)
-#define DSI_DBI_FIFO_WM_QUARTER (0x1)
-#define DSI_DBI_FIFO_WM_LOW (0x2)
-
-#define DSI_DPI_TIMING_MASK (0xffff)
-
-#define DSI_INIT_TIMER_MASK (0xffff)
-
-#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff)
-
-#define DSI_LP_BYTECLK_MASK (0x0ffff)
-
-#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03)
-#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13)
-#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23)
-#define DSI_HS_CTRL_GEN_R0 (0x04)
-#define DSI_HS_CTRL_GEN_R1 (0x14)
-#define DSI_HS_CTRL_GEN_R2 (0x24)
-#define DSI_HS_CTRL_GEN_LONG_W (0x29)
-#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05)
-#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15)
-#define DSI_HS_CTRL_MCS_R0 (0x06)
-#define DSI_HS_CTRL_MCS_LONG_W (0x39)
-#define DSI_HS_CTRL_VC_OFFSET (0x06)
-#define DSI_HS_CTRL_WC_OFFSET (0x08)
-
-#define DSI_FIFO_GEN_HS_DATA_FULL (1 << 0)
-#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY (1 << 1)
-#define DSI_FIFO_GEN_HS_DATA_EMPTY (1 << 2)
-#define DSI_FIFO_GEN_LP_DATA_FULL (1 << 8)
-#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY (1 << 9)
-#define DSI_FIFO_GEN_LP_DATA_EMPTY (1 << 10)
-#define DSI_FIFO_GEN_HS_CTRL_FULL (1 << 16)
-#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY (1 << 17)
-#define DSI_FIFO_GEN_HS_CTRL_EMPTY (1 << 18)
-#define DSI_FIFO_GEN_LP_CTRL_FULL (1 << 24)
-#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY (1 << 25)
-#define DSI_FIFO_GEN_LP_CTRL_EMPTY (1 << 26)
-#define DSI_FIFO_DBI_EMPTY (1 << 27)
-#define DSI_FIFO_DPI_EMPTY (1 << 28)
-
-#define DSI_DBI_HS_LP_SWITCH_MASK (0x1)
-
-#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0)
-#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16)
-
-#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001)
-#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002)
-
-/* Medfield DSI adapter registers */
-#define MIPIA_CONTROL_REG 0xb104
-#define MIPIA_DATA_ADD_REG 0xb108
-#define MIPIA_DATA_LEN_REG 0xb10c
-#define MIPIA_CMD_ADD_REG 0xb110
-#define MIPIA_CMD_LEN_REG 0xb114
-
-/*dsi power modes*/
-#define DSI_POWER_MODE_DISPLAY_ON (1 << 2)
-#define DSI_POWER_MODE_NORMAL_ON (1 << 3)
-#define DSI_POWER_MODE_SLEEP_OUT (1 << 4)
-#define DSI_POWER_MODE_PARTIAL_ON (1 << 5)
-#define DSI_POWER_MODE_IDLE_ON (1 << 6)
-
-enum {
- MDFLD_DSI_ENCODER_DBI = 0,
- MDFLD_DSI_ENCODER_DPI,
-};
-
-enum {
- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
- MDFLD_DSI_VIDEO_BURST_MODE = 3,
-};
-
-#define DSI_DPI_COMPLETE_LAST_LINE (1 << 2)
-#define DSI_DPI_DISABLE_BTA (1 << 3)
-/* Panel types */
-enum {
- TPO_CMD,
- TPO_VID,
- TMD_CMD,
- TMD_VID,
- PYR_CMD,
- PYR_VID,
- TPO,
- TMD,
- PYR,
- HDMI,
- GCT_DETECT
-};
-
-/* Junk that belongs elsewhere */
-#define TPO_PANEL_WIDTH 84
-#define TPO_PANEL_HEIGHT 46
-#define TMD_PANEL_WIDTH 39
-#define TMD_PANEL_HEIGHT 71
-#define PYR_PANEL_WIDTH 53
-#define PYR_PANEL_HEIGHT 95
-
-/* Panel interface */
-struct panel_info {
- u32 width_mm;
- u32 height_mm;
-};
-
-struct mdfld_dsi_dbi_output;
-
-struct mdfld_dsi_connector_state {
- u32 mipi_ctrl_reg;
-};
-
-struct mdfld_dsi_encoder_state {
-
-};
-
-struct mdfld_dsi_connector {
- /*
- * This is ugly, but I have to use connector in it! :-(
- * FIXME: use drm_connector instead.
- */
- struct psb_intel_output base;
-
- int pipe;
- void *private;
- void *pkg_sender;
-
- /* Connection status */
- enum drm_connector_status status;
-};
-
-struct mdfld_dsi_encoder {
- struct drm_encoder base;
- void *private;
-};
-
-/*
- * DSI config, consists of one DSI connector, two DSI encoders.
- * DRM will pick up on DSI encoder basing on differents configs.
- */
-struct mdfld_dsi_config {
- struct drm_device *dev;
- struct drm_display_mode *fixed_mode;
- struct drm_display_mode *mode;
-
- struct mdfld_dsi_connector *connector;
- struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER];
- struct mdfld_dsi_encoder *encoder;
-
- int changed;
-
- int bpp;
- int type;
- int lane_count;
- /*Virtual channel number for this encoder*/
- int channel_num;
- /*video mode configure*/
- int video_mode;
-
- int dvr_ic_inited;
-};
-
-#define MDFLD_DSI_CONNECTOR(psb_output) \
- (container_of(psb_output, struct mdfld_dsi_connector, base))
-
-#define MDFLD_DSI_ENCODER(encoder) \
- (container_of(encoder, struct mdfld_dsi_encoder, base))
-
-struct panel_funcs {
- const struct drm_encoder_funcs *encoder_funcs;
- const struct drm_encoder_helper_funcs *encoder_helper_funcs;
- struct drm_display_mode *(*get_config_mode) (struct drm_device *);
- void (*update_fb) (struct mdfld_dsi_dbi_output *, int);
- int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
- int (*reset)(int pipe);
- void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
-};
-
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c
deleted file mode 100644
index ee3c0368e320..000000000000
--- a/drivers/staging/gma500/mid_bios.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-/* TODO
- * - Split functions by vbt type
- * - Make them all take drm_device
- * - Check ioremap failures
- */
-
-#include <linux/moduleparam.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "mid_bios.h"
-#include "mdfld_output.h"
-
-static int panel_id = GCT_DETECT;
-module_param_named(panel_id, panel_id, int, 0600);
-MODULE_PARM_DESC(panel_id, "Panel Identifier");
-
-
-static void mid_get_fuse_settings(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- uint32_t fuse_value = 0;
- uint32_t fuse_value_tmp = 0;
-
-#define FB_REG06 0xD0810600
-#define FB_MIPI_DISABLE (1 << 11)
-#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
-#define FB_SKU_MASK 0x7000
-#define FB_SKU_SHIFT 12
-#define FB_SKU_100 0
-#define FB_SKU_100L 1
-#define FB_SKU_83 2
- pci_write_config_dword(pci_root, 0xD0, FB_REG06);
- pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
- /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
- if (IS_MRST(dev))
- dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
-
- DRM_INFO("internal display is %s\n",
- dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
-
- /* Prevent runtime suspend at start*/
- if (dev_priv->iLVDS_enable) {
- dev_priv->is_lvds_on = true;
- dev_priv->is_mipi_on = false;
- } else {
- dev_priv->is_mipi_on = true;
- dev_priv->is_lvds_on = false;
- }
-
- dev_priv->video_device_fuse = fuse_value;
-
- pci_write_config_dword(pci_root, 0xD0, FB_REG09);
- pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
- dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
- fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
-
- dev_priv->fuse_reg_value = fuse_value;
-
- switch (fuse_value_tmp) {
- case FB_SKU_100:
- dev_priv->core_freq = 200;
- break;
- case FB_SKU_100L:
- dev_priv->core_freq = 100;
- break;
- case FB_SKU_83:
- dev_priv->core_freq = 166;
- break;
- default:
- dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
- fuse_value_tmp);
- dev_priv->core_freq = 0;
- }
- dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
- pci_dev_put(pci_root);
-}
-
-/*
- * Get the revison ID, B0:D2:F0;0x08
- */
-static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
-{
- uint32_t platform_rev_id = 0;
- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
- pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
- dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
- pci_dev_put(pci_gfx_root);
- dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
- dev_priv->platform_rev_id);
-}
-
-static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
- struct mrst_vbt *vbt = &dev_priv->vbt_data;
- u32 addr;
- u16 new_size;
- u8 *vbt_virtual;
- u8 bpi;
- u8 number_desc = 0;
- struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
- struct gct_r10_timing_info ti;
- void *pGCT;
- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
- /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
- pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
- pci_dev_put(pci_gfx_root);
-
- dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
-
- /* check for platform config address == 0. */
- /* this means fw doesn't support vbt */
-
- if (addr == 0) {
- vbt->size = 0;
- return;
- }
-
- /* get the virtual address of the vbt */
- vbt_virtual = ioremap(addr, sizeof(*vbt));
-
- memcpy(vbt, vbt_virtual, sizeof(*vbt));
- iounmap(vbt_virtual); /* Free virtual address space */
-
- dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
-
- switch (vbt->revision) {
- case 0:
- vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
- vbt->size - sizeof(*vbt) + 4);
- pGCT = vbt->mrst_gct;
- bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
- dev_priv->gct_data.bpi = bpi;
- dev_priv->gct_data.pt =
- ((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
- memcpy(&dev_priv->gct_data.DTD,
- &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
- sizeof(struct mrst_timing_info));
- dev_priv->gct_data.Panel_Port_Control =
- ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
- dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
- ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
- break;
- case 1:
- vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
- vbt->size - sizeof(*vbt) + 4);
- pGCT = vbt->mrst_gct;
- bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
- dev_priv->gct_data.bpi = bpi;
- dev_priv->gct_data.pt =
- ((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
- memcpy(&dev_priv->gct_data.DTD,
- &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
- sizeof(struct mrst_timing_info));
- dev_priv->gct_data.Panel_Port_Control =
- ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
- dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
- ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
- break;
- case 0x10:
- /*header definition changed from rev 01 (v2) to rev 10h. */
- /*so, some values have changed location*/
- new_size = vbt->checksum; /*checksum contains lo size byte*/
- /*LSB of mrst_gct contains hi size byte*/
- new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
-
- vbt->checksum = vbt->size; /*size contains the checksum*/
- if (new_size > 0xff)
- vbt->size = 0xff; /*restrict size to 255*/
- else
- vbt->size = new_size;
-
- /* number of descriptors defined in the GCT */
- number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
- bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
- vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
- GCT_R10_DISPLAY_DESC_SIZE * number_desc);
- pGCT = vbt->mrst_gct;
- pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
- dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
- /*copy the GCT display timings into a temp structure*/
- memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
- /*now copy the temp struct into the dev_priv->gct_data*/
- dp_ti->pixel_clock = ti.pixel_clock;
- dp_ti->hactive_hi = ti.hactive_hi;
- dp_ti->hactive_lo = ti.hactive_lo;
- dp_ti->hblank_hi = ti.hblank_hi;
- dp_ti->hblank_lo = ti.hblank_lo;
- dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
- dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
- dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
- dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
- dp_ti->vactive_hi = ti.vactive_hi;
- dp_ti->vactive_lo = ti.vactive_lo;
- dp_ti->vblank_hi = ti.vblank_hi;
- dp_ti->vblank_lo = ti.vblank_lo;
- dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
- dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
- dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
- dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
- /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
- dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
- *((u8 *)pGCT + 0x0d);
- dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
- (*((u8 *)pGCT + 0x0e)) << 8;
- break;
- default:
- dev_err(dev->dev, "Unknown revision of GCT!\n");
- vbt->size = 0;
- }
- if (IS_MFLD(dev_priv->dev)) {
- if (panel_id == GCT_DETECT) {
- if (dev_priv->gct_data.bpi == 2) {
- dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
- dev_priv->panel_id = PYR_CMD;
- panel_id = PYR_CMD;
- } else if (dev_priv->gct_data.bpi == 0) {
- dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
- dev_priv->panel_id = TMD_VID;
- panel_id = TMD_VID;
- } else {
- dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
- dev_priv->panel_id = TPO_CMD;
- panel_id = TPO_CMD;
- }
- } else {
- dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
- dev_priv->panel_id = panel_id;
- }
- }
-}
-
-int mid_chip_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- mid_get_fuse_settings(dev);
- mid_get_vbt_data(dev_priv);
- mid_get_pci_revID(dev_priv);
- return 0;
-}
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h
deleted file mode 100644
index 00e7d564b7eb..000000000000
--- a/drivers/staging/gma500/mid_bios.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-extern int mid_chip_setup(struct drm_device *dev);
-
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
deleted file mode 100644
index c904d73b1de3..000000000000
--- a/drivers/staging/gma500/mmu.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * 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 <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-
-/*
- * Code for the SGX MMU:
- */
-
-/*
- * clflush on one processor only:
- * clflush should apparently flush the cache line on all processors in an
- * SMP system.
- */
-
-/*
- * kmap atomic:
- * The usage of the slots must be completely encapsulated within a spinlock, and
- * no other functions that may be using the locks for other purposed may be
- * called from within the locked region.
- * Since the slots are per processor, this will guarantee that we are the only
- * user.
- */
-
-/*
- * TODO: Inserting ptes from an interrupt handler:
- * This may be desirable for some SGX functionality where the GPU can fault in
- * needed pages. For that, we need to make an atomic insert_pages function, that
- * may fail.
- * If it fails, the caller need to insert the page using a workqueue function,
- * but on average it should be fast.
- */
-
-struct psb_mmu_driver {
- /* protects driver- and pd structures. Always take in read mode
- * before taking the page table spinlock.
- */
- struct rw_semaphore sem;
-
- /* protects page tables, directory tables and pt tables.
- * and pt structures.
- */
- spinlock_t lock;
-
- atomic_t needs_tlbflush;
-
- uint8_t __iomem *register_map;
- struct psb_mmu_pd *default_pd;
- /*uint32_t bif_ctrl;*/
- int has_clflush;
- int clflush_add;
- unsigned long clflush_mask;
-
- struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
- struct psb_mmu_pd *pd;
- uint32_t index;
- uint32_t count;
- struct page *p;
- uint32_t *v;
-};
-
-struct psb_mmu_pd {
- struct psb_mmu_driver *driver;
- int hw_context;
- struct psb_mmu_pt **tables;
- struct page *p;
- struct page *dummy_pt;
- struct page *dummy_page;
- uint32_t pd_mask;
- uint32_t invalid_pde;
- uint32_t invalid_pte;
-};
-
-static inline uint32_t psb_mmu_pt_index(uint32_t offset)
-{
- return (offset >> PSB_PTE_SHIFT) & 0x3FF;
-}
-
-static inline uint32_t psb_mmu_pd_index(uint32_t offset)
-{
- return offset >> PSB_PDE_SHIFT;
-}
-
-static inline void psb_clflush(void *addr)
-{
- __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
-}
-
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
- void *addr)
-{
- if (!driver->has_clflush)
- return;
-
- mb();
- psb_clflush(addr);
- mb();
-}
-
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
-{
- uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
- uint32_t clflush_count = PAGE_SIZE / clflush_add;
- int i;
- uint8_t *clf;
-
- clf = kmap_atomic(page, KM_USER0);
- mb();
- for (i = 0; i < clflush_count; ++i) {
- psb_clflush(clf);
- clf += clflush_add;
- }
- mb();
- kunmap_atomic(clf, KM_USER0);
-}
-
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
- struct page *page[], unsigned long num_pages)
-{
- int i;
-
- if (!driver->has_clflush)
- return ;
-
- for (i = 0; i < num_pages; i++)
- psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
- int force)
-{
- atomic_set(&driver->needs_tlbflush, 0);
-}
-
-static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
-{
- down_write(&driver->sem);
- psb_mmu_flush_pd_locked(driver, force);
- up_write(&driver->sem);
-}
-
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
-{
- if (rc_prot)
- down_write(&driver->sem);
- if (rc_prot)
- up_write(&driver->sem);
-}
-
-void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
-{
- /*ttm_tt_cache_flush(&pd->p, 1);*/
- psb_pages_clflush(pd->driver, &pd->p, 1);
- down_write(&pd->driver->sem);
- wmb();
- psb_mmu_flush_pd_locked(pd->driver, 1);
- pd->hw_context = hw_context;
- up_write(&pd->driver->sem);
-
-}
-
-static inline unsigned long psb_pd_addr_end(unsigned long addr,
- unsigned long end)
-{
-
- addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
- return (addr < end) ? addr : end;
-}
-
-static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
-{
- uint32_t mask = PSB_PTE_VALID;
-
- if (type & PSB_MMU_CACHED_MEMORY)
- mask |= PSB_PTE_CACHED;
- if (type & PSB_MMU_RO_MEMORY)
- mask |= PSB_PTE_RO;
- if (type & PSB_MMU_WO_MEMORY)
- mask |= PSB_PTE_WO;
-
- return (pfn << PAGE_SHIFT) | mask;
-}
-
-struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
- int trap_pagefaults, int invalid_type)
-{
- struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
- uint32_t *v;
- int i;
-
- if (!pd)
- return NULL;
-
- pd->p = alloc_page(GFP_DMA32);
- if (!pd->p)
- goto out_err1;
- pd->dummy_pt = alloc_page(GFP_DMA32);
- if (!pd->dummy_pt)
- goto out_err2;
- pd->dummy_page = alloc_page(GFP_DMA32);
- if (!pd->dummy_page)
- goto out_err3;
-
- if (!trap_pagefaults) {
- pd->invalid_pde =
- psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
- invalid_type);
- pd->invalid_pte =
- psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
- invalid_type);
- } else {
- pd->invalid_pde = 0;
- pd->invalid_pte = 0;
- }
-
- v = kmap(pd->dummy_pt);
- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
- v[i] = pd->invalid_pte;
-
- kunmap(pd->dummy_pt);
-
- v = kmap(pd->p);
- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
- v[i] = pd->invalid_pde;
-
- kunmap(pd->p);
-
- clear_page(kmap(pd->dummy_page));
- kunmap(pd->dummy_page);
-
- pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
- if (!pd->tables)
- goto out_err4;
-
- pd->hw_context = -1;
- pd->pd_mask = PSB_PTE_VALID;
- pd->driver = driver;
-
- return pd;
-
-out_err4:
- __free_page(pd->dummy_page);
-out_err3:
- __free_page(pd->dummy_pt);
-out_err2:
- __free_page(pd->p);
-out_err1:
- kfree(pd);
- return NULL;
-}
-
-void psb_mmu_free_pt(struct psb_mmu_pt *pt)
-{
- __free_page(pt->p);
- kfree(pt);
-}
-
-void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
-{
- struct psb_mmu_driver *driver = pd->driver;
- struct psb_mmu_pt *pt;
- int i;
-
- down_write(&driver->sem);
- if (pd->hw_context != -1)
- psb_mmu_flush_pd_locked(driver, 1);
-
- /* Should take the spinlock here, but we don't need to do that
- since we have the semaphore in write mode. */
-
- for (i = 0; i < 1024; ++i) {
- pt = pd->tables[i];
- if (pt)
- psb_mmu_free_pt(pt);
- }
-
- vfree(pd->tables);
- __free_page(pd->dummy_page);
- __free_page(pd->dummy_pt);
- __free_page(pd->p);
- kfree(pd);
- up_write(&driver->sem);
-}
-
-static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
-{
- struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
- void *v;
- uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
- uint32_t clflush_count = PAGE_SIZE / clflush_add;
- spinlock_t *lock = &pd->driver->lock;
- uint8_t *clf;
- uint32_t *ptes;
- int i;
-
- if (!pt)
- return NULL;
-
- pt->p = alloc_page(GFP_DMA32);
- if (!pt->p) {
- kfree(pt);
- return NULL;
- }
-
- spin_lock(lock);
-
- v = kmap_atomic(pt->p, KM_USER0);
- clf = (uint8_t *) v;
- ptes = (uint32_t *) v;
- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
- *ptes++ = pd->invalid_pte;
-
-
- if (pd->driver->has_clflush && pd->hw_context != -1) {
- mb();
- for (i = 0; i < clflush_count; ++i) {
- psb_clflush(clf);
- clf += clflush_add;
- }
- mb();
- }
-
- kunmap_atomic(v, KM_USER0);
- spin_unlock(lock);
-
- pt->count = 0;
- pt->pd = pd;
- pt->index = 0;
-
- return pt;
-}
-
-struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
- unsigned long addr)
-{
- uint32_t index = psb_mmu_pd_index(addr);
- struct psb_mmu_pt *pt;
- uint32_t *v;
- spinlock_t *lock = &pd->driver->lock;
-
- spin_lock(lock);
- pt = pd->tables[index];
- while (!pt) {
- spin_unlock(lock);
- pt = psb_mmu_alloc_pt(pd);
- if (!pt)
- return NULL;
- spin_lock(lock);
-
- if (pd->tables[index]) {
- spin_unlock(lock);
- psb_mmu_free_pt(pt);
- spin_lock(lock);
- pt = pd->tables[index];
- continue;
- }
-
- v = kmap_atomic(pd->p, KM_USER0);
- pd->tables[index] = pt;
- v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
- pt->index = index;
- kunmap_atomic((void *) v, KM_USER0);
-
- if (pd->hw_context != -1) {
- psb_mmu_clflush(pd->driver, (void *) &v[index]);
- atomic_set(&pd->driver->needs_tlbflush, 1);
- }
- }
- pt->v = kmap_atomic(pt->p, KM_USER0);
- return pt;
-}
-
-static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
- unsigned long addr)
-{
- uint32_t index = psb_mmu_pd_index(addr);
- struct psb_mmu_pt *pt;
- spinlock_t *lock = &pd->driver->lock;
-
- spin_lock(lock);
- pt = pd->tables[index];
- if (!pt) {
- spin_unlock(lock);
- return NULL;
- }
- pt->v = kmap_atomic(pt->p, KM_USER0);
- return pt;
-}
-
-static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
-{
- struct psb_mmu_pd *pd = pt->pd;
- uint32_t *v;
-
- kunmap_atomic(pt->v, KM_USER0);
- if (pt->count == 0) {
- v = kmap_atomic(pd->p, KM_USER0);
- v[pt->index] = pd->invalid_pde;
- pd->tables[pt->index] = NULL;
-
- if (pd->hw_context != -1) {
- psb_mmu_clflush(pd->driver,
- (void *) &v[pt->index]);
- atomic_set(&pd->driver->needs_tlbflush, 1);
- }
- kunmap_atomic(pt->v, KM_USER0);
- spin_unlock(&pd->driver->lock);
- psb_mmu_free_pt(pt);
- return;
- }
- spin_unlock(&pd->driver->lock);
-}
-
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
- unsigned long addr, uint32_t pte)
-{
- pt->v[psb_mmu_pt_index(addr)] = pte;
-}
-
-static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
- unsigned long addr)
-{
- pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
-}
-
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
- uint32_t mmu_offset, uint32_t gtt_start,
- uint32_t gtt_pages)
-{
- uint32_t *v;
- uint32_t start = psb_mmu_pd_index(mmu_offset);
- struct psb_mmu_driver *driver = pd->driver;
- int num_pages = gtt_pages;
-
- down_read(&driver->sem);
- spin_lock(&driver->lock);
-
- v = kmap_atomic(pd->p, KM_USER0);
- v += start;
-
- while (gtt_pages--) {
- *v++ = gtt_start | pd->pd_mask;
- gtt_start += PAGE_SIZE;
- }
-
- /*ttm_tt_cache_flush(&pd->p, num_pages);*/
- psb_pages_clflush(pd->driver, &pd->p, num_pages);
- kunmap_atomic(v, KM_USER0);
- spin_unlock(&driver->lock);
-
- if (pd->hw_context != -1)
- atomic_set(&pd->driver->needs_tlbflush, 1);
-
- up_read(&pd->driver->sem);
- psb_mmu_flush_pd(pd->driver, 0);
-}
-
-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
-{
- struct psb_mmu_pd *pd;
-
- /* down_read(&driver->sem); */
- pd = driver->default_pd;
- /* up_read(&driver->sem); */
-
- return pd;
-}
-
-/* Returns the physical address of the PD shared by sgx/msvdx */
-uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
-{
- struct psb_mmu_pd *pd;
-
- pd = psb_mmu_get_default_pd(driver);
- return page_to_pfn(pd->p) << PAGE_SHIFT;
-}
-
-void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
-{
- psb_mmu_free_pagedir(driver->default_pd);
- kfree(driver);
-}
-
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
- int trap_pagefaults,
- int invalid_type,
- struct drm_psb_private *dev_priv)
-{
- struct psb_mmu_driver *driver;
-
- driver = kmalloc(sizeof(*driver), GFP_KERNEL);
-
- if (!driver)
- return NULL;
- driver->dev_priv = dev_priv;
-
- driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
- invalid_type);
- if (!driver->default_pd)
- goto out_err1;
-
- spin_lock_init(&driver->lock);
- init_rwsem(&driver->sem);
- down_write(&driver->sem);
- driver->register_map = registers;
- atomic_set(&driver->needs_tlbflush, 1);
-
- driver->has_clflush = 0;
-
- if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
- uint32_t tfms, misc, cap0, cap4, clflush_size;
-
- /*
- * clflush size is determined at kernel setup for x86_64
- * but not for i386. We have to do it here.
- */
-
- cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
- clflush_size = ((misc >> 8) & 0xff) * 8;
- driver->has_clflush = 1;
- driver->clflush_add =
- PAGE_SIZE * clflush_size / sizeof(uint32_t);
- driver->clflush_mask = driver->clflush_add - 1;
- driver->clflush_mask = ~driver->clflush_mask;
- }
-
- up_write(&driver->sem);
- return driver;
-
-out_err1:
- kfree(driver);
- return NULL;
-}
-
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride)
-{
- struct psb_mmu_pt *pt;
- uint32_t rows = 1;
- uint32_t i;
- unsigned long addr;
- unsigned long end;
- unsigned long next;
- unsigned long add;
- unsigned long row_add;
- unsigned long clflush_add = pd->driver->clflush_add;
- unsigned long clflush_mask = pd->driver->clflush_mask;
-
- if (!pd->driver->has_clflush) {
- /*ttm_tt_cache_flush(&pd->p, num_pages);*/
- psb_pages_clflush(pd->driver, &pd->p, num_pages);
- return;
- }
-
- if (hw_tile_stride)
- rows = num_pages / desired_tile_stride;
- else
- desired_tile_stride = num_pages;
-
- add = desired_tile_stride << PAGE_SHIFT;
- row_add = hw_tile_stride << PAGE_SHIFT;
- mb();
- for (i = 0; i < rows; ++i) {
-
- addr = address;
- end = addr + add;
-
- do {
- next = psb_pd_addr_end(addr, end);
- pt = psb_mmu_pt_map_lock(pd, addr);
- if (!pt)
- continue;
- do {
- psb_clflush(&pt->v
- [psb_mmu_pt_index(addr)]);
- } while (addr +=
- clflush_add,
- (addr & clflush_mask) < next);
-
- psb_mmu_pt_unmap_unlock(pt);
- } while (addr = next, next != end);
- address += row_add;
- }
- mb();
-}
-
-void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
- unsigned long address, uint32_t num_pages)
-{
- struct psb_mmu_pt *pt;
- unsigned long addr;
- unsigned long end;
- unsigned long next;
- unsigned long f_address = address;
-
- down_read(&pd->driver->sem);
-
- addr = address;
- end = addr + (num_pages << PAGE_SHIFT);
-
- do {
- next = psb_pd_addr_end(addr, end);
- pt = psb_mmu_pt_alloc_map_lock(pd, addr);
- if (!pt)
- goto out;
- do {
- psb_mmu_invalidate_pte(pt, addr);
- --pt->count;
- } while (addr += PAGE_SIZE, addr < next);
- psb_mmu_pt_unmap_unlock(pt);
-
- } while (addr = next, next != end);
-
-out:
- if (pd->hw_context != -1)
- psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
- up_read(&pd->driver->sem);
-
- if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 0);
-
- return;
-}
-
-void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
- uint32_t num_pages, uint32_t desired_tile_stride,
- uint32_t hw_tile_stride)
-{
- struct psb_mmu_pt *pt;
- uint32_t rows = 1;
- uint32_t i;
- unsigned long addr;
- unsigned long end;
- unsigned long next;
- unsigned long add;
- unsigned long row_add;
- unsigned long f_address = address;
-
- if (hw_tile_stride)
- rows = num_pages / desired_tile_stride;
- else
- desired_tile_stride = num_pages;
-
- add = desired_tile_stride << PAGE_SHIFT;
- row_add = hw_tile_stride << PAGE_SHIFT;
-
- /* down_read(&pd->driver->sem); */
-
- /* Make sure we only need to flush this processor's cache */
-
- for (i = 0; i < rows; ++i) {
-
- addr = address;
- end = addr + add;
-
- do {
- next = psb_pd_addr_end(addr, end);
- pt = psb_mmu_pt_map_lock(pd, addr);
- if (!pt)
- continue;
- do {
- psb_mmu_invalidate_pte(pt, addr);
- --pt->count;
-
- } while (addr += PAGE_SIZE, addr < next);
- psb_mmu_pt_unmap_unlock(pt);
-
- } while (addr = next, next != end);
- address += row_add;
- }
- if (pd->hw_context != -1)
- psb_mmu_flush_ptes(pd, f_address, num_pages,
- desired_tile_stride, hw_tile_stride);
-
- /* up_read(&pd->driver->sem); */
-
- if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 0);
-}
-
-int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
- unsigned long address, uint32_t num_pages,
- int type)
-{
- struct psb_mmu_pt *pt;
- uint32_t pte;
- unsigned long addr;
- unsigned long end;
- unsigned long next;
- unsigned long f_address = address;
- int ret = 0;
-
- down_read(&pd->driver->sem);
-
- addr = address;
- end = addr + (num_pages << PAGE_SHIFT);
-
- do {
- next = psb_pd_addr_end(addr, end);
- pt = psb_mmu_pt_alloc_map_lock(pd, addr);
- if (!pt) {
- ret = -ENOMEM;
- goto out;
- }
- do {
- pte = psb_mmu_mask_pte(start_pfn++, type);
- psb_mmu_set_pte(pt, addr, pte);
- pt->count++;
- } while (addr += PAGE_SIZE, addr < next);
- psb_mmu_pt_unmap_unlock(pt);
-
- } while (addr = next, next != end);
-
-out:
- if (pd->hw_context != -1)
- psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
- up_read(&pd->driver->sem);
-
- if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 1);
-
- return ret;
-}
-
-int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride, int type)
-{
- struct psb_mmu_pt *pt;
- uint32_t rows = 1;
- uint32_t i;
- uint32_t pte;
- unsigned long addr;
- unsigned long end;
- unsigned long next;
- unsigned long add;
- unsigned long row_add;
- unsigned long f_address = address;
- int ret = 0;
-
- if (hw_tile_stride) {
- if (num_pages % desired_tile_stride != 0)
- return -EINVAL;
- rows = num_pages / desired_tile_stride;
- } else {
- desired_tile_stride = num_pages;
- }
-
- add = desired_tile_stride << PAGE_SHIFT;
- row_add = hw_tile_stride << PAGE_SHIFT;
-
- down_read(&pd->driver->sem);
-
- for (i = 0; i < rows; ++i) {
-
- addr = address;
- end = addr + add;
-
- do {
- next = psb_pd_addr_end(addr, end);
- pt = psb_mmu_pt_alloc_map_lock(pd, addr);
- if (!pt) {
- ret = -ENOMEM;
- goto out;
- }
- do {
- pte =
- psb_mmu_mask_pte(page_to_pfn(*pages++),
- type);
- psb_mmu_set_pte(pt, addr, pte);
- pt->count++;
- } while (addr += PAGE_SIZE, addr < next);
- psb_mmu_pt_unmap_unlock(pt);
-
- } while (addr = next, next != end);
-
- address += row_add;
- }
-out:
- if (pd->hw_context != -1)
- psb_mmu_flush_ptes(pd, f_address, num_pages,
- desired_tile_stride, hw_tile_stride);
-
- up_read(&pd->driver->sem);
-
- if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 1);
-
- return ret;
-}
-
-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
- unsigned long *pfn)
-{
- int ret;
- struct psb_mmu_pt *pt;
- uint32_t tmp;
- spinlock_t *lock = &pd->driver->lock;
-
- down_read(&pd->driver->sem);
- pt = psb_mmu_pt_map_lock(pd, virtual);
- if (!pt) {
- uint32_t *v;
-
- spin_lock(lock);
- v = kmap_atomic(pd->p, KM_USER0);
- tmp = v[psb_mmu_pd_index(virtual)];
- kunmap_atomic(v, KM_USER0);
- spin_unlock(lock);
-
- if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
- !(pd->invalid_pte & PSB_PTE_VALID)) {
- ret = -EINVAL;
- goto out;
- }
- ret = 0;
- *pfn = pd->invalid_pte >> PAGE_SHIFT;
- goto out;
- }
- tmp = pt->v[psb_mmu_pt_index(virtual)];
- if (!(tmp & PSB_PTE_VALID)) {
- ret = -EINVAL;
- } else {
- ret = 0;
- *pfn = tmp >> PAGE_SHIFT;
- }
- psb_mmu_pt_unmap_unlock(pt);
-out:
- up_read(&pd->driver->sem);
- return ret;
-}
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
deleted file mode 100644
index b563dbc73104..000000000000
--- a/drivers/staging/gma500/mrst.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-/* MID device specific descriptors */
-
-struct mrst_vbt {
- s8 signature[4]; /*4 bytes,"$GCT" */
- u8 revision;
- u8 size;
- u8 checksum;
- void *mrst_gct;
-} __packed;
-
-struct mrst_timing_info {
- u16 pixel_clock;
- u8 hactive_lo;
- u8 hblank_lo;
- u8 hblank_hi:4;
- u8 hactive_hi:4;
- u8 vactive_lo;
- u8 vblank_lo;
- u8 vblank_hi:4;
- u8 vactive_hi:4;
- u8 hsync_offset_lo;
- u8 hsync_pulse_width_lo;
- u8 vsync_pulse_width_lo:4;
- u8 vsync_offset_lo:4;
- u8 vsync_pulse_width_hi:2;
- u8 vsync_offset_hi:2;
- u8 hsync_pulse_width_hi:2;
- u8 hsync_offset_hi:2;
- u8 width_mm_lo;
- u8 height_mm_lo;
- u8 height_mm_hi:4;
- u8 width_mm_hi:4;
- u8 hborder;
- u8 vborder;
- u8 unknown0:1;
- u8 hsync_positive:1;
- u8 vsync_positive:1;
- u8 separate_sync:2;
- u8 stereo:1;
- u8 unknown6:1;
- u8 interlaced:1;
-} __packed;
-
-struct gct_r10_timing_info {
- u16 pixel_clock;
- u32 hactive_lo:8;
- u32 hactive_hi:4;
- u32 hblank_lo:8;
- u32 hblank_hi:4;
- u32 hsync_offset_lo:8;
- u16 hsync_offset_hi:2;
- u16 hsync_pulse_width_lo:8;
- u16 hsync_pulse_width_hi:2;
- u16 hsync_positive:1;
- u16 rsvd_1:3;
- u8 vactive_lo:8;
- u16 vactive_hi:4;
- u16 vblank_lo:8;
- u16 vblank_hi:4;
- u16 vsync_offset_lo:4;
- u16 vsync_offset_hi:2;
- u16 vsync_pulse_width_lo:4;
- u16 vsync_pulse_width_hi:2;
- u16 vsync_positive:1;
- u16 rsvd_2:3;
-} __packed;
-
-struct mrst_panel_descriptor_v1 {
- u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
- /* 0x61190 if MIPI */
- u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
- u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
- u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */
- /* Register 0x61210 */
- struct mrst_timing_info DTD;/*18 bytes, Standard definition */
- u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */
- /* Bit 0, Frequency, 15 bits,0 - 32767Hz */
- /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */
- u16 Panel_MIPI_Display_Descriptor;
- /*16 bits, Defined as follows: */
- /* if MIPI, 0x0000 if LVDS */
- /* Bit 0, Type, 2 bits, */
- /* 0: Type-1, */
- /* 1: Type-2, */
- /* 2: Type-3, */
- /* 3: Type-4 */
- /* Bit 2, Pixel Format, 4 bits */
- /* Bit0: 16bpp (not supported in LNC), */
- /* Bit1: 18bpp loosely packed, */
- /* Bit2: 18bpp packed, */
- /* Bit3: 24bpp */
- /* Bit 6, Reserved, 2 bits, 00b */
- /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
- /* Bit 14, Reserved, 2 bits, 00b */
-} __packed;
-
-struct mrst_panel_descriptor_v2 {
- u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
- /* 0x61190 if MIPI */
- u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
- u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
- u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */
- /* Register 0x61210 */
- struct mrst_timing_info DTD;/*18 bytes, Standard definition */
- u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/
- /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/
- u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */
- /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/
- u16 Panel_MIPI_Display_Descriptor;
- /*16 bits, Defined as follows: */
- /* if MIPI, 0x0000 if LVDS */
- /* Bit 0, Type, 2 bits, */
- /* 0: Type-1, */
- /* 1: Type-2, */
- /* 2: Type-3, */
- /* 3: Type-4 */
- /* Bit 2, Pixel Format, 4 bits */
- /* Bit0: 16bpp (not supported in LNC), */
- /* Bit1: 18bpp loosely packed, */
- /* Bit2: 18bpp packed, */
- /* Bit3: 24bpp */
- /* Bit 6, Reserved, 2 bits, 00b */
- /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
- /* Bit 14, Reserved, 2 bits, 00b */
-} __packed;
-
-union mrst_panel_rx {
- struct {
- u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
- /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
- u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
- /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/
- u16 SupportedVideoTransferMode:2; /*0: Non-burst only */
- /* 1: Burst and non-burst */
- /* 2/3: Reserved */
- u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/
- u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/
- u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/
- u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */
- u16 Rsvd:5;/*5 bits,00000b */
- } panelrx;
- u16 panel_receiver;
-} __packed;
-
-struct mrst_gct_v1 {
- union { /*8 bits,Defined as follows: */
- struct {
- u8 PanelType:4; /*4 bits, Bit field for panels*/
- /* 0 - 3: 0 = LVDS, 1 = MIPI*/
- /*2 bits,Specifies which of the*/
- u8 BootPanelIndex:2;
- /* 4 panels to use by default*/
- u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
- /* the 4 MIPI DSI receivers to use*/
- } PD;
- u8 PanelDescriptor;
- };
- struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
- union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __packed;
-
-struct mrst_gct_v2 {
- union { /*8 bits,Defined as follows: */
- struct {
- u8 PanelType:4; /*4 bits, Bit field for panels*/
- /* 0 - 3: 0 = LVDS, 1 = MIPI*/
- /*2 bits,Specifies which of the*/
- u8 BootPanelIndex:2;
- /* 4 panels to use by default*/
- u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
- /* the 4 MIPI DSI receivers to use*/
- } PD;
- u8 PanelDescriptor;
- };
- struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
- union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __packed;
-
-struct mrst_gct_data {
- u8 bpi; /* boot panel index, number of panel used during boot */
- u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */
- struct mrst_timing_info DTD; /* timing info for the selected panel */
- u32 Panel_Port_Control;
- u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/
- u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/
- u32 PP_Cycle_Delay;
- u16 Panel_Backlight_Inverter_Descriptor;
- u16 Panel_MIPI_Display_Descriptor;
-} __packed;
-
-#define MODE_SETTING_IN_CRTC 0x1
-#define MODE_SETTING_IN_ENCODER 0x2
-#define MODE_SETTING_ON_GOING 0x3
-#define MODE_SETTING_IN_DSR 0x4
-#define MODE_SETTING_ENCODER_DONE 0x8
-
-#define GCT_R10_HEADER_SIZE 16
-#define GCT_R10_DISPLAY_DESC_SIZE 28
-
-/*
- * Moorestown HDMI interfaces
- */
-
-struct mrst_hdmi_dev {
- struct pci_dev *dev;
- void __iomem *regs;
- unsigned int mmio, mmio_len;
- int dpms_mode;
- struct hdmi_i2c_dev *i2c_dev;
-
- /* register state */
- u32 saveDPLL_CTRL;
- u32 saveDPLL_DIV_CTRL;
- u32 saveDPLL_ADJUST;
- u32 saveDPLL_UPDATE;
- u32 saveDPLL_CLK_ENABLE;
- u32 savePCH_HTOTAL_B;
- u32 savePCH_HBLANK_B;
- u32 savePCH_HSYNC_B;
- u32 savePCH_VTOTAL_B;
- u32 savePCH_VBLANK_B;
- u32 savePCH_VSYNC_B;
- u32 savePCH_PIPEBCONF;
- u32 savePCH_PIPEBSRC;
-};
-
-extern void mrst_hdmi_setup(struct drm_device *dev);
-extern void mrst_hdmi_teardown(struct drm_device *dev);
-extern int mrst_hdmi_i2c_init(struct pci_dev *dev);
-extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
-extern void mrst_hdmi_save(struct drm_device *dev);
-extern void mrst_hdmi_restore(struct drm_device *dev);
-extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
deleted file mode 100644
index 980837e37d80..000000000000
--- a/drivers/staging/gma500/mrst_crtc.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- *
- * 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/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-
-struct psb_intel_range_t {
- int min, max;
-};
-
-struct mrst_limit_t {
- struct psb_intel_range_t dot, m, p1;
-};
-
-struct mrst_clock_t {
- /* derived values */
- int dot;
- int m;
- int p1;
-};
-
-#define MRST_LIMIT_LVDS_100L 0
-#define MRST_LIMIT_LVDS_83 1
-#define MRST_LIMIT_LVDS_100 2
-
-#define MRST_DOT_MIN 19750
-#define MRST_DOT_MAX 120000
-#define MRST_M_MIN_100L 20
-#define MRST_M_MIN_100 10
-#define MRST_M_MIN_83 12
-#define MRST_M_MAX_100L 34
-#define MRST_M_MAX_100 17
-#define MRST_M_MAX_83 20
-#define MRST_P1_MIN 2
-#define MRST_P1_MAX_0 7
-#define MRST_P1_MAX_1 8
-
-static const struct mrst_limit_t mrst_limits[] = {
- { /* MRST_LIMIT_LVDS_100L */
- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
- .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L},
- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
- },
- { /* MRST_LIMIT_LVDS_83L */
- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
- .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83},
- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0},
- },
- { /* MRST_LIMIT_LVDS_100 */
- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
- .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100},
- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
- },
-};
-
-#define MRST_M_MIN 10
-static const u32 mrst_m_converts[] = {
- 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,
- 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,
- 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,
-};
-
-static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
-{
- const struct mrst_limit_t *limit = NULL;
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
- switch (dev_priv->core_freq) {
- case 100:
- limit = &mrst_limits[MRST_LIMIT_LVDS_100L];
- break;
- case 166:
- limit = &mrst_limits[MRST_LIMIT_LVDS_83];
- break;
- case 200:
- limit = &mrst_limits[MRST_LIMIT_LVDS_100];
- break;
- }
- } else {
- limit = NULL;
- dev_err(dev->dev, "mrst_limit Wrong display type.\n");
- }
-
- return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-static void mrst_clock(int refclk, struct mrst_clock_t *clock)
-{
- clock->dot = (refclk * clock->m) / (14 * clock->p1);
-}
-
-void mrstPrintPll(char *prefix, struct mrst_clock_t *clock)
-{
- pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n",
- prefix, clock->dot, clock->m, clock->p1);
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given refclk,
- * or FALSE. Divisor values are the actual divisors for
- */
-static bool
-mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
- struct mrst_clock_t *best_clock)
-{
- struct mrst_clock_t clock;
- const struct mrst_limit_t *limit = mrst_limit(crtc);
- int err = target;
-
- memset(best_clock, 0, sizeof(*best_clock));
-
- for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
- for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- mrst_clock(refclk, &clock);
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
- return err != target;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- u32 temp;
- bool enabled;
-
- if (!gma_power_begin(dev, true))
- return;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- /* Enable the DPLL */
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) == 0) {
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- }
- /* Enable the pipe */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) == 0)
- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
- /* Enable the plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
- REG_WRITE(dspcntr_reg,
- temp | DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- }
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
- /* Disable display plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(dspcntr_reg,
- temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
- }
-
- /* Next, disable display pipes */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
- REG_READ(pipeconf_reg);
- }
- /* Wait for for the pipe disable to take effect. */
- psb_intel_wait_for_vblank(dev);
-
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) != 0) {
- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- }
-
- /* Wait for the clocks to turn off. */
- udelay(150);
- break;
- }
-
- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
- /*Set FIFO Watermarks*/
- REG_WRITE(DSPARB, 0x3FFF);
- REG_WRITE(DSPFW1, 0x3F88080A);
- REG_WRITE(DSPFW2, 0x0b060808);
- REG_WRITE(DSPFW3, 0x0);
- REG_WRITE(DSPFW4, 0x08030404);
- REG_WRITE(DSPFW5, 0x04040404);
- REG_WRITE(DSPFW6, 0x78);
- REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000);
- /* Must write Bit 14 of the Chicken Bit Register */
-
- gma_power_end(dev);
-}
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int mrst_panel_fitter_pipe(struct drm_device *dev)
-{
- u32 pfit_control;
-
- pfit_control = REG_READ(PFIT_CONTROL);
-
- /* See if the panel fitter is in use */
- if ((pfit_control & PFIT_ENABLE) == 0)
- return -1;
- return (pfit_control >> 29) & 3;
-}
-
-static int mrst_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = psb_intel_crtc->pipe;
- int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0;
- int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
- int refclk = 0;
- struct mrst_clock_t clock;
- u32 dpll = 0, fp = 0, dspcntr, pipeconf;
- bool ok, is_sdvo = false;
- bool is_crt = false, is_lvds = false, is_tv = false;
- bool is_mipi = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct psb_intel_output *psb_intel_output = NULL;
- uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
- struct drm_encoder *encoder;
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- memcpy(&psb_intel_crtc->saved_mode,
- mode,
- sizeof(struct drm_display_mode));
- memcpy(&psb_intel_crtc->saved_adjusted_mode,
- adjusted_mode,
- sizeof(struct drm_display_mode));
-
- list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-
- if (encoder->crtc != crtc)
- continue;
-
- psb_intel_output = enc_to_psb_intel_output(encoder);
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_LVDS:
- is_lvds = true;
- break;
- case INTEL_OUTPUT_SDVO:
- is_sdvo = true;
- break;
- case INTEL_OUTPUT_TVOUT:
- is_tv = true;
- break;
- case INTEL_OUTPUT_ANALOG:
- is_crt = true;
- break;
- case INTEL_OUTPUT_MIPI:
- is_mipi = true;
- break;
- }
- }
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Disable the panel fitter if it was on our pipe */
- if (mrst_panel_fitter_pipe(dev) == pipe)
- REG_WRITE(PFIT_CONTROL, 0);
-
- REG_WRITE(pipesrc_reg,
- ((mode->crtc_hdisplay - 1) << 16) |
- (mode->crtc_vdisplay - 1));
-
- if (psb_intel_output)
- drm_connector_property_get_value(&psb_intel_output->base,
- dev->mode_config.scaling_mode_property, &scalingType);
-
- if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
- /* Moorestown doesn't have register support for centering so
- * we need to mess with the h/vblank and h/vsync start and
- * ends to get centering */
- int offsetX = 0, offsetY = 0;
-
- offsetX = (adjusted_mode->crtc_hdisplay -
- mode->crtc_hdisplay) / 2;
- offsetY = (adjusted_mode->crtc_vdisplay -
- mode->crtc_vdisplay) / 2;
-
- REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(hblank_reg,
- (adjusted_mode->crtc_hblank_start - offsetX - 1) |
- ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
- REG_WRITE(hsync_reg,
- (adjusted_mode->crtc_hsync_start - offsetX - 1) |
- ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
- REG_WRITE(vblank_reg,
- (adjusted_mode->crtc_vblank_start - offsetY - 1) |
- ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
- REG_WRITE(vsync_reg,
- (adjusted_mode->crtc_vsync_start - offsetY - 1) |
- ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
- } else {
- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
- ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
- ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
- ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
- ((adjusted_mode->crtc_vsync_end - 1) << 16));
- }
-
- /* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs =
- crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
-
- /* setup pipeconf */
- pipeconf = REG_READ(pipeconf_reg);
-
- /* Set up the display plane register */
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr |= DISPPLANE_GAMMA_ENABLE;
-
- if (pipe == 0)
- dspcntr |= DISPPLANE_SEL_PIPE_A;
- else
- dspcntr |= DISPPLANE_SEL_PIPE_B;
-
- dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE;
- dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE;
-
- if (is_mipi)
- goto mrst_crtc_mode_set_exit;
-
- refclk = dev_priv->core_freq * 1000;
-
- dpll = 0; /*BIT16 = 0 for 100MHz reference */
-
- ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock);
-
- if (!ok) {
- dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
- } else {
- dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d,"
- "m = %x, p1 = %x.\n", clock.dot, clock.m,
- clock.p1);
- }
-
- fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8;
-
- dpll |= DPLL_VGA_MODE_DIS;
-
-
- dpll |= DPLL_VCO_ENABLE;
-
- if (is_lvds)
- dpll |= DPLLA_MODE_LVDS;
- else
- dpll |= DPLLB_MODE_DAC_SERIAL;
-
- if (is_sdvo) {
- int sdvo_pixel_multiply =
- adjusted_mode->clock / mode->clock;
-
- dpll |= DPLL_DVO_HIGH_SPEED;
- dpll |=
- (sdvo_pixel_multiply -
- 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
- }
-
-
- /* compute bitmask from p1 value */
- dpll |= (1 << (clock.p1 - 2)) << 17;
-
- dpll |= DPLL_VCO_ENABLE;
-
- mrstPrintPll("chosen", &clock);
-
- if (dpll & DPLL_VCO_ENABLE) {
- REG_WRITE(fp_reg, fp);
- REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Check the DPLLA lock bit PIPEACONF[29] */
- udelay(150);
- }
-
- REG_WRITE(fp_reg, fp);
- REG_WRITE(dpll_reg, dpll);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
-
- /* write it again -- the BIOS does, after all */
- REG_WRITE(dpll_reg, dpll);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
-
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
- psb_intel_wait_for_vblank(dev);
-
- REG_WRITE(dspcntr_reg, dspcntr);
- psb_intel_wait_for_vblank(dev);
-
-mrst_crtc_mode_set_exit:
- gma_power_end(dev);
- return 0;
-}
-
-static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-int mrst_pipe_set_base(struct drm_crtc *crtc,
- int x, int y, struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- unsigned long start, offset;
-
- int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- u32 dspcntr;
- int ret = 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_dbg(dev->dev, "No FB bound\n");
- return 0;
- }
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- goto pipe_set_base_exit;
- }
- REG_WRITE(dspcntr_reg, dspcntr);
-
- REG_WRITE(dspbase, offset);
- REG_READ(dspbase);
- REG_WRITE(dspsurf, start);
- REG_READ(dspsurf);
-
-pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
-}
-
-static void mrst_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void mrst_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-const struct drm_crtc_helper_funcs mrst_helper_funcs = {
- .dpms = mrst_crtc_dpms,
- .mode_fixup = mrst_crtc_mode_fixup,
- .mode_set = mrst_crtc_mode_set,
- .mode_set_base = mrst_pipe_set_base,
- .prepare = mrst_crtc_prepare,
- .commit = mrst_crtc_commit,
-};
-
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
deleted file mode 100644
index 6707fafbfa1e..000000000000
--- a/drivers/staging/gma500/mrst_device.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/backlight.h>
-#include <linux/module.h>
-#include <linux/dmi.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <asm/mrst.h>
-#include <asm/intel_scu_ipc.h>
-#include "mid_bios.h"
-
-static int devtype;
-
-module_param_named(type, devtype, int, 0600);
-MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
-
-#define DEVICE_MOORESTOWN 1
-#define DEVICE_OAKTRAIL 2
-#define DEVICE_MOORESTOWN_MM 3
-
-static int mrst_device_ident(struct drm_device *dev)
-{
- /* User forced */
- if (devtype)
- return devtype;
- if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") ||
- dmi_match(DMI_PRODUCT_NAME, "OakTrail platform"))
- return DEVICE_OAKTRAIL;
-#if defined(CONFIG_X86_MRST)
- if (dmi_match(DMI_PRODUCT_NAME, "MM") ||
- dmi_match(DMI_PRODUCT_NAME, "MM 10"))
- return DEVICE_MOORESTOWN_MM;
- if (mrst_identify_cpu())
- return DEVICE_MOORESTOWN;
-#endif
- return DEVICE_OAKTRAIL;
-}
-
-
-/* IPC message and command defines used to enable/disable mipi panel voltages */
-#define IPC_MSG_PANEL_ON_OFF 0xE9
-#define IPC_CMD_PANEL_ON 1
-#define IPC_CMD_PANEL_OFF 0
-
-static int mrst_output_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->iLVDS_enable)
- mrst_lvds_init(dev, &dev_priv->mode_dev);
- else
- dev_err(dev->dev, "DSI is not supported\n");
- if (dev_priv->hdmi_priv)
- mrst_hdmi_init(dev, &dev_priv->mode_dev);
- return 0;
-}
-
-/*
- * Provide the low level interfaces for the Moorestown backlight
- */
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-#define BLC_ADJUSTMENT_MAX 100
-
-static struct backlight_device *mrst_backlight_device;
-static int mrst_brightness;
-
-static int mrst_set_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(mrst_backlight_device);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int level = bd->props.brightness;
- u32 blc_pwm_ctl;
- u32 max_pwm_blc;
-
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
- if (gma_power_begin(dev, 0)) {
- /* Calculate and set the brightness value */
- max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
- blc_pwm_ctl = level * max_pwm_blc / 100;
-
- /* Adjust the backlight level with the percent in
- * dev_priv->blc_adj1;
- */
- blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
- blc_pwm_ctl = blc_pwm_ctl / 100;
-
- /* Adjust the backlight level with the percent in
- * dev_priv->blc_adj2;
- */
- blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
- blc_pwm_ctl = blc_pwm_ctl / 100;
-
- /* force PWM bit on */
- REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
- REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
- gma_power_end(dev);
- }
- mrst_brightness = level;
- return 0;
-}
-
-static int mrst_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return mrst_brightness;
-}
-
-static int device_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long core_clock;
- u16 bl_max_freq;
- uint32_t value;
- uint32_t blc_pwm_precision_factor;
-
- dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
- dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
- bl_max_freq = 256;
- /* this needs to be set elsewhere */
- blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
-
- core_clock = dev_priv->core_freq;
-
- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
- value *= blc_pwm_precision_factor;
- value /= bl_max_freq;
- value /= blc_pwm_precision_factor;
-
- if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
- return -ERANGE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
- REG_WRITE(BLC_PWM_CTL, value | (value << 16));
- gma_power_end(dev);
- }
- return 0;
-}
-
-static const struct backlight_ops mrst_ops = {
- .get_brightness = mrst_get_brightness,
- .update_status = mrst_set_brightness,
-};
-
-int mrst_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- mrst_backlight_device = backlight_device_register("mrst-bl",
- NULL, (void *)dev, &mrst_ops, &props);
-
- if (IS_ERR(mrst_backlight_device))
- return PTR_ERR(mrst_backlight_device);
-
- ret = device_backlight_init(dev);
- if (ret < 0) {
- backlight_device_unregister(mrst_backlight_device);
- return ret;
- }
- mrst_backlight_device->props.brightness = 100;
- mrst_backlight_device->props.max_brightness = 100;
- backlight_update_status(mrst_backlight_device);
- dev_priv->backlight_device = mrst_backlight_device;
- return 0;
-}
-
-#endif
-
-/*
- * Provide the Moorestown specific chip logic and low level methods
- * for power management
- */
-
-static void mrst_init_pm(struct drm_device *dev)
-{
-}
-
-/**
- * mrst_save_display_registers - save registers lost on suspend
- * @dev: our DRM device
- *
- * Save the state we need in order to be able to restore the interface
- * upon resume from suspend
- */
-static int mrst_save_display_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int i;
- u32 pp_stat;
-
- /* Display arbitration control + watermarks */
- dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
- dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
- dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
- dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
- dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
- dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
- dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
- dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
- /* Pipe & plane A info */
- dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
- dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
- dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
- dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
- dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
- dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
- dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
- dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
- dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
- dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
- dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
- dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
- dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
- dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
- dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
- dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
- dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
- dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
-
- /* Save cursor regs */
- dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
- dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
- dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
-
- /* Save palette (gamma) */
- for (i = 0; i < 256; i++)
- dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
-
- if (dev_priv->hdmi_priv)
- mrst_hdmi_save(dev);
-
- /* Save performance state */
- dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
-
- /* LVDS state */
- dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
- dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
- dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
- dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
- dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
- dev_priv->saveLVDS = PSB_RVDC32(LVDS);
- dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
- dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
- dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
- dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
-
- /* HW overlay */
- dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
- dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
- dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
- dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
- dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
- dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
- dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-
- /* DPST registers */
- dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
- PSB_RVDC32(HISTOGRAM_INT_CONTROL);
- dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
- PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
- dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
- if (dev_priv->iLVDS_enable) {
- /* Shut down the panel */
- PSB_WVDC32(0, PP_CONTROL);
-
- do {
- pp_stat = PSB_RVDC32(PP_STATUS);
- } while (pp_stat & 0x80000000);
-
- /* Turn off the plane */
- PSB_WVDC32(0x58000000, DSPACNTR);
- /* Trigger the plane disable */
- PSB_WVDC32(0, DSPASURF);
-
- /* Wait ~4 ticks */
- msleep(4);
-
- /* Turn off pipe */
- PSB_WVDC32(0x0, PIPEACONF);
- /* Wait ~8 ticks */
- msleep(8);
-
- /* Turn off PLLs */
- PSB_WVDC32(0, MRST_DPLL_A);
- }
- return 0;
-}
-
-/**
- * mrst_restore_display_registers - restore lost register state
- * @dev: our DRM device
- *
- * Restore register state that was lost during suspend and resume.
- */
-static int mrst_restore_display_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pp_stat;
- int i;
-
- /* Display arbitration + watermarks */
- PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
- PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
- PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
- PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
- PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
- PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
- PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
- PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
- /* Make sure VGA plane is off. it initializes to on after reset!*/
- PSB_WVDC32(0x80000000, VGACNTRL);
-
- /* set the plls */
- PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
- PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
-
- /* Actually enable it */
- PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
- DRM_UDELAY(150);
-
- /* Restore mode */
- PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
- PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
- PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
- PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
- PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
- PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
- PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
- PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
-
- /* Restore performance mode*/
- PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
-
- /* Enable the pipe*/
- if (dev_priv->iLVDS_enable)
- PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
-
- /* Set up the plane*/
- PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
- PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
- PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
-
- /* Enable the plane */
- PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
- PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
-
- /* Enable Cursor A */
- PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
- PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
- PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
-
- /* Restore palette (gamma) */
- for (i = 0; i < 256; i++)
- PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
-
- if (dev_priv->hdmi_priv)
- mrst_hdmi_restore(dev);
-
- if (dev_priv->iLVDS_enable) {
- PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
- PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
- PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
- PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
- PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
- PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
- PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
- PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
- PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
- PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
- }
-
- /* Wait for cycle delay */
- do {
- pp_stat = PSB_RVDC32(PP_STATUS);
- } while (pp_stat & 0x08000000);
-
- /* Wait for panel power up */
- do {
- pp_stat = PSB_RVDC32(PP_STATUS);
- } while (pp_stat & 0x10000000);
-
- /* Restore HW overlay */
- PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
- PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
- PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
- PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
- PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
- PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
- PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
-
- /* DPST registers */
- PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
- HISTOGRAM_INT_CONTROL);
- PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
- HISTOGRAM_LOGIC_CONTROL);
- PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
-
- return 0;
-}
-
-/**
- * mrst_power_down - power down the display island
- * @dev: our DRM device
- *
- * Power down the display interface of our device
- */
-static int mrst_power_down(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pwr_mask ;
- u32 pwr_sts;
-
- pwr_mask = PSB_PWRGT_DISPLAY_MASK;
- outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
-
- while (true) {
- pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
- if ((pwr_sts & pwr_mask) == pwr_mask)
- break;
- else
- udelay(10);
- }
- return 0;
-}
-
-/*
- * mrst_power_up
- *
- * Restore power to the specified island(s) (powergating)
- */
-static int mrst_power_up(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
- u32 pwr_sts, pwr_cnt;
-
- pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
- pwr_cnt &= ~pwr_mask;
- outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
-
- while (true) {
- pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
- if ((pwr_sts & pwr_mask) == 0)
- break;
- else
- udelay(10);
- }
- return 0;
-}
-
-#if defined(CONFIG_X86_MRST)
-static void mrst_lvds_cache_bl(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
- intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
- intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
-}
-
-static void mrst_mm_bl_power(struct drm_device *dev, bool on)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (on) {
- intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
- intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
- intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
- } else {
- intel_scu_ipc_iowrite8(0x2A, 0);
- intel_scu_ipc_iowrite8(0x28, 0);
- intel_scu_ipc_iowrite8(0x29, 0);
- }
-}
-
-static const struct psb_ops mrst_mm_chip_ops = {
- .name = "Moorestown MM ",
- .accel_2d = 1,
- .pipes = 1,
- .crtcs = 1,
- .sgx_offset = MRST_SGX_OFFSET,
-
- .crtc_helper = &mrst_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
-
- .output_init = mrst_output_init,
-
- .lvds_bl_power = mrst_mm_bl_power,
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = mrst_backlight_init,
-#endif
-
- .init_pm = mrst_init_pm,
- .save_regs = mrst_save_display_registers,
- .restore_regs = mrst_restore_display_registers,
- .power_down = mrst_power_down,
- .power_up = mrst_power_up,
-
- .i2c_bus = 0,
-};
-
-#endif
-
-static void oaktrail_teardown(struct drm_device *dev)
-{
- mrst_hdmi_teardown(dev);
-}
-
-static const struct psb_ops oaktrail_chip_ops = {
- .name = "Oaktrail",
- .accel_2d = 1,
- .pipes = 2,
- .crtcs = 2,
- .sgx_offset = MRST_SGX_OFFSET,
-
- .chip_setup = mid_chip_setup,
- .chip_teardown = oaktrail_teardown,
- .crtc_helper = &mrst_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
-
- .output_init = mrst_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = mrst_backlight_init,
-#endif
-
- .init_pm = mrst_init_pm,
- .save_regs = mrst_save_display_registers,
- .restore_regs = mrst_restore_display_registers,
- .power_down = mrst_power_down,
- .power_up = mrst_power_up,
-
- .i2c_bus = 1,
-};
-
-/**
- * mrst_chip_setup - perform the initial chip init
- * @dev: Our drm_device
- *
- * Figure out which incarnation we are and then scan the firmware for
- * tables and information.
- */
-static int mrst_chip_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- switch (mrst_device_ident(dev)) {
- case DEVICE_OAKTRAIL:
- /* Dual CRTC, PC compatible, HDMI, I2C #2 */
- dev_priv->ops = &oaktrail_chip_ops;
- mrst_hdmi_setup(dev);
- return mid_chip_setup(dev);
-#if defined(CONFIG_X86_MRST)
- case DEVICE_MOORESTOWN_MM:
- /* Single CRTC, No HDMI, I2C #0, BL control */
- mrst_lvds_cache_bl(dev);
- dev_priv->ops = &mrst_mm_chip_ops;
- return mid_chip_setup(dev);
- case DEVICE_MOORESTOWN:
- /* Dual CRTC, No HDMI(?), I2C #1 */
- return mid_chip_setup(dev);
-#endif
- default:
- dev_err(dev->dev, "unsupported device type.\n");
- return -ENODEV;
- }
-}
-
-const struct psb_ops mrst_chip_ops = {
- .name = "Moorestown",
- .accel_2d = 1,
- .pipes = 2,
- .crtcs = 2,
- .sgx_offset = MRST_SGX_OFFSET,
-
- .chip_setup = mrst_chip_setup,
- .crtc_helper = &mrst_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
-
- .output_init = mrst_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = mrst_backlight_init,
-#endif
-
- .init_pm = mrst_init_pm,
- .save_regs = mrst_save_display_registers,
- .restore_regs = mrst_restore_display_registers,
- .power_down = mrst_power_down,
- .power_up = mrst_power_up,
-
- .i2c_bus = 2,
-};
-
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c
deleted file mode 100644
index e66607eb3d3e..000000000000
--- a/drivers/staging/gma500/mrst_hdmi.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Li Peng <peng.li@intel.com>
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_drv.h"
-
-#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
-#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
-
-#define HDMI_HCR 0x1000
-#define HCR_ENABLE_HDCP (1 << 5)
-#define HCR_ENABLE_AUDIO (1 << 2)
-#define HCR_ENABLE_PIXEL (1 << 1)
-#define HCR_ENABLE_TMDS (1 << 0)
-
-#define HDMI_HICR 0x1004
-#define HDMI_HSR 0x1008
-#define HDMI_HISR 0x100C
-#define HDMI_DETECT_HDP (1 << 0)
-
-#define HDMI_VIDEO_REG 0x3000
-#define HDMI_UNIT_EN (1 << 7)
-#define HDMI_MODE_OUTPUT (1 << 0)
-#define HDMI_HBLANK_A 0x3100
-
-#define HDMI_AUDIO_CTRL 0x4000
-#define HDMI_ENABLE_AUDIO (1 << 0)
-
-#define PCH_HTOTAL_B 0x3100
-#define PCH_HBLANK_B 0x3104
-#define PCH_HSYNC_B 0x3108
-#define PCH_VTOTAL_B 0x310C
-#define PCH_VBLANK_B 0x3110
-#define PCH_VSYNC_B 0x3114
-#define PCH_PIPEBSRC 0x311C
-
-#define PCH_PIPEB_DSL 0x3800
-#define PCH_PIPEB_SLC 0x3804
-#define PCH_PIPEBCONF 0x3808
-#define PCH_PIPEBSTAT 0x3824
-
-#define CDVO_DFT 0x5000
-#define CDVO_SLEWRATE 0x5004
-#define CDVO_STRENGTH 0x5008
-#define CDVO_RCOMP 0x500C
-
-#define DPLL_CTRL 0x6000
-#define DPLL_PDIV_SHIFT 16
-#define DPLL_PDIV_MASK (0xf << 16)
-#define DPLL_PWRDN (1 << 4)
-#define DPLL_RESET (1 << 3)
-#define DPLL_FASTEN (1 << 2)
-#define DPLL_ENSTAT (1 << 1)
-#define DPLL_DITHEN (1 << 0)
-
-#define DPLL_DIV_CTRL 0x6004
-#define DPLL_CLKF_MASK 0xffffffc0
-#define DPLL_CLKR_MASK (0x3f)
-
-#define DPLL_CLK_ENABLE 0x6008
-#define DPLL_EN_DISP (1 << 31)
-#define DPLL_SEL_HDMI (1 << 8)
-#define DPLL_EN_HDMI (1 << 1)
-#define DPLL_EN_VGA (1 << 0)
-
-#define DPLL_ADJUST 0x600C
-#define DPLL_STATUS 0x6010
-#define DPLL_UPDATE 0x6014
-#define DPLL_DFT 0x6020
-
-struct intel_range {
- int min, max;
-};
-
-struct mrst_hdmi_limit {
- struct intel_range vco, np, nr, nf;
-};
-
-struct mrst_hdmi_clock {
- int np;
- int nr;
- int nf;
- int dot;
-};
-
-#define VCO_MIN 320000
-#define VCO_MAX 1650000
-#define NP_MIN 1
-#define NP_MAX 15
-#define NR_MIN 1
-#define NR_MAX 64
-#define NF_MIN 2
-#define NF_MAX 4095
-
-static const struct mrst_hdmi_limit mrst_hdmi_limit = {
- .vco = { .min = VCO_MIN, .max = VCO_MAX },
- .np = { .min = NP_MIN, .max = NP_MAX },
- .nr = { .min = NR_MIN, .max = NR_MAX },
- .nf = { .min = NF_MIN, .max = NF_MAX },
-};
-
-static void wait_for_vblank(struct drm_device *dev)
-{
- /* FIXME: Can we do this as a sleep ? */
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- mdelay(20);
-}
-
-static void scu_busy_loop(void *scu_base)
-{
- u32 status = 0;
- u32 loop_count = 0;
-
- status = readl(scu_base + 0x04);
- while (status & 1) {
- udelay(1); /* scu processing time is in few u secods */
- status = readl(scu_base + 0x04);
- loop_count++;
- /* break if scu doesn't reset busy bit after huge retry */
- if (loop_count > 1000) {
- DRM_DEBUG_KMS("SCU IPC timed out");
- return;
- }
- }
-}
-
-static void mrst_hdmi_reset(struct drm_device *dev)
-{
- void *base;
- /* FIXME: at least make these defines */
- unsigned int scu_ipc_mmio = 0xff11c000;
- int scu_len = 1024;
-
- base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
- if (base == NULL) {
- DRM_ERROR("failed to map SCU mmio\n");
- return;
- }
-
- /* scu ipc: assert hdmi controller reset */
- writel(0xff11d118, base + 0x0c);
- writel(0x7fffffdf, base + 0x80);
- writel(0x42005, base + 0x0);
- scu_busy_loop(base);
-
- /* scu ipc: de-assert hdmi controller reset */
- writel(0xff11d118, base + 0x0c);
- writel(0x7fffffff, base + 0x80);
- writel(0x42005, base + 0x0);
- scu_busy_loop(base);
-
- iounmap(base);
-}
-
-static void mrst_hdmi_audio_enable(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-
- HDMI_WRITE(HDMI_HCR, 0x67);
- HDMI_READ(HDMI_HCR);
-
- HDMI_WRITE(0x51a8, 0x10);
- HDMI_READ(0x51a8);
-
- HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
- HDMI_READ(HDMI_AUDIO_CTRL);
-}
-
-static void mrst_hdmi_audio_disable(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
-
- HDMI_WRITE(0x51a8, 0x0);
- HDMI_READ(0x51a8);
-
- HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
- HDMI_READ(HDMI_AUDIO_CTRL);
-
- HDMI_WRITE(HDMI_HCR, 0x47);
- HDMI_READ(HDMI_HCR);
-}
-
-void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- u32 temp;
-
- switch (mode) {
- case DRM_MODE_DPMS_OFF:
- /* Disable VGACNTRL */
- REG_WRITE(VGACNTRL, 0x80000000);
-
- /* Disable plane */
- temp = REG_READ(DSPBCNTR);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
- REG_READ(DSPBCNTR);
- /* Flush the plane changes */
- REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
- REG_READ(DSPBSURF);
- }
-
- /* Disable pipe B */
- temp = REG_READ(PIPEBCONF);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
- REG_READ(PIPEBCONF);
- }
-
- /* Disable LNW Pipes, etc */
- temp = REG_READ(PCH_PIPEBCONF);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
- REG_READ(PCH_PIPEBCONF);
- }
- /* wait for pipe off */
- udelay(150);
- /* Disable dpll */
- temp = REG_READ(DPLL_CTRL);
- if ((temp & DPLL_PWRDN) == 0) {
- REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
- REG_WRITE(DPLL_STATUS, 0x1);
- }
- /* wait for dpll off */
- udelay(150);
- break;
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- /* Enable dpll */
- temp = REG_READ(DPLL_CTRL);
- if ((temp & DPLL_PWRDN) != 0) {
- REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
- temp = REG_READ(DPLL_CLK_ENABLE);
- REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
- REG_READ(DPLL_CLK_ENABLE);
- }
- /* wait for dpll warm up */
- udelay(150);
-
- /* Enable pipe B */
- temp = REG_READ(PIPEBCONF);
- if ((temp & PIPEACONF_ENABLE) == 0) {
- REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
- REG_READ(PIPEBCONF);
- }
-
- /* Enable LNW Pipe B */
- temp = REG_READ(PCH_PIPEBCONF);
- if ((temp & PIPEACONF_ENABLE) == 0) {
- REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
- REG_READ(PCH_PIPEBCONF);
- }
- wait_for_vblank(dev);
-
- /* Enable plane */
- temp = REG_READ(DSPBCNTR);
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
- REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
- REG_READ(DSPBSURF);
- }
- psb_intel_crtc_load_lut(crtc);
- }
- /* DSPARB */
- REG_WRITE(DSPARB, 0x00003fbf);
- /* FW1 */
- REG_WRITE(0x70034, 0x3f880a0a);
- /* FW2 */
- REG_WRITE(0x70038, 0x0b060808);
- /* FW4 */
- REG_WRITE(0x70050, 0x08030404);
- /* FW5 */
- REG_WRITE(0x70054, 0x04040404);
- /* LNC Chicken Bits */
- REG_WRITE(0x70400, 0x4000);
-}
-
-
-static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode)
-{
- static int dpms_mode = -1;
-
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- u32 temp;
-
- if (dpms_mode == mode)
- return;
-
- if (mode != DRM_MODE_DPMS_ON)
- temp = 0x0;
- else
- temp = 0x99;
-
- dpms_mode = mode;
- HDMI_WRITE(HDMI_VIDEO_REG, temp);
-}
-
-static unsigned int htotal_calculate(struct drm_display_mode *mode)
-{
- u32 htotal, new_crtc_htotal;
-
- htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
-
- /*
- * 1024 x 768 new_crtc_htotal = 0x1024;
- * 1280 x 1024 new_crtc_htotal = 0x0c34;
- */
- new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
-
- return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
-}
-
-static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target,
- int refclk, struct mrst_hdmi_clock *best_clock)
-{
- int np_min, np_max, nr_min, nr_max;
- int np, nr, nf;
-
- np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10);
- np_max = mrst_hdmi_limit.vco.max / (target * 10);
- if (np_min < mrst_hdmi_limit.np.min)
- np_min = mrst_hdmi_limit.np.min;
- if (np_max > mrst_hdmi_limit.np.max)
- np_max = mrst_hdmi_limit.np.max;
-
- nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
- nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
- if (nr_min < mrst_hdmi_limit.nr.min)
- nr_min = mrst_hdmi_limit.nr.min;
- if (nr_max > mrst_hdmi_limit.nr.max)
- nr_max = mrst_hdmi_limit.nr.max;
-
- np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
- nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
- nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
- DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
-
- /*
- * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000;
- * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
- */
- best_clock->np = np;
- best_clock->nr = nr - 1;
- best_clock->nf = (nf << 14);
-}
-
-int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- int pipe = 1;
- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- int refclk;
- struct mrst_hdmi_clock clock;
- u32 dspcntr, pipeconf, dpll, temp;
- int dspcntr_reg = DSPBCNTR;
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* XXX: Disable the panel fitter if it was on our pipe */
-
- /* Disable dpll if necessary */
- dpll = REG_READ(DPLL_CTRL);
- if ((dpll & DPLL_PWRDN) == 0) {
- REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
- REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
- REG_WRITE(DPLL_STATUS, 0x1);
- }
- udelay(150);
-
- /* reset controller: FIXME - can we sort out the ioremap mess ? */
- iounmap(hdmi_dev->regs);
- mrst_hdmi_reset(dev);
-
- /* program and enable dpll */
- refclk = 25000;
- mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
-
- /* Setting DPLL */
- dpll = REG_READ(DPLL_CTRL);
- dpll &= ~DPLL_PDIV_MASK;
- dpll &= ~(DPLL_PWRDN | DPLL_RESET);
- REG_WRITE(DPLL_CTRL, 0x00000008);
- REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
- REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
- REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
- REG_WRITE(DPLL_UPDATE, 0x80000000);
- REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
- udelay(150);
-
- hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
- if (hdmi_dev->regs == NULL) {
- DRM_ERROR("failed to do hdmi mmio mapping\n");
- return -ENOMEM;
- }
-
- /* configure HDMI */
- HDMI_WRITE(0x1004, 0x1fd);
- HDMI_WRITE(0x2000, 0x1);
- HDMI_WRITE(0x2008, 0x0);
- HDMI_WRITE(0x3130, 0x8);
- HDMI_WRITE(0x101c, 0x1800810);
-
- temp = htotal_calculate(adjusted_mode);
- REG_WRITE(htot_reg, temp);
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
- REG_WRITE(pipesrc_reg,
- ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
-
- REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
- REG_WRITE(PCH_PIPEBSRC,
- ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
-
- temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
- HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp);
-
- REG_WRITE(dspsize_reg,
- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
- REG_WRITE(dsppos_reg, 0);
-
- /* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
-
- /* Set up the display plane register */
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr |= DISPPLANE_GAMMA_ENABLE;
- dspcntr |= DISPPLANE_SEL_PIPE_B;
- dspcntr |= DISPLAY_PLANE_ENABLE;
-
- /* setup pipeconf */
- pipeconf = REG_READ(pipeconf_reg);
- pipeconf |= PIPEACONF_ENABLE;
-
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
-
- REG_WRITE(PCH_PIPEBCONF, pipeconf);
- REG_READ(PCH_PIPEBCONF);
- wait_for_vblank(dev);
-
- REG_WRITE(dspcntr_reg, dspcntr);
- wait_for_vblank(dev);
-
- return 0;
-}
-
-static int mrst_hdmi_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- if (mode->clock > 165000)
- return MODE_CLOCK_HIGH;
- if (mode->clock < 20000)
- return MODE_CLOCK_LOW;
-
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- return MODE_OK;
-}
-
-static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static enum drm_connector_status
-mrst_hdmi_detect(struct drm_connector *connector, bool force)
-{
- enum drm_connector_status status;
- struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- u32 temp;
-
- temp = HDMI_READ(HDMI_HSR);
- DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
-
- if ((temp & HDMI_DETECT_HDP) != 0)
- status = connector_status_connected;
- else
- status = connector_status_disconnected;
-
- return status;
-}
-
-static const unsigned char raw_edid[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
- 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
- 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
- 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
- 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
- 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
- 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
- 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
-};
-
-static int mrst_hdmi_get_modes(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct i2c_adapter *i2c_adap;
- struct edid *edid;
- struct drm_display_mode *mode, *t;
- int i = 0, ret = 0;
-
- i2c_adap = i2c_get_adapter(3);
- if (i2c_adap == NULL) {
- DRM_ERROR("No ddc adapter available!\n");
- edid = (struct edid *)raw_edid;
- } else {
- edid = (struct edid *)raw_edid;
- /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
- }
-
- if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
- connector->display_info.raw_edid = NULL;
- }
-
- /*
- * prune modes that require frame buffer bigger than stolen mem
- */
- list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
- if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
- i++;
- drm_mode_remove(connector, mode);
- }
- }
- return ret - i;
-}
-
-static void mrst_hdmi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
-
- mrst_hdmi_audio_enable(dev);
- return;
-}
-
-static void mrst_hdmi_destroy(struct drm_connector *connector)
-{
- return;
-}
-
-static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = {
- .dpms = mrst_hdmi_dpms,
- .mode_fixup = mrst_hdmi_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
- .mode_set = mrst_hdmi_mode_set,
- .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_helper_funcs
- mrst_hdmi_connector_helper_funcs = {
- .get_modes = mrst_hdmi_get_modes,
- .mode_valid = mrst_hdmi_mode_valid,
- .best_encoder = psb_intel_best_encoder,
-};
-
-static const struct drm_connector_funcs mrst_hdmi_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .detect = mrst_hdmi_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = mrst_hdmi_destroy,
-};
-
-static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
- .destroy = mrst_hdmi_enc_destroy,
-};
-
-void mrst_hdmi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev)
-{
- struct psb_intel_output *psb_intel_output;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- psb_intel_output->mode_dev = mode_dev;
- connector = &psb_intel_output->base;
- encoder = &psb_intel_output->enc;
- drm_connector_init(dev, &psb_intel_output->base,
- &mrst_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_DVID);
-
- drm_encoder_init(dev, &psb_intel_output->enc,
- &mrst_hdmi_enc_funcs,
- DRM_MODE_ENCODER_TMDS);
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
-
- psb_intel_output->type = INTEL_OUTPUT_HDMI;
- drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs);
- drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs);
-
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
- drm_sysfs_connector_add(connector);
-
- return;
-}
-
-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
- {}
-};
-
-void mrst_hdmi_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct pci_dev *pdev;
- struct mrst_hdmi_dev *hdmi_dev;
- int ret;
-
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
- if (!pdev)
- return;
-
- hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL);
- if (!hdmi_dev) {
- dev_err(dev->dev, "failed to allocate memory\n");
- goto out;
- }
-
-
- ret = pci_enable_device(pdev);
- if (ret) {
- dev_err(dev->dev, "failed to enable hdmi controller\n");
- goto free;
- }
-
- hdmi_dev->mmio = pci_resource_start(pdev, 0);
- hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
- hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
- if (!hdmi_dev->regs) {
- dev_err(dev->dev, "failed to map hdmi mmio\n");
- goto free;
- }
-
- hdmi_dev->dev = pdev;
- pci_set_drvdata(pdev, hdmi_dev);
-
- /* Initialize i2c controller */
- ret = mrst_hdmi_i2c_init(hdmi_dev->dev);
- if (ret)
- dev_err(dev->dev, "HDMI I2C initialization failed\n");
-
- dev_priv->hdmi_priv = hdmi_dev;
- mrst_hdmi_audio_disable(dev);
- return;
-
-free:
- kfree(hdmi_dev);
-out:
- return;
-}
-
-void mrst_hdmi_teardown(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- struct pci_dev *pdev;
-
- if (hdmi_dev) {
- pdev = hdmi_dev->dev;
- pci_set_drvdata(pdev, NULL);
- mrst_hdmi_i2c_exit(pdev);
- iounmap(hdmi_dev->regs);
- kfree(hdmi_dev);
- pci_dev_put(pdev);
- }
-}
-
-/* save HDMI register state */
-void mrst_hdmi_save(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- int i;
-
- /* dpll */
- hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
- hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
- hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
- hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
- hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
-
- /* pipe B */
- dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
- dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC);
- dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B);
- dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B);
- dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B);
- dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B);
- dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B);
- dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B);
-
- hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
- hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
- hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
- hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
- hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B);
- hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
- hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
- hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B);
-
- /* plane */
- dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
- dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
- dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
- dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
- dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
- dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
-
- /* cursor B */
- dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
- dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
- dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
-
- /* save palette */
- for (i = 0; i < 256; i++)
- dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
-}
-
-/* restore HDMI register state */
-void mrst_hdmi_restore(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
- int i;
-
- /* dpll */
- PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
- PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
- PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
- PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
- PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
- DRM_UDELAY(150);
-
- /* pipe */
- PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
- PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
- PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
- PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B);
- PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
- PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
- PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B);
-
- PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
- PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
- PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
- PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B);
- PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
- PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
- PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B);
-
- PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
- PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
-
- /* plane */
- PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
- PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
- PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
- PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
- PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
-
- /* cursor B */
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
- PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
-
- /* restore palette */
- for (i = 0; i < 256; i++)
- PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
-}
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
deleted file mode 100644
index 36e7edc4d14c..000000000000
--- a/drivers/staging/gma500/mrst_hdmi_i2c.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Li Peng <peng.li@intel.com>
- */
-
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-#include "psb_drv.h"
-
-#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
-#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
-
-#define HDMI_HCR 0x1000
-#define HCR_DETECT_HDP (1 << 6)
-#define HCR_ENABLE_HDCP (1 << 5)
-#define HCR_ENABLE_AUDIO (1 << 2)
-#define HCR_ENABLE_PIXEL (1 << 1)
-#define HCR_ENABLE_TMDS (1 << 0)
-#define HDMI_HICR 0x1004
-#define HDMI_INTR_I2C_ERROR (1 << 4)
-#define HDMI_INTR_I2C_FULL (1 << 3)
-#define HDMI_INTR_I2C_DONE (1 << 2)
-#define HDMI_INTR_HPD (1 << 0)
-#define HDMI_HSR 0x1008
-#define HDMI_HISR 0x100C
-#define HDMI_HI2CRDB0 0x1200
-#define HDMI_HI2CHCR 0x1240
-#define HI2C_HDCP_WRITE (0 << 2)
-#define HI2C_HDCP_RI_READ (1 << 2)
-#define HI2C_HDCP_READ (2 << 2)
-#define HI2C_EDID_READ (3 << 2)
-#define HI2C_READ_CONTINUE (1 << 1)
-#define HI2C_ENABLE_TRANSACTION (1 << 0)
-
-#define HDMI_ICRH 0x1100
-#define HDMI_HI2CTDR0 0x1244
-#define HDMI_HI2CTDR1 0x1248
-
-#define I2C_STAT_INIT 0
-#define I2C_READ_DONE 1
-#define I2C_TRANSACTION_DONE 2
-
-struct hdmi_i2c_dev {
- struct i2c_adapter *adap;
- struct mutex i2c_lock;
- struct completion complete;
- int status;
- struct i2c_msg *msg;
- int buf_offset;
-};
-
-static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
-{
- u32 temp;
-
- temp = HDMI_READ(HDMI_HICR);
- temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
- HDMI_WRITE(HDMI_HICR, temp);
- HDMI_READ(HDMI_HICR);
-}
-
-static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
-{
- HDMI_WRITE(HDMI_HICR, 0x0);
- HDMI_READ(HDMI_HICR);
-}
-
-static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
-{
- struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
- u32 temp;
-
- i2c_dev->status = I2C_STAT_INIT;
- i2c_dev->msg = pmsg;
- i2c_dev->buf_offset = 0;
- INIT_COMPLETION(i2c_dev->complete);
-
- /* Enable I2C transaction */
- temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
- HDMI_WRITE(HDMI_HI2CHCR, temp);
- HDMI_READ(HDMI_HI2CHCR);
-
- while (i2c_dev->status != I2C_TRANSACTION_DONE)
- wait_for_completion_interruptible_timeout(&i2c_dev->complete,
- 10 * HZ);
-
- return 0;
-}
-
-static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
-{
- /*
- * XXX: i2c write seems isn't useful for EDID probe, don't do anything
- */
- return 0;
-}
-
-static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
- struct i2c_msg *pmsg,
- int num)
-{
- struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
- int i, err = 0;
-
- mutex_lock(&i2c_dev->i2c_lock);
-
- /* Enable i2c unit */
- HDMI_WRITE(HDMI_ICRH, 0x00008760);
-
- /* Enable irq */
- hdmi_i2c_irq_enable(hdmi_dev);
- for (i = 0; i < num; i++) {
- if (pmsg->len && pmsg->buf) {
- if (pmsg->flags & I2C_M_RD)
- err = xfer_read(adap, pmsg);
- else
- err = xfer_write(adap, pmsg);
- }
- pmsg++; /* next message */
- }
-
- /* Disable irq */
- hdmi_i2c_irq_disable(hdmi_dev);
-
- mutex_unlock(&i2c_dev->i2c_lock);
-
- return i;
-}
-
-static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
-}
-
-static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
- .master_xfer = mrst_hdmi_i2c_access,
- .functionality = mrst_hdmi_i2c_func,
-};
-
-static struct i2c_adapter mrst_hdmi_i2c_adapter = {
- .name = "mrst_hdmi_i2c",
- .nr = 3,
- .owner = THIS_MODULE,
- .class = I2C_CLASS_DDC,
- .algo = &mrst_hdmi_i2c_algorithm,
-};
-
-static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
-{
- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
- struct i2c_msg *msg = i2c_dev->msg;
- u8 *buf = msg->buf;
- u32 temp;
- int i, offset;
-
- offset = i2c_dev->buf_offset;
- for (i = 0; i < 0x10; i++) {
- temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
- memcpy(buf + (offset + i * 4), &temp, 4);
- }
- i2c_dev->buf_offset += (0x10 * 4);
-
- /* clearing read buffer full intr */
- temp = HDMI_READ(HDMI_HISR);
- HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
- HDMI_READ(HDMI_HISR);
-
- /* continue read transaction */
- temp = HDMI_READ(HDMI_HI2CHCR);
- HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
- HDMI_READ(HDMI_HI2CHCR);
-
- i2c_dev->status = I2C_READ_DONE;
- return;
-}
-
-static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
-{
- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
- u32 temp;
-
- /* clear transaction done intr */
- temp = HDMI_READ(HDMI_HISR);
- HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
- HDMI_READ(HDMI_HISR);
-
-
- temp = HDMI_READ(HDMI_HI2CHCR);
- HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
- HDMI_READ(HDMI_HI2CHCR);
-
- i2c_dev->status = I2C_TRANSACTION_DONE;
- return;
-}
-
-static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
-{
- struct mrst_hdmi_dev *hdmi_dev = dev;
- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
- u32 stat;
-
- stat = HDMI_READ(HDMI_HISR);
-
- if (stat & HDMI_INTR_HPD) {
- HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
- HDMI_READ(HDMI_HISR);
- }
-
- if (stat & HDMI_INTR_I2C_FULL)
- hdmi_i2c_read(hdmi_dev);
-
- if (stat & HDMI_INTR_I2C_DONE)
- hdmi_i2c_transaction_done(hdmi_dev);
-
- complete(&i2c_dev->complete);
-
- return IRQ_HANDLED;
-}
-
-/*
- * choose alternate function 2 of GPIO pin 52, 53,
- * which is used by HDMI I2C logic
- */
-static void mrst_hdmi_i2c_gpio_fix(void)
-{
- void *base;
- unsigned int gpio_base = 0xff12c000;
- int gpio_len = 0x1000;
- u32 temp;
-
- base = ioremap((resource_size_t)gpio_base, gpio_len);
- if (base == NULL) {
- DRM_ERROR("gpio ioremap fail\n");
- return;
- }
-
- temp = readl(base + 0x44);
- DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
- writel((temp | 0x00000a00), (base + 0x44));
- temp = readl(base + 0x44);
- DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
-
- iounmap(base);
-}
-
-int mrst_hdmi_i2c_init(struct pci_dev *dev)
-{
- struct mrst_hdmi_dev *hdmi_dev;
- struct hdmi_i2c_dev *i2c_dev;
- int ret;
-
- hdmi_dev = pci_get_drvdata(dev);
-
- i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
- if (i2c_dev == NULL) {
- DRM_ERROR("Can't allocate interface\n");
- ret = -ENOMEM;
- goto exit;
- }
-
- i2c_dev->adap = &mrst_hdmi_i2c_adapter;
- i2c_dev->status = I2C_STAT_INIT;
- init_completion(&i2c_dev->complete);
- mutex_init(&i2c_dev->i2c_lock);
- i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
- hdmi_dev->i2c_dev = i2c_dev;
-
- /* Enable HDMI I2C function on gpio */
- mrst_hdmi_i2c_gpio_fix();
-
- /* request irq */
- ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
- mrst_hdmi_i2c_adapter.name, hdmi_dev);
- if (ret) {
- DRM_ERROR("Failed to request IRQ for I2C controller\n");
- goto err;
- }
-
- /* Adapter registration */
- ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
- return ret;
-
-err:
- kfree(i2c_dev);
-exit:
- return ret;
-}
-
-void mrst_hdmi_i2c_exit(struct pci_dev *dev)
-{
- struct mrst_hdmi_dev *hdmi_dev;
- struct hdmi_i2c_dev *i2c_dev;
-
- hdmi_dev = pci_get_drvdata(dev);
- if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
- DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
-
- i2c_dev = hdmi_dev->i2c_dev;
- kfree(i2c_dev);
- free_irq(dev->irq, hdmi_dev);
-}
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
deleted file mode 100644
index e7999a2a3796..000000000000
--- a/drivers/staging/gma500/mrst_lvds.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright © 2006-2009 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-#include <asm/mrst.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-/* The max/min PWM frequency in BPCR[31:17] - */
-/* The smallest number is 1 (not 0) that can fit in the
- * 15-bit field of the and then*/
-/* shifts to the left by one bit to get the actual 16-bit
- * value that the 15-bits correspond to.*/
-#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
-#define BRIGHTNESS_MAX_LEVEL 100
-
-/**
- * Sets the power state for the panel.
- */
-static void mrst_lvds_set_power(struct drm_device *dev,
- struct psb_intel_output *output, bool on)
-{
- u32 pp_status;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!gma_power_begin(dev, true))
- return;
-
- if (on) {
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
- POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
- dev_priv->is_lvds_on = true;
- if (dev_priv->ops->lvds_bl_power)
- dev_priv->ops->lvds_bl_power(dev, true);
- } else {
- if (dev_priv->ops->lvds_bl_power)
- dev_priv->ops->lvds_bl_power(dev, false);
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
- ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while (pp_status & PP_ON);
- dev_priv->is_lvds_on = false;
- pm_request_idle(&dev->pdev->dev);
- }
- gma_power_end(dev);
-}
-
-static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-
- if (mode == DRM_MODE_DPMS_ON)
- mrst_lvds_set_power(dev, output, true);
- else
- mrst_lvds_set_power(dev, output, false);
-
- /* XXX: We never power down the LVDS pairs. */
-}
-
-static void mrst_lvds_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct psb_intel_mode_device *mode_dev =
- enc_to_psb_intel_output(encoder)->mode_dev;
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 lvds_port;
- uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
-
- if (!gma_power_begin(dev, true))
- return;
-
- /*
- * The LVDS pin pair will already have been turned on in the
- * psb_intel_crtc_mode_set since it has a large impact on the DPLL
- * settings.
- */
- lvds_port = (REG_READ(LVDS) &
- (~LVDS_PIPEB_SELECT)) |
- LVDS_PORT_EN |
- LVDS_BORDER_EN;
-
- /* If the firmware says dither on Moorestown, or the BIOS does
- on Oaktrail then enable dithering */
- if (mode_dev->panel_wants_dither || dev_priv->lvds_dither)
- lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE;
-
- REG_WRITE(LVDS, lvds_port);
-
- drm_connector_property_get_value(
- &enc_to_psb_intel_output(encoder)->base,
- dev->mode_config.scaling_mode_property,
- &v);
-
- if (v == DRM_MODE_SCALE_NO_SCALE)
- REG_WRITE(PFIT_CONTROL, 0);
- else if (v == DRM_MODE_SCALE_ASPECT) {
- if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) ||
- (mode->hdisplay != adjusted_mode->crtc_hdisplay)) {
- if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) ==
- (mode->hdisplay * adjusted_mode->crtc_vdisplay))
- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
- else if ((adjusted_mode->crtc_hdisplay *
- mode->vdisplay) > (mode->hdisplay *
- adjusted_mode->crtc_vdisplay))
- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
- PFIT_SCALING_MODE_PILLARBOX);
- else
- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
- PFIT_SCALING_MODE_LETTERBOX);
- } else
- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
- } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/
- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
-
- gma_power_end(dev);
-}
-
-static void mrst_lvds_prepare(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (!gma_power_begin(dev, true))
- return;
-
- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
- BACKLIGHT_DUTY_CYCLE_MASK);
- mrst_lvds_set_power(dev, output, false);
- gma_power_end(dev);
-}
-
-static u32 mrst_lvds_get_max_backlight(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 ret;
-
- if (gma_power_begin(dev, false)) {
- ret = ((REG_READ(BLC_PWM_CTL) &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
- gma_power_end(dev);
- } else
- ret = ((dev_priv->saveBLC_PWM_CTL &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
- return ret;
-}
-
-static void mrst_lvds_commit(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (mode_dev->backlight_duty_cycle == 0)
- mode_dev->backlight_duty_cycle =
- mrst_lvds_get_max_backlight(dev);
- mrst_lvds_set_power(dev, output, true);
-}
-
-static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
- .dpms = mrst_lvds_dpms,
- .mode_fixup = psb_intel_lvds_mode_fixup,
- .prepare = mrst_lvds_prepare,
- .mode_set = mrst_lvds_mode_set,
- .commit = mrst_lvds_commit,
-};
-
-static struct drm_display_mode lvds_configuration_modes[] = {
- /* hard coded fixed mode for TPO LTPS LPJ040K001A */
- { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836,
- 846, 1056, 0, 480, 489, 491, 525, 0, 0) },
- /* hard coded fixed mode for LVDS 800x480 */
- { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801,
- 802, 1024, 0, 480, 481, 482, 525, 0, 0) },
- /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072,
- 1104, 1184, 0, 600, 603, 604, 608, 0, 0) },
- /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104,
- 1136, 1184, 0, 600, 603, 604, 608, 0, 0) },
- /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */
- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124,
- 1204, 1312, 0, 600, 607, 610, 621, 0, 0) },
- /* hard coded fixed mode for LVDS 1024x768 */
- { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
- 1184, 1344, 0, 768, 771, 777, 806, 0, 0) },
- /* hard coded fixed mode for LVDS 1366x768 */
- { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430,
- 1558, 1664, 0, 768, 769, 770, 776, 0, 0) },
-};
-
-/* Returns the panel fixed mode from configuration. */
-
-static struct drm_display_mode *
-mrst_lvds_get_configuration_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode = NULL;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
-
- if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay + \
- ((ti->hsync_offset_hi << 8) | \
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start + \
- ((ti->hsync_pulse_width_hi << 8) | \
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 4) | \
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \
- ti->vsync_pulse_width_lo);
- mode->vtotal = mode->vdisplay + \
- ((ti->vblank_hi << 8) | ti->vblank_lo);
- mode->clock = ti->pixel_clock * 10;
-#if 0
- printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay);
- printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay);
- printk(KERN_INFO "HSS is %d\n", mode->hsync_start);
- printk(KERN_INFO "HSE is %d\n", mode->hsync_end);
- printk(KERN_INFO "htotal is %d\n", mode->htotal);
- printk(KERN_INFO "VSS is %d\n", mode->vsync_start);
- printk(KERN_INFO "VSE is %d\n", mode->vsync_end);
- printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
- printk(KERN_INFO "clock is %d\n", mode->clock);
-#endif
- } else
- mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- return mode;
-}
-
-/**
- * mrst_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void mrst_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev)
-{
- struct psb_intel_output *psb_intel_output;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- struct edid *edid;
- int ret = 0;
- struct i2c_adapter *i2c_adap;
- struct drm_display_mode *scan; /* *modes, *bios_mode; */
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- psb_intel_output->mode_dev = mode_dev;
- connector = &psb_intel_output->base;
- encoder = &psb_intel_output->enc;
- dev_priv->is_lvds_on = true;
- drm_connector_init(dev, &psb_intel_output->base,
- &psb_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
-
- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
- psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
- drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs);
- drm_connector_helper_add(connector,
- &psb_intel_lvds_connector_helper_funcs);
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- drm_connector_attach_property(connector,
- dev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_FULLSCREEN);
- drm_connector_attach_property(connector,
- dev_priv->backlight_property,
- BRIGHTNESS_MAX_LEVEL);
-
- mode_dev->panel_wants_dither = false;
- if (dev_priv->vbt_data.size != 0x00)
- mode_dev->panel_wants_dither = (dev_priv->gct_data.
- Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE);
-
- /*
- * LVDS discovery:
- * 1) check for EDID on DDC
- * 2) check for VBT data
- * 3) check to see if LVDS is already on
- * if none of the above, no panel
- * 4) make sure lid is open
- * if closed, act like it's not there for now
- */
-
- i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
-
- if (i2c_adap == NULL)
- dev_err(dev->dev, "No ddc adapter available!\n");
- /*
- * Attempt to get the fixed panel mode from DDC. Assume that the
- * preferred mode is the right one.
- */
- if (i2c_adap) {
- edid = drm_get_edid(connector, i2c_adap);
- if (edid) {
- drm_mode_connector_update_edid_property(connector,
- edid);
- ret = drm_add_edid_modes(connector, edid);
- kfree(edid);
- }
-
- list_for_each_entry(scan, &connector->probed_modes, head) {
- if (scan->type & DRM_MODE_TYPE_PREFERRED) {
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, scan);
- goto out; /* FIXME: check for quirks */
- }
- }
- }
- /*
- * If we didn't get EDID, try geting panel timing
- * from configuration data
- */
- mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev);
-
- if (mode_dev->panel_fixed_mode) {
- mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
- goto out; /* FIXME: check for quirks */
- }
-
- /* If we still don't have a mode after all that, give up. */
- if (!mode_dev->panel_fixed_mode) {
- dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
- }
-
-out:
- drm_sysfs_connector_add(connector);
- return;
-
-failed_find:
- dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-
-/* failed_ddc: */
-
- drm_encoder_cleanup(encoder);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
deleted file mode 100644
index 408257038335..000000000000
--- a/drivers/staging/gma500/power.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Benjamin Defnet <benjamin.r.defnet@intel.com>
- * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- * Alan Cox <alan@linux.intel.com>
- */
-
-#include "power.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/mutex.h>
-#include <linux/pm_runtime.h>
-
-static struct mutex power_mutex; /* Serialize power ops */
-static spinlock_t power_ctrl_lock; /* Serialize power claim */
-
-/**
- * gma_power_init - initialise power manager
- * @dev: our device
- *
- * Set up for power management tracking of our hardware.
- */
-void gma_power_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /* FIXME: Move APM/OSPM base into relevant device code */
- dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
- dev_priv->ospm_base &= 0xffff;
-
- dev_priv->display_power = true; /* We start active */
- dev_priv->display_count = 0; /* Currently no users */
- dev_priv->suspended = false; /* And not suspended */
- spin_lock_init(&power_ctrl_lock);
- mutex_init(&power_mutex);
-
- dev_priv->ops->init_pm(dev);
-}
-
-/**
- * gma_power_uninit - end power manager
- * @dev: device to end for
- *
- * Undo the effects of gma_power_init
- */
-void gma_power_uninit(struct drm_device *dev)
-{
- pm_runtime_disable(&dev->pdev->dev);
- pm_runtime_set_suspended(&dev->pdev->dev);
-}
-
-/**
- * gma_suspend_display - suspend the display logic
- * @dev: our DRM device
- *
- * Suspend the display logic of the graphics interface
- */
-static void gma_suspend_display(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->display_power)
- return;
- dev_priv->ops->save_regs(dev);
- dev_priv->ops->power_down(dev);
- dev_priv->display_power = false;
-}
-
-/**
- * gma_resume_display - resume display side logic
- *
- * Resume the display hardware restoring state and enabling
- * as necessary.
- */
-static void gma_resume_display(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (dev_priv->display_power)
- return;
-
- /* turn on the display power island */
- dev_priv->ops->power_up(dev);
- dev_priv->suspended = false;
- dev_priv->display_power = true;
-
- PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
- pci_write_config_word(pdev, PSB_GMCH_CTRL,
- dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
- dev_priv->ops->restore_regs(dev);
-}
-
-/**
- * gma_suspend_pci - suspend PCI side
- * @pdev: PCI device
- *
- * Perform the suspend processing on our PCI device state
- */
-static void gma_suspend_pci(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int bsm, vbt;
-
- if (dev_priv->suspended)
- return;
-
- pci_save_state(pdev);
- pci_read_config_dword(pdev, 0x5C, &bsm);
- dev_priv->saveBSM = bsm;
- pci_read_config_dword(pdev, 0xFC, &vbt);
- dev_priv->saveVBT = vbt;
- pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
- pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
-
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
-
- dev_priv->suspended = true;
-}
-
-/**
- * gma_resume_pci - resume helper
- * @dev: our PCI device
- *
- * Perform the resume processing on our PCI device state - rewrite
- * register state and re-enable the PCI device
- */
-static bool gma_resume_pci(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
-
- if (!dev_priv->suspended)
- return true;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
- pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
- /* restoring MSI address and data in PCIx space */
- pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
- pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
- ret = pci_enable_device(pdev);
-
- if (ret != 0)
- dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
- else
- dev_priv->suspended = false;
- return !dev_priv->suspended;
-}
-
-/**
- * gma_power_suspend - bus callback for suspend
- * @pdev: our PCI device
- * @state: suspend type
- *
- * Called back by the PCI layer during a suspend of the system. We
- * perform the necessary shut down steps and save enough state that
- * we can undo this when resume is called.
- */
-int gma_power_suspend(struct device *_dev)
-{
- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
- struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- mutex_lock(&power_mutex);
- if (!dev_priv->suspended) {
- if (dev_priv->display_count) {
- mutex_unlock(&power_mutex);
- return -EBUSY;
- }
- psb_irq_uninstall(dev);
- gma_suspend_display(dev);
- gma_suspend_pci(pdev);
- }
- mutex_unlock(&power_mutex);
- return 0;
-}
-
-/**
- * gma_power_resume - resume power
- * @pdev: PCI device
- *
- * Resume the PCI side of the graphics and then the displays
- */
-int gma_power_resume(struct device *_dev)
-{
- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
- struct drm_device *dev = pci_get_drvdata(pdev);
-
- mutex_lock(&power_mutex);
- gma_resume_pci(pdev);
- gma_resume_display(pdev);
- psb_irq_preinstall(dev);
- psb_irq_postinstall(dev);
- mutex_unlock(&power_mutex);
- return 0;
-}
-
-/**
- * gma_power_is_on - returne true if power is on
- * @dev: our DRM device
- *
- * Returns true if the display island power is on at this moment
- */
-bool gma_power_is_on(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- return dev_priv->display_power;
-}
-
-/**
- * gma_power_begin - begin requiring power
- * @dev: our DRM device
- * @force_on: true to force power on
- *
- * Begin an action that requires the display power island is enabled.
- * We refcount the islands.
- */
-bool gma_power_begin(struct drm_device *dev, bool force_on)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&power_ctrl_lock, flags);
- /* Power already on ? */
- if (dev_priv->display_power) {
- dev_priv->display_count++;
- pm_runtime_get(&dev->pdev->dev);
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return true;
- }
- if (force_on == false)
- goto out_false;
-
- /* Ok power up needed */
- ret = gma_resume_pci(dev->pdev);
- if (ret == 0) {
- /* FIXME: we want to defer this for Medfield/Oaktrail */
- gma_resume_display(dev->pdev);
- psb_irq_preinstall(dev);
- psb_irq_postinstall(dev);
- pm_runtime_get(&dev->pdev->dev);
- dev_priv->display_count++;
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return true;
- }
-out_false:
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return false;
-}
-
-/**
- * gma_power_end - end use of power
- * @dev: Our DRM device
- *
- * Indicate that one of our gma_power_begin() requested periods when
- * the diplay island power is needed has completed.
- */
-void gma_power_end(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long flags;
- spin_lock_irqsave(&power_ctrl_lock, flags);
- dev_priv->display_count--;
- WARN_ON(dev_priv->display_count < 0);
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- pm_runtime_put(&dev->pdev->dev);
-}
-
-int psb_runtime_suspend(struct device *dev)
-{
- return gma_power_suspend(dev);
-}
-
-int psb_runtime_resume(struct device *dev)
-{
- return gma_power_resume(dev);;
-}
-
-int psb_runtime_idle(struct device *dev)
-{
- struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
- struct drm_psb_private *dev_priv = drmdev->dev_private;
- if (dev_priv->display_count)
- return 0;
- else
- return 1;
-}
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
deleted file mode 100644
index 1969d2ecb328..000000000000
--- a/drivers/staging/gma500/power.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
-
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Benjamin Defnet <benjamin.r.defnet@intel.com>
- * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- * Alan Cox <alan@linux.intel.com>
- */
-#ifndef _PSB_POWERMGMT_H_
-#define _PSB_POWERMGMT_H_
-
-#include <linux/pci.h>
-#include <drm/drmP.h>
-
-void gma_power_init(struct drm_device *dev);
-void gma_power_uninit(struct drm_device *dev);
-
-/*
- * The kernel bus power management will call these functions
- */
-int gma_power_suspend(struct device *dev);
-int gma_power_resume(struct device *dev);
-
-/*
- * These are the functions the driver should use to wrap all hw access
- * (i.e. register reads and writes)
- */
-bool gma_power_begin(struct drm_device *dev, bool force);
-void gma_power_end(struct drm_device *dev);
-
-/*
- * Use this function to do an instantaneous check for if the hw is on.
- * Only use this in cases where you know the mutex is already held such
- * as in irq install/uninstall and you need to
- * prevent a deadlock situation. Otherwise use gma_power_begin().
- */
-bool gma_power_is_on(struct drm_device *dev);
-
-/*
- * GFX-Runtime PM callbacks
- */
-int psb_runtime_suspend(struct device *dev);
-int psb_runtime_resume(struct device *dev);
-int psb_runtime_idle(struct device *dev);
-
-#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
deleted file mode 100644
index b97aa78519f2..000000000000
--- a/drivers/staging/gma500/psb_device.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-
-
-static int psb_output_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- psb_intel_lvds_init(dev, &dev_priv->mode_dev);
- psb_intel_sdvo_init(dev, SDVOB);
- return 0;
-}
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-/*
- * Poulsbo Backlight Interfaces
- */
-
-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-
-#define PSB_BLC_PWM_PRECISION_FACTOR 10
-#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
-
-static int psb_brightness;
-static struct backlight_device *psb_backlight_device;
-
-static int psb_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return psb_brightness;
-}
-
-
-static int psb_backlight_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long core_clock;
- /* u32 bl_max_freq; */
- /* unsigned long value; */
- u16 bl_max_freq;
- uint32_t value;
- uint32_t blc_pwm_precision_factor;
-
- /* get bl_max_freq and pol from dev_priv*/
- if (!dev_priv->lvds_bl) {
- dev_err(dev->dev, "Has no valid LVDS backlight info\n");
- return -ENOENT;
- }
- bl_max_freq = dev_priv->lvds_bl->freq;
- blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-
- core_clock = dev_priv->core_freq;
-
- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
- value *= blc_pwm_precision_factor;
- value /= bl_max_freq;
- value /= blc_pwm_precision_factor;
-
- if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
- value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
- return -ERANGE;
- else {
- value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
- REG_WRITE(BLC_PWM_CTL,
- (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
- }
- return 0;
-}
-
-static int psb_set_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(psb_backlight_device);
- int level = bd->props.brightness;
-
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
- psb_intel_lvds_set_brightness(dev, level);
- psb_brightness = level;
- return 0;
-}
-
-static const struct backlight_ops psb_ops = {
- .get_brightness = psb_get_brightness,
- .update_status = psb_set_brightness,
-};
-
-static int psb_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- psb_backlight_device = backlight_device_register("psb-bl",
- NULL, (void *)dev, &psb_ops, &props);
- if (IS_ERR(psb_backlight_device))
- return PTR_ERR(psb_backlight_device);
-
- ret = psb_backlight_setup(dev);
- if (ret < 0) {
- backlight_device_unregister(psb_backlight_device);
- psb_backlight_device = NULL;
- return ret;
- }
- psb_backlight_device->props.brightness = 100;
- psb_backlight_device->props.max_brightness = 100;
- backlight_update_status(psb_backlight_device);
- dev_priv->backlight_device = psb_backlight_device;
- return 0;
-}
-
-#endif
-
-/*
- * Provide the Poulsbo specific chip logic and low level methods
- * for power management
- */
-
-static void psb_init_pm(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
- gating &= ~3; /* Disable 2D clock gating */
- gating |= 1;
- PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
- PSB_RSGX32(PSB_CR_CLKGATECTL);
-}
-
-/**
- * psb_save_display_registers - save registers lost on suspend
- * @dev: our DRM device
- *
- * Save the state we need in order to be able to restore the interface
- * upon resume from suspend
- */
-static int psb_save_display_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
-
- /* Display arbitration control + watermarks */
- dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
- dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
- dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
- dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
- dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
- dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
- dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
- dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
- /* Save crtc and output state */
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->save(crtc);
- }
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- connector->funcs->save(connector);
-
- mutex_unlock(&dev->mode_config.mutex);
- return 0;
-}
-
-/**
- * psb_restore_display_registers - restore lost register state
- * @dev: our DRM device
- *
- * Restore register state that was lost during suspend and resume.
- */
-static int psb_restore_display_registers(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
-
- /* Display arbitration + watermarks */
- PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
- PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
- PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
- PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
- PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
- PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
- PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
- PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
- /*make sure VGA plane is off. it initializes to on after reset!*/
- PSB_WVDC32(0x80000000, VGACNTRL);
-
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->restore(crtc);
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- connector->funcs->restore(connector);
-
- mutex_unlock(&dev->mode_config.mutex);
- return 0;
-}
-
-static int psb_power_down(struct drm_device *dev)
-{
- return 0;
-}
-
-static int psb_power_up(struct drm_device *dev)
-{
- return 0;
-}
-
-static void psb_get_core_freq(struct drm_device *dev)
-{
- uint32_t clock;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
- /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
- pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
- pci_read_config_dword(pci_root, 0xD4, &clock);
- pci_dev_put(pci_root);
-
- switch (clock & 0x07) {
- case 0:
- dev_priv->core_freq = 100;
- break;
- case 1:
- dev_priv->core_freq = 133;
- break;
- case 2:
- dev_priv->core_freq = 150;
- break;
- case 3:
- dev_priv->core_freq = 178;
- break;
- case 4:
- dev_priv->core_freq = 200;
- break;
- case 5:
- case 6:
- case 7:
- dev_priv->core_freq = 266;
- default:
- dev_priv->core_freq = 0;
- }
-}
-
-static int psb_chip_setup(struct drm_device *dev)
-{
- psb_get_core_freq(dev);
- gma_intel_opregion_init(dev);
- psb_intel_init_bios(dev);
- return 0;
-}
-
-const struct psb_ops psb_chip_ops = {
- .name = "Poulsbo",
- .accel_2d = 1,
- .pipes = 2,
- .crtcs = 2,
- .sgx_offset = PSB_SGX_OFFSET,
- .chip_setup = psb_chip_setup,
-
- .crtc_helper = &psb_intel_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
-
- .output_init = psb_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = psb_backlight_init,
-#endif
-
- .init_pm = psb_init_pm,
- .save_regs = psb_save_display_registers,
- .restore_regs = psb_restore_display_registers,
- .power_down = psb_power_down,
- .power_up = psb_power_up,
-};
-
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
deleted file mode 100644
index 0da846835688..000000000000
--- a/drivers/staging/gma500/psb_drm.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-#ifndef _PSB_DRM_H_
-#define _PSB_DRM_H_
-
-#define PSB_NUM_PIPE 3
-
-#define PSB_GPU_ACCESS_READ (1ULL << 32)
-#define PSB_GPU_ACCESS_WRITE (1ULL << 33)
-#define PSB_GPU_ACCESS_MASK (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
-
-#define PSB_BO_FLAG_COMMAND (1ULL << 52)
-
-/*
- * Feedback components:
- */
-
-struct drm_psb_sizes_arg {
- u32 ta_mem_size;
- u32 mmu_size;
- u32 pds_size;
- u32 rastgeom_size;
- u32 tt_size;
- u32 vram_size;
-};
-
-struct drm_psb_dpst_lut_arg {
- uint8_t lut[256];
- int output_id;
-};
-
-#define PSB_DC_CRTC_SAVE 0x01
-#define PSB_DC_CRTC_RESTORE 0x02
-#define PSB_DC_OUTPUT_SAVE 0x04
-#define PSB_DC_OUTPUT_RESTORE 0x08
-#define PSB_DC_CRTC_MASK 0x03
-#define PSB_DC_OUTPUT_MASK 0x0C
-
-struct drm_psb_dc_state_arg {
- u32 flags;
- u32 obj_id;
-};
-
-struct drm_psb_mode_operation_arg {
- u32 obj_id;
- u16 operation;
- struct drm_mode_modeinfo mode;
- void *data;
-};
-
-struct drm_psb_stolen_memory_arg {
- u32 base;
- u32 size;
-};
-
-/*Display Register Bits*/
-#define REGRWBITS_PFIT_CONTROLS (1 << 0)
-#define REGRWBITS_PFIT_AUTOSCALE_RATIOS (1 << 1)
-#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
-#define REGRWBITS_PIPEASRC (1 << 3)
-#define REGRWBITS_PIPEBSRC (1 << 4)
-#define REGRWBITS_VTOTAL_A (1 << 5)
-#define REGRWBITS_VTOTAL_B (1 << 6)
-#define REGRWBITS_DSPACNTR (1 << 8)
-#define REGRWBITS_DSPBCNTR (1 << 9)
-#define REGRWBITS_DSPCCNTR (1 << 10)
-
-/*Overlay Register Bits*/
-#define OV_REGRWBITS_OVADD (1 << 0)
-#define OV_REGRWBITS_OGAM_ALL (1 << 1)
-
-#define OVC_REGRWBITS_OVADD (1 << 2)
-#define OVC_REGRWBITS_OGAM_ALL (1 << 3)
-
-struct drm_psb_register_rw_arg {
- u32 b_force_hw_on;
-
- u32 display_read_mask;
- u32 display_write_mask;
-
- struct {
- u32 pfit_controls;
- u32 pfit_autoscale_ratios;
- u32 pfit_programmed_scale_ratios;
- u32 pipeasrc;
- u32 pipebsrc;
- u32 vtotal_a;
- u32 vtotal_b;
- } display;
-
- u32 overlay_read_mask;
- u32 overlay_write_mask;
-
- struct {
- u32 OVADD;
- u32 OGAMC0;
- u32 OGAMC1;
- u32 OGAMC2;
- u32 OGAMC3;
- u32 OGAMC4;
- u32 OGAMC5;
- u32 IEP_ENABLED;
- u32 IEP_BLE_MINMAX;
- u32 IEP_BSSCC_CONTROL;
- u32 b_wait_vblank;
- } overlay;
-
- u32 sprite_enable_mask;
- u32 sprite_disable_mask;
-
- struct {
- u32 dspa_control;
- u32 dspa_key_value;
- u32 dspa_key_mask;
- u32 dspc_control;
- u32 dspc_stride;
- u32 dspc_position;
- u32 dspc_linear_offset;
- u32 dspc_size;
- u32 dspc_surface;
- } sprite;
-
- u32 subpicture_enable_mask;
- u32 subpicture_disable_mask;
-};
-
-/* Controlling the kernel modesetting buffers */
-
-#define DRM_PSB_SIZES 0x07
-#define DRM_PSB_FUSE_REG 0x08
-#define DRM_PSB_DC_STATE 0x0A
-#define DRM_PSB_ADB 0x0B
-#define DRM_PSB_MODE_OPERATION 0x0C
-#define DRM_PSB_STOLEN_MEMORY 0x0D
-#define DRM_PSB_REGISTER_RW 0x0E
-
-/*
- * NOTE: Add new commands here, but increment
- * the values below and increment their
- * corresponding defines where they're
- * defined elsewhere.
- */
-
-#define DRM_PSB_GEM_CREATE 0x10
-#define DRM_PSB_2D_OP 0x11
-#define DRM_PSB_GEM_MMAP 0x12
-#define DRM_PSB_DPST 0x1B
-#define DRM_PSB_GAMMA 0x1C
-#define DRM_PSB_DPST_BL 0x1D
-#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
-
-#define PSB_MODE_OPERATION_MODE_VALID 0x01
-#define PSB_MODE_OPERATION_SET_DC_BASE 0x02
-
-struct drm_psb_get_pipe_from_crtc_id_arg {
- /** ID of CRTC being requested **/
- u32 crtc_id;
-
- /** pipe of requested CRTC **/
- u32 pipe;
-};
-
-/* FIXME: move this into a medfield header once we are sure it isn't needed for an
- ioctl */
-struct psb_drm_dpu_rect {
- int x, y;
- int width, height;
-};
-
-struct drm_psb_gem_create {
- __u64 size;
- __u32 handle;
- __u32 flags;
-#define PSB_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */
-};
-
-#define PSB_2D_OP_BUFLEN 16
-
-struct drm_psb_2d_op {
- __u32 src; /* Handles, only src supported right now */
- __u32 dst;
- __u32 mask;
- __u32 pat;
- __u32 size; /* In dwords of command */
- __u32 spare; /* And bumps array to u64 align */
- __u32 cmd[PSB_2D_OP_BUFLEN];
-};
-
-struct drm_psb_gem_mmap {
- __u32 handle;
- __u32 pad;
- /**
- * Fake offset to use for subsequent mmap call
- *
- * This is a fixed-size type for 32/64 compatibility.
- */
- __u64 offset;
-};
-
-#endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
deleted file mode 100644
index 95816808f867..000000000000
--- a/drivers/staging/gma500/psb_drv.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
- * All Rights Reserved.
- *
- * 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 <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "framebuffer.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "mid_bios.h"
-#include "mdfld_dsi_dbi.h"
-#include <drm/drm_pciids.h>
-#include "power.h"
-#include <linux/cpu.h>
-#include <linux/notifier.h>
-#include <linux/spinlock.h>
-#include <linux/pm_runtime.h>
-#include <linux/module.h>
-#include <acpi/video.h>
-
-static int drm_psb_trap_pagefaults;
-
-int drm_psb_no_fb;
-
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-MODULE_PARM_DESC(no_fb, "Disable FBdev");
-MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(no_fb, drm_psb_no_fb, int, 0600);
-module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
-
-
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
- { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
- { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
-#if defined(CONFIG_DRM_PSB_MRST)
- { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
- { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
-#endif
-#if defined(CONFIG_DRM_PSB_MFLD)
- { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-#endif
-#if defined(CONFIG_DRM_PSB_CDV)
- { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-#endif
- { 0, 0, 0}
-};
-MODULE_DEVICE_TABLE(pci, pciidlist);
-
-/*
- * Standard IOCTLs.
- */
-
-#define DRM_IOCTL_PSB_SIZES \
- DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
- struct drm_psb_sizes_arg)
-#define DRM_IOCTL_PSB_FUSE_REG \
- DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_PSB_DC_STATE \
- DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
- struct drm_psb_dc_state_arg)
-#define DRM_IOCTL_PSB_ADB \
- DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_PSB_MODE_OPERATION \
- DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
- struct drm_psb_mode_operation_arg)
-#define DRM_IOCTL_PSB_STOLEN_MEMORY \
- DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
- struct drm_psb_stolen_memory_arg)
-#define DRM_IOCTL_PSB_REGISTER_RW \
- DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
- struct drm_psb_register_rw_arg)
-#define DRM_IOCTL_PSB_DPST \
- DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
- uint32_t)
-#define DRM_IOCTL_PSB_GAMMA \
- DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
- struct drm_psb_dpst_lut_arg)
-#define DRM_IOCTL_PSB_DPST_BL \
- DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
- uint32_t)
-#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
- DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
- struct drm_psb_get_pipe_from_crtc_id_arg)
-#define DRM_IOCTL_PSB_GEM_CREATE \
- DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
- struct drm_psb_gem_create)
-#define DRM_IOCTL_PSB_2D_OP \
- DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
- struct drm_psb_2d_op)
-#define DRM_IOCTL_PSB_GEM_MMAP \
- DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
- struct drm_psb_gem_mmap)
-
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
- struct drm_file *file_priv);
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-#define PSB_IOCTL_DEF(ioctl, func, flags) \
- [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
-
-static struct drm_ioctl_desc psb_ioctls[] = {
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
- DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
- DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
- DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
- psb_intel_get_pipe_from_crtc_id, 0),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
- DRM_UNLOCKED | DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl,
- DRM_UNLOCKED| DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
- DRM_UNLOCKED | DRM_AUTH),
-};
-
-static void psb_lastclose(struct drm_device *dev)
-{
- return;
-}
-
-static void psb_do_takedown(struct drm_device *dev)
-{
-}
-
-static int psb_do_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = &dev_priv->gtt;
-
- uint32_t stolen_gtt;
-
- int ret = -ENOMEM;
-
- if (pg->mmu_gatt_start & 0x0FFFFFFF) {
- dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
- ret = -EINVAL;
- goto out_err;
- }
-
-
- stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
- stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
- stolen_gtt =
- (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
-
- dev_priv->gatt_free_offset = pg->mmu_gatt_start +
- (stolen_gtt << PAGE_SHIFT) * 1024;
-
- if (1 || drm_debug) {
- uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
- uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
- DRM_INFO("SGX core id = 0x%08x\n", core_id);
- DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
- (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
- _PSB_CC_REVISION_MAJOR_SHIFT,
- (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
- _PSB_CC_REVISION_MINOR_SHIFT);
- DRM_INFO
- ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
- (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
- _PSB_CC_REVISION_MAINTENANCE_SHIFT,
- (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
- _PSB_CC_REVISION_DESIGNER_SHIFT);
- }
-
-
- spin_lock_init(&dev_priv->irqmask_lock);
- spin_lock_init(&dev_priv->lock_2d);
-
- PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
- PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
- PSB_RSGX32(PSB_CR_BIF_BANK1);
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
- PSB_CR_BIF_CTRL);
- psb_spank(dev_priv);
-
- /* mmu_gatt ?? */
- PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
- return 0;
-out_err:
- psb_do_takedown(dev);
- return ret;
-}
-
-static int psb_driver_unload(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /* Kill vblank etc here */
-
- gma_backlight_exit(dev);
-
- if (drm_psb_no_fb == 0)
- psb_modeset_cleanup(dev);
-
- if (dev_priv) {
- psb_lid_timer_takedown(dev_priv);
- gma_intel_opregion_exit(dev);
-
- if (dev_priv->ops->chip_teardown)
- dev_priv->ops->chip_teardown(dev);
- psb_do_takedown(dev);
-
-
- if (dev_priv->pf_pd) {
- psb_mmu_free_pagedir(dev_priv->pf_pd);
- dev_priv->pf_pd = NULL;
- }
- if (dev_priv->mmu) {
- struct psb_gtt *pg = &dev_priv->gtt;
-
- down_read(&pg->sem);
- psb_mmu_remove_pfn_sequence(
- psb_mmu_get_default_pd
- (dev_priv->mmu),
- pg->mmu_gatt_start,
- dev_priv->vram_stolen_size >> PAGE_SHIFT);
- up_read(&pg->sem);
- psb_mmu_driver_takedown(dev_priv->mmu);
- dev_priv->mmu = NULL;
- }
- psb_gtt_takedown(dev);
- if (dev_priv->scratch_page) {
- __free_page(dev_priv->scratch_page);
- dev_priv->scratch_page = NULL;
- }
- if (dev_priv->vdc_reg) {
- iounmap(dev_priv->vdc_reg);
- dev_priv->vdc_reg = NULL;
- }
- if (dev_priv->sgx_reg) {
- iounmap(dev_priv->sgx_reg);
- dev_priv->sgx_reg = NULL;
- }
-
- kfree(dev_priv);
- dev->dev_private = NULL;
-
- /*destroy VBT data*/
- psb_intel_destroy_bios(dev);
- }
-
- gma_power_uninit(dev);
-
- return 0;
-}
-
-
-static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
-{
- struct drm_psb_private *dev_priv;
- unsigned long resource_start;
- struct psb_gtt *pg;
- unsigned long irqflags;
- int ret = -ENOMEM;
- uint32_t tt_pages;
- struct drm_connector *connector;
- struct psb_intel_output *psb_intel_output;
-
- dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
- if (dev_priv == NULL)
- return -ENOMEM;
-
- dev_priv->ops = (struct psb_ops *)chipset;
- dev_priv->dev = dev;
- dev->dev_private = (void *) dev_priv;
-
- if (!IS_PSB(dev)) {
- if (pci_enable_msi(dev->pdev))
- dev_warn(dev->dev, "Enabling MSI failed!\n");
- }
-
- dev_priv->num_pipe = dev_priv->ops->pipes;
-
- resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
-
- dev_priv->vdc_reg =
- ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
- if (!dev_priv->vdc_reg)
- goto out_err;
-
- dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
- PSB_SGX_SIZE);
- if (!dev_priv->sgx_reg)
- goto out_err;
-
- ret = dev_priv->ops->chip_setup(dev);
- if (ret)
- goto out_err;
-
- /* Init OSPM support */
- gma_power_init(dev);
-
- ret = -ENOMEM;
-
- dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
- if (!dev_priv->scratch_page)
- goto out_err;
-
- set_pages_uc(dev_priv->scratch_page, 1);
-
- ret = psb_gtt_init(dev, 0);
- if (ret)
- goto out_err;
-
- dev_priv->mmu = psb_mmu_driver_init((void *)0,
- drm_psb_trap_pagefaults, 0,
- dev_priv);
- if (!dev_priv->mmu)
- goto out_err;
-
- pg = &dev_priv->gtt;
-
- tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
- (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
-
- dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
- if (!dev_priv->pf_pd)
- goto out_err;
-
- psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
- psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
-
- ret = psb_do_init(dev);
- if (ret)
- return ret;
-
- PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
- PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
-
-/* igd_opregion_init(&dev_priv->opregion_dev); */
- acpi_video_register();
- if (dev_priv->lid_state)
- psb_lid_timer_init(dev_priv);
-
- ret = drm_vblank_init(dev, dev_priv->num_pipe);
- if (ret)
- goto out_err;
-
- /*
- * Install interrupt handlers prior to powering off SGX or else we will
- * crash.
- */
- dev_priv->vdc_irq_mask = 0;
- dev_priv->pipestat[0] = 0;
- dev_priv->pipestat[1] = 0;
- dev_priv->pipestat[2] = 0;
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
- PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET))
- drm_irq_install(dev);
-
- dev->vblank_disable_allowed = 1;
-
- dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-
- dev->driver->get_vblank_counter = psb_get_vblank_counter;
-
-#if defined(CONFIG_DRM_PSB_MFLD)
- /* FIXME: this is not the right place for this stuff ! */
- mdfld_output_setup(dev);
-#endif
- if (drm_psb_no_fb == 0) {
- psb_modeset_init(dev);
- psb_fbdev_init(dev);
- drm_kms_helper_poll_init(dev);
- }
-
- /* Only add backlight support if we have LVDS output */
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- psb_intel_output = to_psb_intel_output(connector);
-
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_LVDS:
- case INTEL_OUTPUT_MIPI:
- ret = gma_backlight_init(dev);
- break;
- }
- }
-
- if (ret)
- return ret;
-
- /* Enable runtime pm at last */
- pm_runtime_set_active(&dev->pdev->dev);
- return 0;
-out_err:
- psb_driver_unload(dev);
- return ret;
-}
-
-int psb_driver_device_is_agp(struct drm_device *dev)
-{
- return 0;
-}
-
-
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- struct drm_psb_sizes_arg *arg = data;
-
- *arg = dev_priv->sizes;
- return 0;
-}
-
-static int psb_dc_state_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- uint32_t flags;
- uint32_t obj_id;
- struct drm_mode_object *obj;
- struct drm_connector *connector;
- struct drm_crtc *crtc;
- struct drm_psb_dc_state_arg *arg = data;
-
-
- /* Double check MRST case */
- if (IS_MRST(dev) || IS_MFLD(dev))
- return -EOPNOTSUPP;
-
- flags = arg->flags;
- obj_id = arg->obj_id;
-
- if (flags & PSB_DC_CRTC_MASK) {
- obj = drm_mode_object_find(dev, obj_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- dev_dbg(dev->dev, "Invalid CRTC object.\n");
- return -EINVAL;
- }
-
- crtc = obj_to_crtc(obj);
-
- mutex_lock(&dev->mode_config.mutex);
- if (drm_helper_crtc_in_use(crtc)) {
- if (flags & PSB_DC_CRTC_SAVE)
- crtc->funcs->save(crtc);
- else
- crtc->funcs->restore(crtc);
- }
- mutex_unlock(&dev->mode_config.mutex);
-
- return 0;
- } else if (flags & PSB_DC_OUTPUT_MASK) {
- obj = drm_mode_object_find(dev, obj_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- dev_dbg(dev->dev, "Invalid connector id.\n");
- return -EINVAL;
- }
-
- connector = obj_to_connector(obj);
- if (flags & PSB_DC_OUTPUT_SAVE)
- connector->funcs->save(connector);
- else
- connector->funcs->restore(connector);
-
- return 0;
- }
- return -EINVAL;
-}
-
-static inline void get_brightness(struct backlight_device *bd)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- if (bd) {
- bd->props.brightness = bd->ops->get_brightness(bd);
- backlight_update_status(bd);
- }
-#endif
-}
-
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- uint32_t *arg = data;
-
- dev_priv->blc_adj2 = *arg;
- get_brightness(dev_priv->backlight_device);
- return 0;
-}
-
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- uint32_t *arg = data;
-
- dev_priv->blc_adj1 = *arg;
- get_brightness(dev_priv->backlight_device);
- return 0;
-}
-
-/* return the current mode to the dpst module */
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- uint32_t *arg = data;
- uint32_t x;
- uint32_t y;
- uint32_t reg;
-
- if (!gma_power_begin(dev, 0))
- return -EIO;
-
- reg = PSB_RVDC32(PIPEASRC);
-
- gma_power_end(dev);
-
- /* horizontal is the left 16 bits */
- x = reg >> 16;
- /* vertical is the right 16 bits */
- y = reg & 0x0000ffff;
-
- /* the values are the image size minus one */
- x++;
- y++;
-
- *arg = (x << 16) | y;
-
- return 0;
-}
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_dpst_lut_arg *lut_arg = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
- struct psb_intel_crtc *psb_intel_crtc;
- int i = 0;
- int32_t obj_id;
-
- obj_id = lut_arg->output_id;
- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- dev_dbg(dev->dev, "Invalid Connector object.\n");
- return -EINVAL;
- }
-
- connector = obj_to_connector(obj);
- crtc = connector->encoder->crtc;
- psb_intel_crtc = to_psb_intel_crtc(crtc);
-
- for (i = 0; i < 256; i++)
- psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
-
- psb_intel_crtc_load_lut(crtc);
-
- return 0;
-}
-
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- uint32_t obj_id;
- uint16_t op;
- struct drm_mode_modeinfo *umode;
- struct drm_display_mode *mode = NULL;
- struct drm_psb_mode_operation_arg *arg;
- struct drm_mode_object *obj;
- struct drm_connector *connector;
- struct drm_framebuffer *drm_fb;
- struct psb_framebuffer *psb_fb;
- struct drm_connector_helper_funcs *connector_funcs;
- int ret = 0;
- int resp = MODE_OK;
- struct drm_psb_private *dev_priv = psb_priv(dev);
-
- arg = (struct drm_psb_mode_operation_arg *)data;
- obj_id = arg->obj_id;
- op = arg->operation;
-
- switch (op) {
- case PSB_MODE_OPERATION_SET_DC_BASE:
- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
- if (!obj) {
- dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
- return -EINVAL;
- }
-
- drm_fb = obj_to_fb(obj);
- psb_fb = to_psb_fb(drm_fb);
-
- if (gma_power_begin(dev, 0)) {
- REG_WRITE(DSPASURF, psb_fb->gtt->offset);
- REG_READ(DSPASURF);
- gma_power_end(dev);
- } else {
- dev_priv->saveDSPASURF = psb_fb->gtt->offset;
- }
-
- return 0;
- case PSB_MODE_OPERATION_MODE_VALID:
- umode = &arg->mode;
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, obj_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- ret = -EINVAL;
- goto mode_op_out;
- }
-
- connector = obj_to_connector(obj);
-
- mode = drm_mode_create(dev);
- if (!mode) {
- ret = -ENOMEM;
- goto mode_op_out;
- }
-
- /* drm_crtc_convert_umode(mode, umode); */
- {
- mode->clock = umode->clock;
- mode->hdisplay = umode->hdisplay;
- mode->hsync_start = umode->hsync_start;
- mode->hsync_end = umode->hsync_end;
- mode->htotal = umode->htotal;
- mode->hskew = umode->hskew;
- mode->vdisplay = umode->vdisplay;
- mode->vsync_start = umode->vsync_start;
- mode->vsync_end = umode->vsync_end;
- mode->vtotal = umode->vtotal;
- mode->vscan = umode->vscan;
- mode->vrefresh = umode->vrefresh;
- mode->flags = umode->flags;
- mode->type = umode->type;
- strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
- mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
- }
-
- connector_funcs = (struct drm_connector_helper_funcs *)
- connector->helper_private;
-
- if (connector_funcs->mode_valid) {
- resp = connector_funcs->mode_valid(connector, mode);
- arg->data = (void *)resp;
- }
-
- /*do some clean up work*/
- if (mode)
- drm_mode_destroy(dev, mode);
-mode_op_out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-
- default:
- dev_dbg(dev->dev, "Unsupported psb mode operation\n");
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- struct drm_psb_stolen_memory_arg *arg = data;
-
- arg->base = dev_priv->stolen_base;
- arg->size = dev_priv->vram_stolen_size;
-
- return 0;
-}
-
-/* FIXME: needs Medfield changes */
-static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- struct drm_psb_register_rw_arg *arg = data;
- bool usage = arg->b_force_hw_on ? true : false;
-
- if (arg->display_write_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
- PSB_WVDC32(arg->display.pfit_controls,
- PFIT_CONTROL);
- if (arg->display_write_mask &
- REGRWBITS_PFIT_AUTOSCALE_RATIOS)
- PSB_WVDC32(arg->display.pfit_autoscale_ratios,
- PFIT_AUTO_RATIOS);
- if (arg->display_write_mask &
- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
- PSB_WVDC32(
- arg->display.pfit_programmed_scale_ratios,
- PFIT_PGM_RATIOS);
- if (arg->display_write_mask & REGRWBITS_PIPEASRC)
- PSB_WVDC32(arg->display.pipeasrc,
- PIPEASRC);
- if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
- PSB_WVDC32(arg->display.pipebsrc,
- PIPEBSRC);
- if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
- PSB_WVDC32(arg->display.vtotal_a,
- VTOTAL_A);
- if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
- PSB_WVDC32(arg->display.vtotal_b,
- VTOTAL_B);
- gma_power_end(dev);
- } else {
- if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
- dev_priv->savePFIT_CONTROL =
- arg->display.pfit_controls;
- if (arg->display_write_mask &
- REGRWBITS_PFIT_AUTOSCALE_RATIOS)
- dev_priv->savePFIT_AUTO_RATIOS =
- arg->display.pfit_autoscale_ratios;
- if (arg->display_write_mask &
- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
- dev_priv->savePFIT_PGM_RATIOS =
- arg->display.pfit_programmed_scale_ratios;
- if (arg->display_write_mask & REGRWBITS_PIPEASRC)
- dev_priv->savePIPEASRC = arg->display.pipeasrc;
- if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
- dev_priv->savePIPEBSRC = arg->display.pipebsrc;
- if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
- dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
- if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
- dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
- }
- }
-
- if (arg->display_read_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- if (arg->display_read_mask &
- REGRWBITS_PFIT_CONTROLS)
- arg->display.pfit_controls =
- PSB_RVDC32(PFIT_CONTROL);
- if (arg->display_read_mask &
- REGRWBITS_PFIT_AUTOSCALE_RATIOS)
- arg->display.pfit_autoscale_ratios =
- PSB_RVDC32(PFIT_AUTO_RATIOS);
- if (arg->display_read_mask &
- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
- arg->display.pfit_programmed_scale_ratios =
- PSB_RVDC32(PFIT_PGM_RATIOS);
- if (arg->display_read_mask & REGRWBITS_PIPEASRC)
- arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
- if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
- arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
- if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
- arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
- if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
- arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
- gma_power_end(dev);
- } else {
- if (arg->display_read_mask &
- REGRWBITS_PFIT_CONTROLS)
- arg->display.pfit_controls =
- dev_priv->savePFIT_CONTROL;
- if (arg->display_read_mask &
- REGRWBITS_PFIT_AUTOSCALE_RATIOS)
- arg->display.pfit_autoscale_ratios =
- dev_priv->savePFIT_AUTO_RATIOS;
- if (arg->display_read_mask &
- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
- arg->display.pfit_programmed_scale_ratios =
- dev_priv->savePFIT_PGM_RATIOS;
- if (arg->display_read_mask & REGRWBITS_PIPEASRC)
- arg->display.pipeasrc = dev_priv->savePIPEASRC;
- if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
- arg->display.pipebsrc = dev_priv->savePIPEBSRC;
- if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
- arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
- if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
- arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
- }
- }
-
- if (arg->overlay_write_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
- PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
- PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
- PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
- PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
- PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
- PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
- }
- if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
- PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
- PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
- PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
- PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
- PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
- PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
- }
-
- if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
- PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
-
- if (arg->overlay.b_wait_vblank) {
- /* Wait for 20ms.*/
- unsigned long vblank_timeout = jiffies
- + HZ/50;
- uint32_t temp;
- while (time_before_eq(jiffies,
- vblank_timeout)) {
- temp = PSB_RVDC32(OV_DOVASTA);
- if ((temp & (0x1 << 31)) != 0)
- break;
- cpu_relax();
- }
- }
- }
- if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
- PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
- if (arg->overlay.b_wait_vblank) {
- /* Wait for 20ms.*/
- unsigned long vblank_timeout =
- jiffies + HZ/50;
- uint32_t temp;
- while (time_before_eq(jiffies,
- vblank_timeout)) {
- temp = PSB_RVDC32(OVC_DOVCSTA);
- if ((temp & (0x1 << 31)) != 0)
- break;
- cpu_relax();
- }
- }
- }
- gma_power_end(dev);
- } else {
- if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
- dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
- dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
- dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
- dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
- dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
- dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
- }
- if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
- dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
- dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
- dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
- dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
- dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
- dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
- }
- if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
- dev_priv->saveOV_OVADD = arg->overlay.OVADD;
- if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
- dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
- }
- }
-
- if (arg->overlay_read_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
- arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
- arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
- arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
- arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
- arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
- arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
- }
- if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
- arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
- arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
- arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
- arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
- arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
- arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
- }
- if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
- arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
- if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
- arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
- gma_power_end(dev);
- } else {
- if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
- arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
- arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
- arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
- arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
- arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
- arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
- }
- if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
- arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
- arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
- arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
- arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
- arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
- arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
- }
- if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
- arg->overlay.OVADD = dev_priv->saveOV_OVADD;
- if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
- arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
- }
- }
-
- if (arg->sprite_enable_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- PSB_WVDC32(0x1F3E, DSPARB);
- PSB_WVDC32(arg->sprite.dspa_control
- | PSB_RVDC32(DSPACNTR), DSPACNTR);
- PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
- PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
- PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
- PSB_RVDC32(DSPASURF);
- PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
- PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
- PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
- PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
- PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
- PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
- PSB_RVDC32(DSPCSURF);
- gma_power_end(dev);
- }
- }
-
- if (arg->sprite_disable_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- PSB_WVDC32(0x3F3E, DSPARB);
- PSB_WVDC32(0x0, DSPCCNTR);
- PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
- PSB_RVDC32(DSPCSURF);
- gma_power_end(dev);
- }
- }
-
- if (arg->subpicture_enable_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- uint32_t temp;
- if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
- temp = PSB_RVDC32(DSPACNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp &= ~DISPPLANE_BOTTOM;
- temp |= DISPPLANE_32BPP;
- PSB_WVDC32(temp, DSPACNTR);
-
- temp = PSB_RVDC32(DSPABASE);
- PSB_WVDC32(temp, DSPABASE);
- PSB_RVDC32(DSPABASE);
- temp = PSB_RVDC32(DSPASURF);
- PSB_WVDC32(temp, DSPASURF);
- PSB_RVDC32(DSPASURF);
- }
- if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
- temp = PSB_RVDC32(DSPBCNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp &= ~DISPPLANE_BOTTOM;
- temp |= DISPPLANE_32BPP;
- PSB_WVDC32(temp, DSPBCNTR);
-
- temp = PSB_RVDC32(DSPBBASE);
- PSB_WVDC32(temp, DSPBBASE);
- PSB_RVDC32(DSPBBASE);
- temp = PSB_RVDC32(DSPBSURF);
- PSB_WVDC32(temp, DSPBSURF);
- PSB_RVDC32(DSPBSURF);
- }
- if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
- temp = PSB_RVDC32(DSPCCNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp &= ~DISPPLANE_BOTTOM;
- temp |= DISPPLANE_32BPP;
- PSB_WVDC32(temp, DSPCCNTR);
-
- temp = PSB_RVDC32(DSPCBASE);
- PSB_WVDC32(temp, DSPCBASE);
- PSB_RVDC32(DSPCBASE);
- temp = PSB_RVDC32(DSPCSURF);
- PSB_WVDC32(temp, DSPCSURF);
- PSB_RVDC32(DSPCSURF);
- }
- gma_power_end(dev);
- }
- }
-
- if (arg->subpicture_disable_mask != 0) {
- if (gma_power_begin(dev, usage)) {
- uint32_t temp;
- if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
- temp = PSB_RVDC32(DSPACNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp |= DISPPLANE_32BPP_NO_ALPHA;
- PSB_WVDC32(temp, DSPACNTR);
-
- temp = PSB_RVDC32(DSPABASE);
- PSB_WVDC32(temp, DSPABASE);
- PSB_RVDC32(DSPABASE);
- temp = PSB_RVDC32(DSPASURF);
- PSB_WVDC32(temp, DSPASURF);
- PSB_RVDC32(DSPASURF);
- }
- if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
- temp = PSB_RVDC32(DSPBCNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp |= DISPPLANE_32BPP_NO_ALPHA;
- PSB_WVDC32(temp, DSPBCNTR);
-
- temp = PSB_RVDC32(DSPBBASE);
- PSB_WVDC32(temp, DSPBBASE);
- PSB_RVDC32(DSPBBASE);
- temp = PSB_RVDC32(DSPBSURF);
- PSB_WVDC32(temp, DSPBSURF);
- PSB_RVDC32(DSPBSURF);
- }
- if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
- temp = PSB_RVDC32(DSPCCNTR);
- temp &= ~DISPPLANE_PIXFORMAT_MASK;
- temp |= DISPPLANE_32BPP_NO_ALPHA;
- PSB_WVDC32(temp, DSPCCNTR);
-
- temp = PSB_RVDC32(DSPCBASE);
- PSB_WVDC32(temp, DSPCBASE);
- PSB_RVDC32(DSPCBASE);
- temp = PSB_RVDC32(DSPCSURF);
- PSB_WVDC32(temp, DSPCSURF);
- PSB_RVDC32(DSPCSURF);
- }
- gma_power_end(dev);
- }
- }
-
- return 0;
-}
-
-static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
-{
- return 0;
-}
-
-static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- struct drm_file *file_priv = filp->private_data;
- struct drm_device *dev = file_priv->minor->dev;
- int ret;
-
- pm_runtime_forbid(dev->dev);
- ret = drm_ioctl(filp, cmd, arg);
- pm_runtime_allow(dev->dev);
- return ret;
- /* FIXME: do we need to wrap the other side of this */
-}
-
-
-/* When a client dies:
- * - Check for and clean up flipped page state
- */
-void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static void psb_remove(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- drm_put_dev(dev);
-}
-
-static const struct dev_pm_ops psb_pm_ops = {
- .suspend = gma_power_suspend,
- .resume = gma_power_resume,
- .freeze = gma_power_suspend,
- .thaw = gma_power_resume,
- .poweroff = gma_power_suspend,
- .restore = gma_power_resume,
- .runtime_suspend = psb_runtime_suspend,
- .runtime_resume = psb_runtime_resume,
- .runtime_idle = psb_runtime_idle,
-};
-
-static struct vm_operations_struct psb_gem_vm_ops = {
- .fault = psb_gem_fault,
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
-
-static const struct file_operations gma500_driver_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = psb_unlocked_ioctl,
- .mmap = drm_gem_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
-};
-
-static struct drm_driver driver = {
- .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
- DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
- .load = psb_driver_load,
- .unload = psb_driver_unload,
-
- .ioctls = psb_ioctls,
- .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
- .device_is_agp = psb_driver_device_is_agp,
- .irq_preinstall = psb_irq_preinstall,
- .irq_postinstall = psb_irq_postinstall,
- .irq_uninstall = psb_irq_uninstall,
- .irq_handler = psb_irq_handler,
- .enable_vblank = psb_enable_vblank,
- .disable_vblank = psb_disable_vblank,
- .get_vblank_counter = psb_get_vblank_counter,
- .lastclose = psb_lastclose,
- .open = psb_driver_open,
- .preclose = psb_driver_preclose,
- .postclose = psb_driver_close,
- .reclaim_buffers = drm_core_reclaim_buffers,
-
- .gem_init_object = psb_gem_init_object,
- .gem_free_object = psb_gem_free_object,
- .gem_vm_ops = &psb_gem_vm_ops,
- .dumb_create = psb_gem_dumb_create,
- .dumb_map_offset = psb_gem_dumb_map_gtt,
- .dumb_destroy = psb_gem_dumb_destroy,
- .fops = &gma500_driver_fops,
- .name = DRIVER_NAME,
- .desc = DRIVER_DESC,
- .date = PSB_DRM_DRIVER_DATE,
- .major = PSB_DRM_DRIVER_MAJOR,
- .minor = PSB_DRM_DRIVER_MINOR,
- .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
-};
-
-static struct pci_driver psb_pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- .probe = psb_probe,
- .remove = psb_remove,
- .driver.pm = &psb_pm_ops,
-};
-
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- return drm_get_pci_dev(pdev, ent, &driver);
-}
-
-static int __init psb_init(void)
-{
- return drm_pci_init(&driver, &psb_pci_driver);
-}
-
-static void __exit psb_exit(void)
-{
- drm_pci_exit(&driver, &psb_pci_driver);
-}
-
-late_initcall(psb_init);
-module_exit(psb_exit);
-
-MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
deleted file mode 100644
index 11d963a055be..000000000000
--- a/drivers/staging/gma500/psb_drv.h
+++ /dev/null
@@ -1,952 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- **************************************************************************/
-
-#ifndef _PSB_DRV_H_
-#define _PSB_DRV_H_
-
-#include <linux/kref.h>
-
-#include <drm/drmP.h>
-#include "drm_global.h"
-#include "gem_glue.h"
-#include "psb_drm.h"
-#include "psb_reg.h"
-#include "psb_intel_drv.h"
-#include "gtt.h"
-#include "power.h"
-#include "mrst.h"
-#include "medfield.h"
-
-/* Append new drm mode definition here, align with libdrm definition */
-#define DRM_MODE_SCALE_NO_SCALE 2
-
-enum {
- CHIP_PSB_8108 = 0, /* Poulsbo */
- CHIP_PSB_8109 = 1, /* Poulsbo */
- CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */
- CHIP_MFLD_0130 = 3, /* Medfield */
-};
-
-#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108)
-#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
-#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
-
-/*
- * Driver definitions
- */
-
-#define DRIVER_NAME "gma500"
-#define DRIVER_DESC "DRM driver for the Intel GMA500"
-
-#define PSB_DRM_DRIVER_DATE "2011-06-06"
-#define PSB_DRM_DRIVER_MAJOR 1
-#define PSB_DRM_DRIVER_MINOR 0
-#define PSB_DRM_DRIVER_PATCHLEVEL 0
-
-/*
- * Hardware offsets
- */
-#define PSB_VDC_OFFSET 0x00000000
-#define PSB_VDC_SIZE 0x000080000
-#define MRST_MMIO_SIZE 0x0000C0000
-#define MDFLD_MMIO_SIZE 0x000100000
-#define PSB_SGX_SIZE 0x8000
-#define PSB_SGX_OFFSET 0x00040000
-#define MRST_SGX_OFFSET 0x00080000
-/*
- * PCI resource identifiers
- */
-#define PSB_MMIO_RESOURCE 0
-#define PSB_GATT_RESOURCE 2
-#define PSB_GTT_RESOURCE 3
-/*
- * PCI configuration
- */
-#define PSB_GMCH_CTRL 0x52
-#define PSB_BSM 0x5C
-#define _PSB_GMCH_ENABLED 0x4
-#define PSB_PGETBL_CTL 0x2020
-#define _PSB_PGETBL_ENABLED 0x00000001
-#define PSB_SGX_2D_SLAVE_PORT 0x4000
-
-/* To get rid of */
-#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
-#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
-
-/*
- * SGX side MMU definitions (these can probably go)
- */
-
-/*
- * Flags for external memory type field.
- */
-#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */
-#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */
-#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */
-/*
- * PTE's and PDE's
- */
-#define PSB_PDE_MASK 0x003FFFFF
-#define PSB_PDE_SHIFT 22
-#define PSB_PTE_SHIFT 12
-/*
- * Cache control
- */
-#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */
-#define PSB_PTE_WO 0x0002 /* Write only */
-#define PSB_PTE_RO 0x0004 /* Read only */
-#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */
-
-/*
- * VDC registers and bits
- */
-#define PSB_MSVDX_CLOCKGATING 0x2064
-#define PSB_TOPAZ_CLOCKGATING 0x2068
-#define PSB_HWSTAM 0x2098
-#define PSB_INSTPM 0x20C0
-#define PSB_INT_IDENTITY_R 0x20A4
-#define _MDFLD_PIPEC_EVENT_FLAG (1<<2)
-#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3)
-#define _PSB_DPST_PIPEB_FLAG (1<<4)
-#define _MDFLD_PIPEB_EVENT_FLAG (1<<4)
-#define _PSB_VSYNC_PIPEB_FLAG (1<<5)
-#define _PSB_DPST_PIPEA_FLAG (1<<6)
-#define _PSB_PIPEA_EVENT_FLAG (1<<6)
-#define _PSB_VSYNC_PIPEA_FLAG (1<<7)
-#define _MDFLD_MIPIA_FLAG (1<<16)
-#define _MDFLD_MIPIC_FLAG (1<<17)
-#define _PSB_IRQ_SGX_FLAG (1<<18)
-#define _PSB_IRQ_MSVDX_FLAG (1<<19)
-#define _LNC_IRQ_TOPAZ_FLAG (1<<20)
-
-#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \
- _PSB_VSYNC_PIPEB_FLAG)
-
-/* This flag includes all the display IRQ bits excepts the vblank irqs. */
-#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
- _MDFLD_PIPEB_EVENT_FLAG | \
- _PSB_PIPEA_EVENT_FLAG | \
- _PSB_VSYNC_PIPEA_FLAG | \
- _MDFLD_MIPIA_FLAG | \
- _MDFLD_MIPIC_FLAG)
-#define PSB_INT_IDENTITY_R 0x20A4
-#define PSB_INT_MASK_R 0x20A8
-#define PSB_INT_ENABLE_R 0x20A0
-
-#define _PSB_MMU_ER_MASK 0x0001FF00
-#define _PSB_MMU_ER_HOST (1 << 16)
-#define GPIOA 0x5010
-#define GPIOB 0x5014
-#define GPIOC 0x5018
-#define GPIOD 0x501c
-#define GPIOE 0x5020
-#define GPIOF 0x5024
-#define GPIOG 0x5028
-#define GPIOH 0x502c
-#define GPIO_CLOCK_DIR_MASK (1 << 0)
-#define GPIO_CLOCK_DIR_IN (0 << 1)
-#define GPIO_CLOCK_DIR_OUT (1 << 1)
-#define GPIO_CLOCK_VAL_MASK (1 << 2)
-#define GPIO_CLOCK_VAL_OUT (1 << 3)
-#define GPIO_CLOCK_VAL_IN (1 << 4)
-#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
-#define GPIO_DATA_DIR_MASK (1 << 8)
-#define GPIO_DATA_DIR_IN (0 << 9)
-#define GPIO_DATA_DIR_OUT (1 << 9)
-#define GPIO_DATA_VAL_MASK (1 << 10)
-#define GPIO_DATA_VAL_OUT (1 << 11)
-#define GPIO_DATA_VAL_IN (1 << 12)
-#define GPIO_DATA_PULLUP_DISABLE (1 << 13)
-
-#define VCLK_DIVISOR_VGA0 0x6000
-#define VCLK_DIVISOR_VGA1 0x6004
-#define VCLK_POST_DIV 0x6010
-
-#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
-#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
-#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
-#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
-#define PSB_COMM_USER_IRQ (1024 >> 2)
-#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
-#define PSB_COMM_FW (2048 >> 2)
-
-#define PSB_UIRQ_VISTEST 1
-#define PSB_UIRQ_OOM_REPLY 2
-#define PSB_UIRQ_FIRE_TA_REPLY 3
-#define PSB_UIRQ_FIRE_RASTER_REPLY 4
-
-#define PSB_2D_SIZE (256*1024*1024)
-#define PSB_MAX_RELOC_PAGES 1024
-
-#define PSB_LOW_REG_OFFS 0x0204
-#define PSB_HIGH_REG_OFFS 0x0600
-
-#define PSB_NUM_VBLANKS 2
-
-
-#define PSB_2D_SIZE (256*1024*1024)
-#define PSB_MAX_RELOC_PAGES 1024
-
-#define PSB_LOW_REG_OFFS 0x0204
-#define PSB_HIGH_REG_OFFS 0x0600
-
-#define PSB_NUM_VBLANKS 2
-#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
-#define PSB_LID_DELAY (DRM_HZ / 10)
-
-#define MDFLD_PNW_B0 0x04
-#define MDFLD_PNW_C0 0x08
-
-#define MDFLD_DSR_2D_3D_0 (1 << 0)
-#define MDFLD_DSR_2D_3D_2 (1 << 1)
-#define MDFLD_DSR_CURSOR_0 (1 << 2)
-#define MDFLD_DSR_CURSOR_2 (1 << 3)
-#define MDFLD_DSR_OVERLAY_0 (1 << 4)
-#define MDFLD_DSR_OVERLAY_2 (1 << 5)
-#define MDFLD_DSR_MIPI_CONTROL (1 << 6)
-#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4))
-#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5))
-#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
-
-#define MDFLD_DSR_RR 45
-#define MDFLD_DPU_ENABLE (1 << 31)
-#define MDFLD_DSR_FULLSCREEN (1 << 30)
-#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
-
-#define PSB_PWR_STATE_ON 1
-#define PSB_PWR_STATE_OFF 2
-
-#define PSB_PMPOLICY_NOPM 0
-#define PSB_PMPOLICY_CLOCKGATING 1
-#define PSB_PMPOLICY_POWERDOWN 2
-
-#define PSB_PMSTATE_POWERUP 0
-#define PSB_PMSTATE_CLOCKGATED 1
-#define PSB_PMSTATE_POWERDOWN 2
-#define PSB_PCIx_MSI_ADDR_LOC 0x94
-#define PSB_PCIx_MSI_DATA_LOC 0x98
-
-/* Medfield crystal settings */
-#define KSEL_CRYSTAL_19 1
-#define KSEL_BYPASS_19 5
-#define KSEL_BYPASS_25 6
-#define KSEL_BYPASS_83_100 7
-
-struct opregion_header;
-struct opregion_acpi;
-struct opregion_swsci;
-struct opregion_asle;
-
-struct psb_intel_opregion {
- struct opregion_header *header;
- struct opregion_acpi *acpi;
- struct opregion_swsci *swsci;
- struct opregion_asle *asle;
- int enabled;
-};
-
-struct psb_ops;
-
-struct drm_psb_private {
- struct drm_device *dev;
- const struct psb_ops *ops;
-
- struct psb_gtt gtt;
-
- /* GTT Memory manager */
- struct psb_gtt_mm *gtt_mm;
- struct page *scratch_page;
- u32 *gtt_map;
- uint32_t stolen_base;
- void *vram_addr;
- unsigned long vram_stolen_size;
- int gtt_initialized;
- u16 gmch_ctrl; /* Saved GTT setup */
- u32 pge_ctl;
-
- struct mutex gtt_mutex;
- struct resource *gtt_mem; /* Our PCI resource */
-
- struct psb_mmu_driver *mmu;
- struct psb_mmu_pd *pf_pd;
-
- /*
- * Register base
- */
-
- uint8_t *sgx_reg;
- uint8_t *vdc_reg;
- uint32_t gatt_free_offset;
-
- /*
- * Fencing / irq.
- */
-
- uint32_t vdc_irq_mask;
- uint32_t pipestat[PSB_NUM_PIPE];
-
- spinlock_t irqmask_lock;
-
- /*
- * Power
- */
-
- bool suspended;
- bool display_power;
- int display_count;
-
- /*
- * Modesetting
- */
- struct psb_intel_mode_device mode_dev;
-
- struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
- struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
- uint32_t num_pipe;
-
- /*
- * OSPM info (Power management base) (can go ?)
- */
- uint32_t ospm_base;
-
- /*
- * Sizes info
- */
-
- struct drm_psb_sizes_arg sizes;
-
- u32 fuse_reg_value;
- u32 video_device_fuse;
-
- /* PCI revision ID for B0:D2:F0 */
- uint8_t platform_rev_id;
-
- /*
- * LVDS info
- */
- int backlight_duty_cycle; /* restore backlight to this value */
- bool panel_wants_dither;
- struct drm_display_mode *panel_fixed_mode;
- struct drm_display_mode *lfp_lvds_vbt_mode;
- struct drm_display_mode *sdvo_lvds_vbt_mode;
-
- struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
- struct psb_intel_i2c_chan *lvds_i2c_bus;
-
- /* Feature bits from the VBIOS */
- unsigned int int_tv_support:1;
- unsigned int lvds_dither:1;
- unsigned int lvds_vbt:1;
- unsigned int int_crt_support:1;
- unsigned int lvds_use_ssc:1;
- int lvds_ssc_freq;
- bool is_lvds_on;
- bool is_mipi_on;
- u32 mipi_ctrl_display;
-
- unsigned int core_freq;
- uint32_t iLVDS_enable;
-
- /* Runtime PM state */
- int rpm_enabled;
-
- /* MID specific */
- struct mrst_vbt vbt_data;
- struct mrst_gct_data gct_data;
-
- /* MIPI Panel type etc */
- int panel_id;
- bool dual_mipi; /* dual display - DPI & DBI */
- bool dpi_panel_on; /* The DPI panel power is on */
- bool dpi_panel_on2; /* The DPI panel power is on */
- bool dbi_panel_on; /* The DBI panel power is on */
- bool dbi_panel_on2; /* The DBI panel power is on */
- u32 dsr_fb_update; /* DSR FB update counter */
-
- /* Moorestown HDMI state */
- struct mrst_hdmi_dev *hdmi_priv;
-
- /* Moorestown pipe config register value cache */
- uint32_t pipeconf;
- uint32_t pipeconf1;
- uint32_t pipeconf2;
-
- /* Moorestown plane control register value cache */
- uint32_t dspcntr;
- uint32_t dspcntr1;
- uint32_t dspcntr2;
-
- /* Moorestown MM backlight cache */
- uint8_t saveBKLTCNT;
- uint8_t saveBKLTREQ;
- uint8_t saveBKLTBRTL;
-
- /*
- * Register state
- */
- uint32_t saveDSPACNTR;
- uint32_t saveDSPBCNTR;
- uint32_t savePIPEACONF;
- uint32_t savePIPEBCONF;
- uint32_t savePIPEASRC;
- uint32_t savePIPEBSRC;
- uint32_t saveFPA0;
- uint32_t saveFPA1;
- uint32_t saveDPLL_A;
- uint32_t saveDPLL_A_MD;
- uint32_t saveHTOTAL_A;
- uint32_t saveHBLANK_A;
- uint32_t saveHSYNC_A;
- uint32_t saveVTOTAL_A;
- uint32_t saveVBLANK_A;
- uint32_t saveVSYNC_A;
- uint32_t saveDSPASTRIDE;
- uint32_t saveDSPASIZE;
- uint32_t saveDSPAPOS;
- uint32_t saveDSPABASE;
- uint32_t saveDSPASURF;
- uint32_t saveDSPASTATUS;
- uint32_t saveFPB0;
- uint32_t saveFPB1;
- uint32_t saveDPLL_B;
- uint32_t saveDPLL_B_MD;
- uint32_t saveHTOTAL_B;
- uint32_t saveHBLANK_B;
- uint32_t saveHSYNC_B;
- uint32_t saveVTOTAL_B;
- uint32_t saveVBLANK_B;
- uint32_t saveVSYNC_B;
- uint32_t saveDSPBSTRIDE;
- uint32_t saveDSPBSIZE;
- uint32_t saveDSPBPOS;
- uint32_t saveDSPBBASE;
- uint32_t saveDSPBSURF;
- uint32_t saveDSPBSTATUS;
- uint32_t saveVCLK_DIVISOR_VGA0;
- uint32_t saveVCLK_DIVISOR_VGA1;
- uint32_t saveVCLK_POST_DIV;
- uint32_t saveVGACNTRL;
- uint32_t saveADPA;
- uint32_t saveLVDS;
- uint32_t saveDVOA;
- uint32_t saveDVOB;
- uint32_t saveDVOC;
- uint32_t savePP_ON;
- uint32_t savePP_OFF;
- uint32_t savePP_CONTROL;
- uint32_t savePP_CYCLE;
- uint32_t savePFIT_CONTROL;
- uint32_t savePaletteA[256];
- uint32_t savePaletteB[256];
- uint32_t saveBLC_PWM_CTL2;
- uint32_t saveBLC_PWM_CTL;
- uint32_t saveCLOCKGATING;
- uint32_t saveDSPARB;
- uint32_t saveDSPATILEOFF;
- uint32_t saveDSPBTILEOFF;
- uint32_t saveDSPAADDR;
- uint32_t saveDSPBADDR;
- uint32_t savePFIT_AUTO_RATIOS;
- uint32_t savePFIT_PGM_RATIOS;
- uint32_t savePP_ON_DELAYS;
- uint32_t savePP_OFF_DELAYS;
- uint32_t savePP_DIVISOR;
- uint32_t saveBSM;
- uint32_t saveVBT;
- uint32_t saveBCLRPAT_A;
- uint32_t saveBCLRPAT_B;
- uint32_t saveDSPALINOFF;
- uint32_t saveDSPBLINOFF;
- uint32_t savePERF_MODE;
- uint32_t saveDSPFW1;
- uint32_t saveDSPFW2;
- uint32_t saveDSPFW3;
- uint32_t saveDSPFW4;
- uint32_t saveDSPFW5;
- uint32_t saveDSPFW6;
- uint32_t saveCHICKENBIT;
- uint32_t saveDSPACURSOR_CTRL;
- uint32_t saveDSPBCURSOR_CTRL;
- uint32_t saveDSPACURSOR_BASE;
- uint32_t saveDSPBCURSOR_BASE;
- uint32_t saveDSPACURSOR_POS;
- uint32_t saveDSPBCURSOR_POS;
- uint32_t save_palette_a[256];
- uint32_t save_palette_b[256];
- uint32_t saveOV_OVADD;
- uint32_t saveOV_OGAMC0;
- uint32_t saveOV_OGAMC1;
- uint32_t saveOV_OGAMC2;
- uint32_t saveOV_OGAMC3;
- uint32_t saveOV_OGAMC4;
- uint32_t saveOV_OGAMC5;
- uint32_t saveOVC_OVADD;
- uint32_t saveOVC_OGAMC0;
- uint32_t saveOVC_OGAMC1;
- uint32_t saveOVC_OGAMC2;
- uint32_t saveOVC_OGAMC3;
- uint32_t saveOVC_OGAMC4;
- uint32_t saveOVC_OGAMC5;
-
- /* MSI reg save */
- uint32_t msi_addr;
- uint32_t msi_data;
-
- /* Medfield specific register save state */
- uint32_t saveHDMIPHYMISCCTL;
- uint32_t saveHDMIB_CONTROL;
- uint32_t saveDSPCCNTR;
- uint32_t savePIPECCONF;
- uint32_t savePIPECSRC;
- uint32_t saveHTOTAL_C;
- uint32_t saveHBLANK_C;
- uint32_t saveHSYNC_C;
- uint32_t saveVTOTAL_C;
- uint32_t saveVBLANK_C;
- uint32_t saveVSYNC_C;
- uint32_t saveDSPCSTRIDE;
- uint32_t saveDSPCSIZE;
- uint32_t saveDSPCPOS;
- uint32_t saveDSPCSURF;
- uint32_t saveDSPCSTATUS;
- uint32_t saveDSPCLINOFF;
- uint32_t saveDSPCTILEOFF;
- uint32_t saveDSPCCURSOR_CTRL;
- uint32_t saveDSPCCURSOR_BASE;
- uint32_t saveDSPCCURSOR_POS;
- uint32_t save_palette_c[256];
- uint32_t saveOV_OVADD_C;
- uint32_t saveOV_OGAMC0_C;
- uint32_t saveOV_OGAMC1_C;
- uint32_t saveOV_OGAMC2_C;
- uint32_t saveOV_OGAMC3_C;
- uint32_t saveOV_OGAMC4_C;
- uint32_t saveOV_OGAMC5_C;
-
- /* DSI register save */
- uint32_t saveDEVICE_READY_REG;
- uint32_t saveINTR_EN_REG;
- uint32_t saveDSI_FUNC_PRG_REG;
- uint32_t saveHS_TX_TIMEOUT_REG;
- uint32_t saveLP_RX_TIMEOUT_REG;
- uint32_t saveTURN_AROUND_TIMEOUT_REG;
- uint32_t saveDEVICE_RESET_REG;
- uint32_t saveDPI_RESOLUTION_REG;
- uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
- uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
- uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
- uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
- uint32_t saveVERT_SYNC_PAD_COUNT_REG;
- uint32_t saveVERT_BACK_PORCH_COUNT_REG;
- uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
- uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
- uint32_t saveINIT_COUNT_REG;
- uint32_t saveMAX_RET_PAK_REG;
- uint32_t saveVIDEO_FMT_REG;
- uint32_t saveEOT_DISABLE_REG;
- uint32_t saveLP_BYTECLK_REG;
- uint32_t saveHS_LS_DBI_ENABLE_REG;
- uint32_t saveTXCLKESC_REG;
- uint32_t saveDPHY_PARAM_REG;
- uint32_t saveMIPI_CONTROL_REG;
- uint32_t saveMIPI;
- uint32_t saveMIPI_C;
-
- /* DPST register save */
- uint32_t saveHISTOGRAM_INT_CONTROL_REG;
- uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
- uint32_t savePWM_CONTROL_LOGIC;
-
- /*
- * DSI info.
- */
- void * dbi_dsr_info;
- void * dbi_dpu_info;
- void * dsi_configs[2];
- /*
- * LID-Switch
- */
- spinlock_t lid_lock;
- struct timer_list lid_timer;
- struct psb_intel_opregion opregion;
- u32 *lid_state;
- u32 lid_last_state;
-
- /*
- * Watchdog
- */
-
- uint32_t apm_reg;
- uint16_t apm_base;
-
- /*
- * Used for modifying backlight from
- * xrandr -- consider removing and using HAL instead
- */
- struct backlight_device *backlight_device;
- struct drm_property *backlight_property;
- uint32_t blc_adj1;
- uint32_t blc_adj2;
-
- void *fbdev;
- /* DPST state */
- uint32_t dsr_idle_count;
- bool is_in_idle;
- bool dsr_enable;
- void (*exit_idle)(struct drm_device *dev, u32 update_src);
-
- /* 2D acceleration */
- spinlock_t lock_2d;
-
- /* FIXME: Arrays anyone ? */
- struct mdfld_dsi_encoder *encoder0;
- struct mdfld_dsi_encoder *encoder2;
- struct mdfld_dsi_dbi_output * dbi_output;
- struct mdfld_dsi_dbi_output * dbi_output2;
- u32 bpp;
- u32 bpp2;
-
- bool dispstatus;
-};
-
-
-/*
- * Operations for each board type
- */
-
-struct psb_ops {
- const char *name;
- unsigned int accel_2d:1;
- int pipes; /* Number of output pipes */
- int crtcs; /* Number of CRTCs */
- int sgx_offset; /* Base offset of SGX device */
-
- /* Sub functions */
- struct drm_crtc_helper_funcs const *crtc_helper;
- struct drm_crtc_funcs const *crtc_funcs;
-
- /* Setup hooks */
- int (*chip_setup)(struct drm_device *dev);
- void (*chip_teardown)(struct drm_device *dev);
-
- /* Display management hooks */
- int (*output_init)(struct drm_device *dev);
- /* Power management hooks */
- void (*init_pm)(struct drm_device *dev);
- int (*save_regs)(struct drm_device *dev);
- int (*restore_regs)(struct drm_device *dev);
- int (*power_up)(struct drm_device *dev);
- int (*power_down)(struct drm_device *dev);
-
- void (*lvds_bl_power)(struct drm_device *dev, bool on);
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- /* Backlight */
- int (*backlight_init)(struct drm_device *dev);
-#endif
- int i2c_bus; /* I2C bus identifier for Moorestown */
-};
-
-
-
-struct psb_mmu_driver;
-
-extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
-extern int drm_pick_crtcs(struct drm_device *dev);
-
-static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
-{
- return (struct drm_psb_private *) dev->dev_private;
-}
-
-/*
- * MMU stuff.
- */
-
-extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
- int trap_pagefaults,
- int invalid_type,
- struct drm_psb_private *dev_priv);
-extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
-extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
- *driver);
-extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
- uint32_t gtt_start, uint32_t gtt_pages);
-extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
- int trap_pagefaults,
- int invalid_type);
-extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
-extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
-extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
- unsigned long address,
- uint32_t num_pages);
-extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
- uint32_t start_pfn,
- unsigned long address,
- uint32_t num_pages, int type);
-extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
- unsigned long *pfn);
-
-/*
- * Enable / disable MMU for different requestors.
- */
-
-
-extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
-extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride, int type);
-extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride);
-/*
- *psb_irq.c
- */
-
-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
-extern int psb_irq_enable_dpst(struct drm_device *dev);
-extern int psb_irq_disable_dpst(struct drm_device *dev);
-extern void psb_irq_preinstall(struct drm_device *dev);
-extern int psb_irq_postinstall(struct drm_device *dev);
-extern void psb_irq_uninstall(struct drm_device *dev);
-extern void psb_irq_turn_on_dpst(struct drm_device *dev);
-extern void psb_irq_turn_off_dpst(struct drm_device *dev);
-
-extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
-extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int psb_enable_vblank(struct drm_device *dev, int crtc);
-extern void psb_disable_vblank(struct drm_device *dev, int crtc);
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
-
-extern int mdfld_enable_te(struct drm_device *dev, int pipe);
-extern void mdfld_disable_te(struct drm_device *dev, int pipe);
-
-/*
- * intel_opregion.c
- */
-extern int gma_intel_opregion_init(struct drm_device *dev);
-extern int gma_intel_opregion_exit(struct drm_device *dev);
-
-/*
- * framebuffer.c
- */
-extern int psbfb_probed(struct drm_device *dev);
-extern int psbfb_remove(struct drm_device *dev,
- struct drm_framebuffer *fb);
-/*
- * accel_2d.c
- */
-extern void psbfb_copyarea(struct fb_info *info,
- const struct fb_copyarea *region);
-extern int psbfb_sync(struct fb_info *info);
-extern void psb_spank(struct drm_psb_private *dev_priv);
-extern int psb_accel_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
-
-/*
- * psb_reset.c
- */
-
-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
-extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
-
-/* modesetting */
-extern void psb_modeset_init(struct drm_device *dev);
-extern void psb_modeset_cleanup(struct drm_device *dev);
-extern int psb_fbdev_init(struct drm_device *dev);
-
-/* backlight.c */
-int gma_backlight_init(struct drm_device *dev);
-void gma_backlight_exit(struct drm_device *dev);
-
-/* mrst_crtc.c */
-extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
-
-/* mrst_lvds.c */
-extern void mrst_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-
-/* psb_intel_display.c */
-extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
-extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
-
-/* psb_intel_lvds.c */
-extern const struct drm_connector_helper_funcs
- psb_intel_lvds_connector_helper_funcs;
-extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
-
-/* gem.c */
-extern int psb_gem_init_object(struct drm_gem_object *obj);
-extern void psb_gem_free_object(struct drm_gem_object *obj);
-extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
- struct drm_file *file);
-extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args);
-extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle);
-extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset);
-extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
-extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file);
-
-/* psb_device.c */
-extern const struct psb_ops psb_chip_ops;
-
-/* mrst_device.c */
-extern const struct psb_ops mrst_chip_ops;
-
-/* mdfld_device.c */
-extern const struct psb_ops mdfld_chip_ops;
-
-/* cdv_device.c */
-extern const struct psb_ops cdv_chip_ops;
-
-/*
- * Debug print bits setting
- */
-#define PSB_D_GENERAL (1 << 0)
-#define PSB_D_INIT (1 << 1)
-#define PSB_D_IRQ (1 << 2)
-#define PSB_D_ENTRY (1 << 3)
-/* debug the get H/V BP/FP count */
-#define PSB_D_HV (1 << 4)
-#define PSB_D_DBI_BF (1 << 5)
-#define PSB_D_PM (1 << 6)
-#define PSB_D_RENDER (1 << 7)
-#define PSB_D_REG (1 << 8)
-#define PSB_D_MSVDX (1 << 9)
-#define PSB_D_TOPAZ (1 << 10)
-
-extern int drm_psb_no_fb;
-extern int drm_idle_check_interval;
-
-/*
- * Utilities
- */
-
-static inline u32 MRST_MSG_READ32(uint port, uint offset)
-{
- int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
- uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_read_config_dword(pci_root, 0xD4, &ret_val);
- pci_dev_put(pci_root);
- return ret_val;
-}
-static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
-{
- int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD4, value);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_dev_put(pci_root);
-}
-static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
-{
- int mcr = (0x10<<24) | (port << 16) | (offset << 8);
- uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_read_config_dword(pci_root, 0xD4, &ret_val);
- pci_dev_put(pci_root);
- return ret_val;
-}
-static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
-{
- int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD4, value);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_dev_put(pci_root);
-}
-
-static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- return ioread32(dev_priv->vdc_reg + reg);
-}
-
-#define REG_READ(reg) REGISTER_READ(dev, (reg))
-
-static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
- uint32_t val)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- iowrite32((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val))
-
-static inline void REGISTER_WRITE16(struct drm_device *dev,
- uint32_t reg, uint32_t val)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- iowrite16((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val))
-
-static inline void REGISTER_WRITE8(struct drm_device *dev,
- uint32_t reg, uint32_t val)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- iowrite8((val), dev_priv->vdc_reg + (reg));
-}
-
-#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val))
-
-#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs))
-#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs))
-
-/* #define TRAP_SGX_PM_FAULT 1 */
-#ifdef TRAP_SGX_PM_FAULT
-#define PSB_RSGX32(_offs) \
-({ \
- if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \
- printk(KERN_ERR \
- "access sgx when it's off!! (READ) %s, %d\n", \
- __FILE__, __LINE__); \
- melay(1000); \
- } \
- ioread32(dev_priv->sgx_reg + (_offs)); \
-})
-#else
-#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs))
-#endif
-#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs))
-
-#define MSVDX_REG_DUMP 0
-
-#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs))
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
deleted file mode 100644
index 85659613ae62..000000000000
--- a/drivers/staging/gma500/psb_intel_display.c
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Copyright © 2006-2011 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "framebuffer.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-
-#include "mdfld_output.h"
-
-struct psb_intel_clock_t {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
-};
-
-struct psb_intel_range_t {
- int min, max;
-};
-
-struct psb_intel_p2_t {
- int dot_limit;
- int p2_slow, p2_fast;
-};
-
-#define INTEL_P2_NUM 2
-
-struct psb_intel_limit_t {
- struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
- struct psb_intel_p2_t p2;
-};
-
-#define I8XX_DOT_MIN 25000
-#define I8XX_DOT_MAX 350000
-#define I8XX_VCO_MIN 930000
-#define I8XX_VCO_MAX 1400000
-#define I8XX_N_MIN 3
-#define I8XX_N_MAX 16
-#define I8XX_M_MIN 96
-#define I8XX_M_MAX 140
-#define I8XX_M1_MIN 18
-#define I8XX_M1_MAX 26
-#define I8XX_M2_MIN 6
-#define I8XX_M2_MAX 16
-#define I8XX_P_MIN 4
-#define I8XX_P_MAX 128
-#define I8XX_P1_MIN 2
-#define I8XX_P1_MAX 33
-#define I8XX_P1_LVDS_MIN 1
-#define I8XX_P1_LVDS_MAX 6
-#define I8XX_P2_SLOW 4
-#define I8XX_P2_FAST 2
-#define I8XX_P2_LVDS_SLOW 14
-#define I8XX_P2_LVDS_FAST 14 /* No fast option */
-#define I8XX_P2_SLOW_LIMIT 165000
-
-#define I9XX_DOT_MIN 20000
-#define I9XX_DOT_MAX 400000
-#define I9XX_VCO_MIN 1400000
-#define I9XX_VCO_MAX 2800000
-#define I9XX_N_MIN 3
-#define I9XX_N_MAX 8
-#define I9XX_M_MIN 70
-#define I9XX_M_MAX 120
-#define I9XX_M1_MIN 10
-#define I9XX_M1_MAX 20
-#define I9XX_M2_MIN 5
-#define I9XX_M2_MAX 9
-#define I9XX_P_SDVO_DAC_MIN 5
-#define I9XX_P_SDVO_DAC_MAX 80
-#define I9XX_P_LVDS_MIN 7
-#define I9XX_P_LVDS_MAX 98
-#define I9XX_P1_MIN 1
-#define I9XX_P1_MAX 8
-#define I9XX_P2_SDVO_DAC_SLOW 10
-#define I9XX_P2_SDVO_DAC_FAST 5
-#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000
-#define I9XX_P2_LVDS_SLOW 14
-#define I9XX_P2_LVDS_FAST 7
-#define I9XX_P2_LVDS_SLOW_LIMIT 112000
-
-#define INTEL_LIMIT_I8XX_DVO_DAC 0
-#define INTEL_LIMIT_I8XX_LVDS 1
-#define INTEL_LIMIT_I9XX_SDVO_DAC 2
-#define INTEL_LIMIT_I9XX_LVDS 3
-
-static const struct psb_intel_limit_t psb_intel_limits[] = {
- { /* INTEL_LIMIT_I8XX_DVO_DAC */
- .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
- .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
- .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
- .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
- .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
- .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
- .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
- .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX},
- .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
- .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST},
- },
- { /* INTEL_LIMIT_I8XX_LVDS */
- .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
- .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
- .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
- .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
- .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
- .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
- .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
- .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX},
- .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
- .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST},
- },
- { /* INTEL_LIMIT_I9XX_SDVO_DAC */
- .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
- .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
- .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
- .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
- .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
- .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
- .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX},
- .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
- .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
- .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast =
- I9XX_P2_SDVO_DAC_FAST},
- },
- { /* INTEL_LIMIT_I9XX_LVDS */
- .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
- .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
- .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
- .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
- .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
- .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
- .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX},
- .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
- /* The single-channel range is 25-112Mhz, and dual-channel
- * is 80-224Mhz. Prefer single channel as much as possible.
- */
- .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
- .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST},
- },
-};
-
-static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc)
-{
- const struct psb_intel_limit_t *limit;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
- limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS];
- else
- limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
- return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock)
-{
- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
- clock->p = clock->p1 * clock->p2;
- clock->vco = refclk * clock->m / (clock->n + 2);
- clock->dot = clock->vco / clock->p;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
-
-static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock)
-{
- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
- clock->p = clock->p1 * clock->p2;
- clock->vco = refclk * clock->m / (clock->n + 2);
- clock->dot = clock->vco / clock->p;
-}
-
-static void psb_intel_clock(struct drm_device *dev, int refclk,
- struct psb_intel_clock_t *clock)
-{
- return i9xx_clock(refclk, clock);
-}
-
-/**
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *l_entry;
-
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
- if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(l_entry);
- if (psb_intel_output->type == type)
- return true;
- }
- }
- return false;
-}
-
-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
-/**
- * Returns whether the given set of divisors are valid for a given refclk with
- * the given connectors.
- */
-
-static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc,
- struct psb_intel_clock_t *clock)
-{
- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
-
- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
- INTELPllInvalid("p1 out of range\n");
- if (clock->p < limit->p.min || limit->p.max < clock->p)
- INTELPllInvalid("p out of range\n");
- if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
- INTELPllInvalid("m2 out of range\n");
- if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
- INTELPllInvalid("m1 out of range\n");
- if (clock->m1 <= clock->m2)
- INTELPllInvalid("m1 <= m2\n");
- if (clock->m < limit->m.min || limit->m.max < clock->m)
- INTELPllInvalid("m out of range\n");
- if (clock->n < limit->n.min || limit->n.max < clock->n)
- INTELPllInvalid("n out of range\n");
- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
- INTELPllInvalid("vco out of range\n");
- /* XXX: We may need to be checking "Dot clock"
- * depending on the multiplier, connector, etc.,
- * rather than just a single range.
- */
- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
- INTELPllInvalid("dot out of range\n");
-
- return true;
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE. The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
-static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
- int refclk,
- struct psb_intel_clock_t *best_clock)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_clock_t clock;
- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
- int err = target;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
- /*
- * For LVDS, if the panel is on, just rely on its current
- * settings for dual-channel. We haven't figured out how to
- * reliably set up different single/dual channel state, if we
- * even can.
- */
- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
- LVDS_CLKB_POWER_UP)
- clock.p2 = limit->p2.p2_fast;
- else
- clock.p2 = limit->p2.p2_slow;
- } else {
- if (target < limit->p2.dot_limit)
- clock.p2 = limit->p2.p2_slow;
- else
- clock.p2 = limit->p2.p2_fast;
- }
-
- memset(best_clock, 0, sizeof(*best_clock));
-
- for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
- clock.m1++) {
- for (clock.m2 = limit->m2.min;
- clock.m2 < clock.m1 && clock.m2 <= limit->m2.max;
- clock.m2++) {
- for (clock.n = limit->n.min;
- clock.n <= limit->n.max; clock.n++) {
- for (clock.p1 = limit->p1.min;
- clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- psb_intel_clock(dev, refclk, &clock);
-
- if (!psb_intel_PLL_is_valid
- (crtc, &clock))
- continue;
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- }
- }
-
- return err != target;
-}
-
-void psb_intel_wait_for_vblank(struct drm_device *dev)
-{
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- mdelay(20);
-}
-
-int psb_intel_pipe_set_base(struct drm_crtc *crtc,
- int x, int y, struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_i915_master_private *master_priv; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- unsigned long start, offset;
- int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- u32 dspcntr;
- int ret = 0;
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_dbg(dev->dev, "No FB bound\n");
- goto psb_intel_pipe_cleaner;
- }
-
- /* We are displaying this buffer, make sure it is actually loaded
- into the GTT */
- ret = psb_gtt_pin(psbfb->gtt);
- if (ret < 0)
- goto psb_intel_pipe_set_base_exit;
- start = psbfb->gtt->offset;
-
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(dspstride, crtc->fb->pitches[0]);
-
- dspcntr = REG_READ(dspcntr_reg);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- psb_gtt_unpin(psbfb->gtt);
- goto psb_intel_pipe_set_base_exit;
- }
- REG_WRITE(dspcntr_reg, dspcntr);
-
-
- if (0 /* FIXMEAC - check what PSB needs */) {
- REG_WRITE(dspbase, offset);
- REG_READ(dspbase);
- REG_WRITE(dspsurf, start);
- REG_READ(dspsurf);
- } else {
- REG_WRITE(dspbase, start + offset);
- REG_READ(dspbase);
- }
-
-psb_intel_pipe_cleaner:
- /* If there was a previous display we can now unpin it */
- if (old_fb)
- psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_i915_master_private *master_priv; */
- /* struct drm_i915_private *dev_priv = dev->dev_private; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- u32 temp;
- bool enabled;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- /* Enable the DPLL */
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) == 0) {
- REG_WRITE(dpll_reg, temp);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
- }
-
- /* Enable the pipe */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) == 0)
- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
-
- /* Enable the plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
- REG_WRITE(dspcntr_reg,
- temp | DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- }
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Disable display plane */
- temp = REG_READ(dspcntr_reg);
- if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
- REG_WRITE(dspcntr_reg,
- temp & ~DISPLAY_PLANE_ENABLE);
- /* Flush the plane changes */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
- }
-
- /* Next, disable display pipes */
- temp = REG_READ(pipeconf_reg);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
- REG_READ(pipeconf_reg);
- }
-
- /* Wait for vblank for the disable to take effect. */
- psb_intel_wait_for_vblank(dev);
-
- temp = REG_READ(dpll_reg);
- if ((temp & DPLL_VCO_ENABLE) != 0) {
- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- }
-
- /* Wait for the clocks to turn off. */
- udelay(150);
- break;
- }
-
- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
- /*Set FIFO Watermarks*/
- REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void psb_intel_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-void psb_intel_encoder_prepare(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of prepare see psb_intel_lvds_prepare */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void psb_intel_encoder_commit(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of commit see psb_intel_lvds_commit */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
-{
- u32 pfit_control;
-
- pfit_control = REG_READ(PFIT_CONTROL);
-
- /* See if the panel fitter is in use */
- if ((pfit_control & PFIT_ENABLE) == 0)
- return -1;
- /* Must be on PIPE 1 for PSB */
- return 1;
-}
-
-static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- int pipe = psb_intel_crtc->pipe;
- int fp_reg = (pipe == 0) ? FPA0 : FPB0;
- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
- int refclk;
- struct psb_intel_clock_t clock;
- u32 dpll = 0, fp = 0, dspcntr, pipeconf;
- bool ok, is_sdvo = false, is_dvo = false;
- bool is_crt = false, is_lvds = false, is_tv = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *connector;
-
- /* No scan out no play */
- if (crtc->fb == NULL) {
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- return 0;
- }
-
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (!connector->encoder
- || connector->encoder->crtc != crtc)
- continue;
-
- switch (psb_intel_output->type) {
- case INTEL_OUTPUT_LVDS:
- is_lvds = true;
- break;
- case INTEL_OUTPUT_SDVO:
- is_sdvo = true;
- break;
- case INTEL_OUTPUT_DVO:
- is_dvo = true;
- break;
- case INTEL_OUTPUT_TVOUT:
- is_tv = true;
- break;
- case INTEL_OUTPUT_ANALOG:
- is_crt = true;
- break;
- }
- }
-
- refclk = 96000;
-
- ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
- &clock);
- if (!ok) {
- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
- return 0;
- }
-
- fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-
- dpll = DPLL_VGA_MODE_DIS;
- if (is_lvds) {
- dpll |= DPLLB_MODE_LVDS;
- dpll |= DPLL_DVO_HIGH_SPEED;
- } else
- dpll |= DPLLB_MODE_DAC_SERIAL;
- if (is_sdvo) {
- int sdvo_pixel_multiply =
- adjusted_mode->clock / mode->clock;
- dpll |= DPLL_DVO_HIGH_SPEED;
- dpll |=
- (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
- }
-
- /* compute bitmask from p1 value */
- dpll |= (1 << (clock.p1 - 1)) << 16;
- switch (clock.p2) {
- case 5:
- dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
- break;
- case 7:
- dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
- break;
- case 10:
- dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
- break;
- case 14:
- dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
- break;
- }
-
- if (is_tv) {
- /* XXX: just matching BIOS for now */
-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
- dpll |= 3;
- }
- dpll |= PLL_REF_INPUT_DREFCLK;
-
- /* setup pipeconf */
- pipeconf = REG_READ(pipeconf_reg);
-
- /* Set up the display plane register */
- dspcntr = DISPPLANE_GAMMA_ENABLE;
-
- if (pipe == 0)
- dspcntr |= DISPPLANE_SEL_PIPE_A;
- else
- dspcntr |= DISPPLANE_SEL_PIPE_B;
-
- dspcntr |= DISPLAY_PLANE_ENABLE;
- pipeconf |= PIPEACONF_ENABLE;
- dpll |= DPLL_VCO_ENABLE;
-
-
- /* Disable the panel fitter if it was on our pipe */
- if (psb_intel_panel_fitter_pipe(dev) == pipe)
- REG_WRITE(PFIT_CONTROL, 0);
-
- drm_mode_debug_printmodeline(mode);
-
- if (dpll & DPLL_VCO_ENABLE) {
- REG_WRITE(fp_reg, fp);
- REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
- REG_READ(dpll_reg);
- udelay(150);
- }
-
- /* The LVDS pin pair needs to be on before the DPLLs are enabled.
- * This is an exception to the general rule that mode_set doesn't turn
- * things on.
- */
- if (is_lvds) {
- u32 lvds = REG_READ(LVDS);
-
- lvds &= ~LVDS_PIPEB_SELECT;
- if (pipe == 1)
- lvds |= LVDS_PIPEB_SELECT;
-
- lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
- /* Set the B0-B3 data pairs corresponding to
- * whether we're going to
- * set the DPLLs for dual-channel mode or not.
- */
- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
- if (clock.p2 == 7)
- lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-
- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
- * appropriately here, but we need to look more
- * thoroughly into how panels behave in the two modes.
- */
-
- REG_WRITE(LVDS, lvds);
- REG_READ(LVDS);
- }
-
- REG_WRITE(fp_reg, fp);
- REG_WRITE(dpll_reg, dpll);
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
-
- /* write it again -- the BIOS does, after all */
- REG_WRITE(dpll_reg, dpll);
-
- REG_READ(dpll_reg);
- /* Wait for the clocks to stabilize. */
- udelay(150);
-
- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
- ((adjusted_mode->crtc_htotal - 1) << 16));
- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
- ((adjusted_mode->crtc_hblank_end - 1) << 16));
- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
- ((adjusted_mode->crtc_hsync_end - 1) << 16));
- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
- ((adjusted_mode->crtc_vtotal - 1) << 16));
- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
- ((adjusted_mode->crtc_vblank_end - 1) << 16));
- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
- ((adjusted_mode->crtc_vsync_end - 1) << 16));
- /* pipesrc and dspsize control the size that is scaled from,
- * which should always be the user's requested size.
- */
- REG_WRITE(dspsize_reg,
- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
- REG_WRITE(dsppos_reg, 0);
- REG_WRITE(pipesrc_reg,
- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
-
- psb_intel_wait_for_vblank(dev);
-
- REG_WRITE(dspcntr_reg, dspcntr);
-
- /* Flush the plane changes */
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-
- psb_intel_wait_for_vblank(dev);
-
- return 0;
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int palreg = PALETTE_A;
- int i;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->enabled)
- return;
-
- switch (psb_intel_crtc->pipe) {
- case 0:
- break;
- case 1:
- palreg = PALETTE_B;
- break;
- case 2:
- palreg = PALETTE_C;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- if (gma_power_begin(dev, false)) {
- for (i = 0; i < 256; i++) {
- REG_WRITE(palreg + 4 * i,
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]));
- }
- gma_power_end(dev);
- } else {
- for (i = 0; i < 256; i++) {
- dev_priv->save_palette_a[i] =
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]);
- }
-
- }
-}
-
-/**
- * Save HW states of giving crtc
- */
-static void psb_intel_crtc_save(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- int pipeA = (psb_intel_crtc->pipe == 0);
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_err(dev->dev, "No CRTC state found\n");
- return;
- }
-
- crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
- crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
- crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
- crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
- crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
- crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
- crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
- crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
- crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
- crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
- crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
- crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
- crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
-
- /*NOTE: DSPSIZE DSPPOS only for psb*/
- crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
- crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
-
- crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
-
- paletteReg = pipeA ? PALETTE_A : PALETTE_B;
- for (i = 0; i < 256; ++i)
- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void psb_intel_crtc_restore(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- /* struct drm_psb_private * dev_priv =
- (struct drm_psb_private *)dev->dev_private; */
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
- int pipeA = (psb_intel_crtc->pipe == 0);
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_err(dev->dev, "No crtc state\n");
- return;
- }
-
- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
- REG_WRITE(pipeA ? DPLL_A : DPLL_B,
- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
- REG_READ(pipeA ? DPLL_A : DPLL_B);
- udelay(150);
- }
-
- REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
- REG_READ(pipeA ? FPA0 : FPB0);
-
- REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
- REG_READ(pipeA ? FPA1 : FPB1);
-
- REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
- REG_READ(pipeA ? DPLL_A : DPLL_B);
- udelay(150);
-
- REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
- REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
- REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
- REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
- REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
- REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
- REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
-
- REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
- REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
-
- REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
- REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
-
- psb_intel_wait_for_vblank(dev);
-
- REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-
- psb_intel_wait_for_vblank(dev);
-
- paletteReg = pipeA ? PALETTE_A : PALETTE_B;
- for (i = 0; i < 256; ++i)
- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
- uint32_t temp;
- size_t addr = 0;
- struct gtt_range *gt;
- struct drm_gem_object *obj;
- int ret;
-
- /* if we want to turn of the cursor ignore width and height */
- if (!handle) {
- /* turn off the cursor */
- temp = CURSOR_MODE_DISABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, 0);
- gma_power_end(dev);
- }
-
- /* Unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = NULL;
- }
-
- return 0;
- }
-
- /* Currently we only support 64x64 cursors */
- if (width != 64 || height != 64) {
- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
-
- if (obj->size < width * height * 4) {
- dev_dbg(dev->dev, "buffer is to small\n");
- return -ENOMEM;
- }
-
- gt = container_of(obj, struct gtt_range, gem);
-
- /* Pin the memory into the GTT */
- ret = psb_gtt_pin(gt);
- if (ret) {
- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
- return ret;
- }
-
-
- addr = gt->offset; /* Or resource.start ??? */
-
- psb_intel_crtc->cursor_addr = addr;
-
- temp = 0;
- /* set the pipe for the cursor */
- temp |= (pipe << 28);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
-
- /* unpin the old bo */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = obj;
- }
- return 0;
-}
-
-static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t temp = 0;
- uint32_t addr;
-
-
- if (x < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
- x = -x;
- }
- if (y < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
- y = -y;
- }
-
- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
- addr = psb_intel_crtc->cursor_addr;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
- gma_power_end(dev);
- }
- return 0;
-}
-
-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t type, uint32_t size)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int i;
-
- if (size != 256)
- return;
-
- for (i = 0; i < 256; i++) {
- psb_intel_crtc->lut_r[i] = red[i] >> 8;
- psb_intel_crtc->lut_g[i] = green[i] >> 8;
- psb_intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- psb_intel_crtc_load_lut(crtc);
-}
-
-static int psb_crtc_set_config(struct drm_mode_set *set)
-{
- int ret;
- struct drm_device *dev = set->crtc->dev;
-
- pm_runtime_forbid(&dev->pdev->dev);
- ret = drm_crtc_helper_set_config(set);
- pm_runtime_allow(&dev->pdev->dev);
- return ret;
-}
-
-/* Returns the clock of the currently programmed mode of the given pipe. */
-static int psb_intel_crtc_clock_get(struct drm_device *dev,
- struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- u32 dpll;
- u32 fp;
- struct psb_intel_clock_t clock;
- bool is_lvds;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (gma_power_begin(dev, false)) {
- dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
- fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
- else
- fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
- is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
- gma_power_end(dev);
- } else {
- dpll = (pipe == 0) ?
- dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
-
- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
- fp = (pipe == 0) ?
- dev_priv->saveFPA0 :
- dev_priv->saveFPB0;
- else
- fp = (pipe == 0) ?
- dev_priv->saveFPA1 :
- dev_priv->saveFPB1;
-
- is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
- }
-
- clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
- clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
- clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-
- if (is_lvds) {
- clock.p1 =
- ffs((dpll &
- DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
- DPLL_FPA01_P1_POST_DIV_SHIFT);
- clock.p2 = 14;
-
- if ((dpll & PLL_REF_INPUT_MASK) ==
- PLLB_REF_INPUT_SPREADSPECTRUMIN) {
- /* XXX: might not be 66MHz */
- i8xx_clock(66000, &clock);
- } else
- i8xx_clock(48000, &clock);
- } else {
- if (dpll & PLL_P1_DIVIDE_BY_TWO)
- clock.p1 = 2;
- else {
- clock.p1 =
- ((dpll &
- DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
- DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
- }
- if (dpll & PLL_P2_DIVIDE_BY_4)
- clock.p2 = 4;
- else
- clock.p2 = 2;
-
- i8xx_clock(48000, &clock);
- }
-
- /* XXX: It would be nice to validate the clocks, but we can't reuse
- * i830PllIsValid() because it relies on the xf86_config connector
- * configuration being accurate, which it isn't necessarily.
- */
-
- return clock.dot;
-}
-
-/** Returns the currently programmed mode of the given pipe. */
-struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
- struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- struct drm_display_mode *mode;
- int htot;
- int hsync;
- int vtot;
- int vsync;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (gma_power_begin(dev, false)) {
- htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
- hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
- vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
- vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
- gma_power_end(dev);
- } else {
- htot = (pipe == 0) ?
- dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
- hsync = (pipe == 0) ?
- dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
- vtot = (pipe == 0) ?
- dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
- vsync = (pipe == 0) ?
- dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
- }
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- mode->clock = psb_intel_crtc_clock_get(dev, crtc);
- mode->hdisplay = (htot & 0xffff) + 1;
- mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
- mode->hsync_start = (hsync & 0xffff) + 1;
- mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
- mode->vdisplay = (vtot & 0xffff) + 1;
- mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
- mode->vsync_start = (vsync & 0xffff) + 1;
- mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- return mode;
-}
-
-void psb_intel_crtc_destroy(struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct gtt_range *gt;
-
- /* Unpin the old GEM object */
- if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
- psb_gtt_unpin(gt);
- drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
- psb_intel_crtc->cursor_obj = NULL;
- }
- kfree(psb_intel_crtc->crtc_state);
- drm_crtc_cleanup(crtc);
- kfree(psb_intel_crtc);
-}
-
-const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
- .dpms = psb_intel_crtc_dpms,
- .mode_fixup = psb_intel_crtc_mode_fixup,
- .mode_set = psb_intel_crtc_mode_set,
- .mode_set_base = psb_intel_pipe_set_base,
- .prepare = psb_intel_crtc_prepare,
- .commit = psb_intel_crtc_commit,
-};
-
-const struct drm_crtc_funcs psb_intel_crtc_funcs = {
- .save = psb_intel_crtc_save,
- .restore = psb_intel_crtc_restore,
- .cursor_set = psb_intel_crtc_cursor_set,
- .cursor_move = psb_intel_crtc_cursor_move,
- .gamma_set = psb_intel_crtc_gamma_set,
- .set_config = psb_crtc_set_config,
- .destroy = psb_intel_crtc_destroy,
-};
-
-/*
- * Set the default value of cursor control and base register
- * to zero. This is a workaround for h/w defect on Oaktrail
- */
-static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
-{
- u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
- u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
-
- REG_WRITE(control[pipe], 0);
- REG_WRITE(base[pipe], 0);
-}
-
-void psb_intel_crtc_init(struct drm_device *dev, int pipe,
- struct psb_intel_mode_device *mode_dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc;
- int i;
- uint16_t *r_base, *g_base, *b_base;
-
- /* We allocate a extra array of drm_connector pointers
- * for fbdev after the crtc */
- psb_intel_crtc =
- kzalloc(sizeof(struct psb_intel_crtc) +
- (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
- GFP_KERNEL);
- if (psb_intel_crtc == NULL)
- return;
-
- psb_intel_crtc->crtc_state =
- kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
- if (!psb_intel_crtc->crtc_state) {
- dev_err(dev->dev, "Crtc state error: No memory\n");
- kfree(psb_intel_crtc);
- return;
- }
-
- /* Set the CRTC operations from the chip specific data */
- drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
-
- drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
- psb_intel_crtc->pipe = pipe;
- psb_intel_crtc->plane = pipe;
-
- r_base = psb_intel_crtc->base.gamma_store;
- g_base = r_base + 256;
- b_base = g_base + 256;
- for (i = 0; i < 256; i++) {
- psb_intel_crtc->lut_r[i] = i;
- psb_intel_crtc->lut_g[i] = i;
- psb_intel_crtc->lut_b[i] = i;
- r_base[i] = i << 8;
- g_base[i] = i << 8;
- b_base[i] = i << 8;
-
- psb_intel_crtc->lut_adj[i] = 0;
- }
-
- psb_intel_crtc->mode_dev = mode_dev;
- psb_intel_crtc->cursor_addr = 0;
-
- drm_crtc_helper_add(&psb_intel_crtc->base,
- dev_priv->ops->crtc_helper);
-
- /* Setup the array of drm_connector pointer array */
- psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
- BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] =
- &psb_intel_crtc->base;
- dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] =
- &psb_intel_crtc->base;
- psb_intel_crtc->mode_set.connectors =
- (struct drm_connector **) (psb_intel_crtc + 1);
- psb_intel_crtc->mode_set.num_connectors = 0;
- psb_intel_cursor_init(dev, pipe);
-}
-
-int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
- struct drm_mode_object *drmmode_obj;
- struct psb_intel_crtc *crtc;
-
- if (!dev_priv) {
- dev_err(dev->dev, "called with no initialization\n");
- return -EINVAL;
- }
-
- drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
- DRM_MODE_OBJECT_CRTC);
-
- if (!drmmode_obj) {
- dev_err(dev->dev, "no such CRTC id\n");
- return -EINVAL;
- }
-
- crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
- pipe_from_crtc_id->pipe = crtc->pipe;
-
- return 0;
-}
-
-struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
-{
- struct drm_crtc *crtc = NULL;
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- if (psb_intel_crtc->pipe == pipe)
- break;
- }
- return crtc;
-}
-
-int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
-{
- int index_mask = 0;
- struct drm_connector *connector;
- int entry = 0;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- if (type_mask & (1 << psb_intel_output->type))
- index_mask |= (1 << entry);
- entry++;
- }
- return index_mask;
-}
-
-
-void psb_intel_modeset_cleanup(struct drm_device *dev)
-{
- drm_mode_config_cleanup(dev);
-}
-
-
-/* current intel driver doesn't take advantage of encoders
- always give back the encoder for the connector
-*/
-struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- return &psb_intel_output->enc;
-}
-
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
deleted file mode 100644
index 535b49a5e409..000000000000
--- a/drivers/staging/gma500/psb_intel_display.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* copyright (c) 2008, Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#ifndef _INTEL_DISPLAY_H_
-#define _INTEL_DISPLAY_H_
-
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t type, uint32_t size);
-void psb_intel_crtc_destroy(struct drm_crtc *crtc);
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
deleted file mode 100644
index 36b554b5c335..000000000000
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Intel Corporation.
- *
- * 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.
- *
- */
-
-#ifndef __INTEL_DRV_H__
-#define __INTEL_DRV_H__
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <linux/gpio.h>
-
-/*
- * Display related stuff
- */
-
-/* store information about an Ixxx DVO */
-/* The i830->i865 use multiple DVOs with multiple i2cs */
-/* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_OUTPUTS 6
-/* maximum connectors per crtcs in the mode set */
-#define INTELFB_CONN_LIMIT 4
-
-#define INTEL_I2C_BUS_DVO 1
-#define INTEL_I2C_BUS_SDVO 2
-
-/* these are outputs from the chip - integrated only
- * external chips are via DVO or SDVO output */
-#define INTEL_OUTPUT_UNUSED 0
-#define INTEL_OUTPUT_ANALOG 1
-#define INTEL_OUTPUT_DVO 2
-#define INTEL_OUTPUT_SDVO 3
-#define INTEL_OUTPUT_LVDS 4
-#define INTEL_OUTPUT_TVOUT 5
-#define INTEL_OUTPUT_HDMI 6
-#define INTEL_OUTPUT_MIPI 7
-#define INTEL_OUTPUT_MIPI2 8
-
-#define INTEL_DVO_CHIP_NONE 0
-#define INTEL_DVO_CHIP_LVDS 1
-#define INTEL_DVO_CHIP_TMDS 2
-#define INTEL_DVO_CHIP_TVOUT 4
-
-/*
- * Hold information useally put on the device driver privates here,
- * since it needs to be shared across multiple of devices drivers privates.
- */
-struct psb_intel_mode_device {
-
- /*
- * Abstracted memory manager operations
- */
- size_t(*bo_offset) (struct drm_device *dev, void *bo);
-
- /*
- * Cursor (Can go ?)
- */
- int cursor_needs_physical;
-
- /*
- * LVDS info
- */
- int backlight_duty_cycle; /* restore backlight to this value */
- bool panel_wants_dither;
- struct drm_display_mode *panel_fixed_mode;
- struct drm_display_mode *panel_fixed_mode2;
- struct drm_display_mode *vbt_mode; /* if any */
-
- uint32_t saveBLC_PWM_CTL;
-};
-
-struct psb_intel_i2c_chan {
- /* for getting at dev. private (mmio etc.) */
- struct drm_device *drm_dev;
- u32 reg; /* GPIO reg */
- struct i2c_adapter adapter;
- struct i2c_algo_bit_data algo;
- u8 slave_addr;
-};
-
-struct psb_intel_output {
- struct drm_connector base;
-
- struct drm_encoder enc;
- int type;
-
- struct psb_intel_i2c_chan *i2c_bus; /* for control functions */
- struct psb_intel_i2c_chan *ddc_bus; /* for DDC only stuff */
- bool load_detect_temp;
- void *dev_priv;
-
- struct psb_intel_mode_device *mode_dev;
- struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
-};
-
-struct psb_intel_crtc_state {
- uint32_t saveDSPCNTR;
- uint32_t savePIPECONF;
- uint32_t savePIPESRC;
- uint32_t saveDPLL;
- uint32_t saveFP0;
- uint32_t saveFP1;
- uint32_t saveHTOTAL;
- uint32_t saveHBLANK;
- uint32_t saveHSYNC;
- uint32_t saveVTOTAL;
- uint32_t saveVBLANK;
- uint32_t saveVSYNC;
- uint32_t saveDSPSTRIDE;
- uint32_t saveDSPSIZE;
- uint32_t saveDSPPOS;
- uint32_t saveDSPBASE;
- uint32_t savePalette[256];
-};
-
-struct psb_intel_crtc {
- struct drm_crtc base;
- int pipe;
- int plane;
- uint32_t cursor_addr;
- u8 lut_r[256], lut_g[256], lut_b[256];
- u8 lut_adj[256];
- struct psb_intel_framebuffer *fbdev_fb;
- /* a mode_set for fbdev users on this crtc */
- struct drm_mode_set mode_set;
-
- /* GEM object that holds our cursor */
- struct drm_gem_object *cursor_obj;
-
- struct drm_display_mode saved_mode;
- struct drm_display_mode saved_adjusted_mode;
-
- struct psb_intel_mode_device *mode_dev;
-
- /*crtc mode setting flags*/
- u32 mode_flags;
-
- /* Saved Crtc HW states */
- struct psb_intel_crtc_state *crtc_state;
-};
-
-#define to_psb_intel_crtc(x) \
- container_of(x, struct psb_intel_crtc, base)
-#define to_psb_intel_output(x) \
- container_of(x, struct psb_intel_output, base)
-#define enc_to_psb_intel_output(x) \
- container_of(x, struct psb_intel_output, enc)
-#define to_psb_intel_framebuffer(x) \
- container_of(x, struct psb_intel_framebuffer, base)
-
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
- const u32 reg, const char *name);
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan);
-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output);
-extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output);
-
-extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
- struct psb_intel_mode_device *mode_dev);
-extern void psb_intel_crt_init(struct drm_device *dev);
-extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device);
-extern void psb_intel_dvo_init(struct drm_device *dev);
-extern void psb_intel_tv_init(struct drm_device *dev);
-extern void psb_intel_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
-extern void mrst_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev);
-extern void mrst_dsi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void mid_dsi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev, int dsi_num);
-
-extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
-extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
-
-extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
- *connector);
-
-extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
- struct drm_crtc *crtc);
-extern void psb_intel_wait_for_vblank(struct drm_device *dev);
-extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
- int pipe);
-extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
- int sdvoB);
-extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector);
-extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
- int enable);
-extern int intelfb_probe(struct drm_device *dev);
-extern int intelfb_remove(struct drm_device *dev,
- struct drm_framebuffer *fb);
-extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device
- *dev, struct
- drm_mode_fb_cmd
- *mode_cmd,
- void *mm_private);
-extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode);
-extern int psb_intel_lvds_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value);
-extern void psb_intel_lvds_destroy(struct drm_connector *connector);
-extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
-
-extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
-extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
-
-#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
deleted file mode 100644
index 21022e1a977a..000000000000
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <drm/drmP.h>
-
-#include "intel_bios.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-
-/*
- * LVDS I2C backlight control macros
- */
-#define BRIGHTNESS_MAX_LEVEL 100
-#define BRIGHTNESS_MASK 0xFF
-#define BLC_I2C_TYPE 0x01
-#define BLC_PWM_TYPT 0x02
-
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-
-#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE)
-#define PSB_BLC_MIN_PWM_REG_FREQ (0x2)
-#define PSB_BLC_PWM_PRECISION_FACTOR (10)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-
-struct psb_intel_lvds_priv {
- /*
- * Saved LVDO output states
- */
- uint32_t savePP_ON;
- uint32_t savePP_OFF;
- uint32_t saveLVDS;
- uint32_t savePP_CONTROL;
- uint32_t savePP_CYCLE;
- uint32_t savePFIT_CONTROL;
- uint32_t savePFIT_PGM_RATIOS;
- uint32_t saveBLC_PWM_CTL;
-};
-
-
-/*
- * Returns the maximum level of the backlight duty cycle field.
- */
-static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 ret;
-
- if (gma_power_begin(dev, false)) {
- ret = REG_READ(BLC_PWM_CTL);
- gma_power_end(dev);
- } else /* Powered off, use the saved value */
- ret = dev_priv->saveBLC_PWM_CTL;
-
- /* Top 15bits hold the frequency mask */
- ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT;
-
- ret *= 2; /* Return a 16bit range as needed for setting */
- if (ret == 0)
- dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
- REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
- return ret;
-}
-
-/*
- * Set LVDS backlight level by I2C command
- *
- * FIXME: at some point we need to both track this for PM and also
- * disable runtime pm on MRST if the brightness is nil (ie blanked)
- */
-static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
- unsigned int level)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
-
- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
- u8 out_buf[2];
- unsigned int blc_i2c_brightness;
-
- struct i2c_msg msgs[] = {
- {
- .addr = lvds_i2c_bus->slave_addr,
- .flags = 0,
- .len = 2,
- .buf = out_buf,
- }
- };
-
- blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
- BRIGHTNESS_MASK /
- BRIGHTNESS_MAX_LEVEL);
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
-
- out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
- out_buf[1] = (u8)blc_i2c_brightness;
-
- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
- dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
- dev_priv->lvds_bl->brightnesscmd,
- blc_i2c_brightness);
- return 0;
- }
-
- dev_err(dev->dev, "I2C transfer error\n");
- return -1;
-}
-
-
-static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
-
- u32 max_pwm_blc;
- u32 blc_pwm_duty_cycle;
-
- max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
-
- /*BLC_PWM_CTL Should be initiated while backlight device init*/
- BUG_ON(max_pwm_blc == 0);
-
- blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
-
- blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
- REG_WRITE(BLC_PWM_CTL,
- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
- (blc_pwm_duty_cycle));
-
- dev_info(dev->dev, "Backlight lvds set brightness %08x\n",
- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
- (blc_pwm_duty_cycle));
-
- return 0;
-}
-
-/*
- * Set LVDS backlight level either by I2C or PWM
- */
-void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- dev_dbg(dev->dev, "backlight level is %d\n", level);
-
- if (!dev_priv->lvds_bl) {
- dev_err(dev->dev, "NO LVDS backlight info\n");
- return;
- }
-
- if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
- psb_lvds_i2c_set_brightness(dev, level);
- else
- psb_lvds_pwm_set_brightness(dev, level);
-}
-
-/*
- * Sets the backlight level.
- *
- * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight().
- */
-static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 blc_pwm_ctl;
-
- if (gma_power_begin(dev, false)) {
- blc_pwm_ctl = REG_READ(BLC_PWM_CTL);
- blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
- REG_WRITE(BLC_PWM_CTL,
- (blc_pwm_ctl |
- (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
- (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
- gma_power_end(dev);
- } else {
- blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
- ~BACKLIGHT_DUTY_CYCLE_MASK;
- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
- (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
- }
-}
-
-/*
- * Sets the power state for the panel.
- */
-static void psb_intel_lvds_set_power(struct drm_device *dev,
- struct psb_intel_output *output, bool on)
-{
- u32 pp_status;
-
- if (!gma_power_begin(dev, true)) {
- dev_err(dev->dev, "set power, chip off!\n");
- return;
- }
-
- if (on) {
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
- POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
-
- psb_intel_lvds_set_backlight(dev,
- output->
- mode_dev->backlight_duty_cycle);
- } else {
- psb_intel_lvds_set_backlight(dev, 0);
-
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
- ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while (pp_status & PP_ON);
- }
-
- gma_power_end(dev);
-}
-
-static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
-
- if (mode == DRM_MODE_DPMS_ON)
- psb_intel_lvds_set_power(dev, output, true);
- else
- psb_intel_lvds_set_power(dev, output, false);
-
- /* XXX: We never power down the LVDS pairs. */
-}
-
-static void psb_intel_lvds_save(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_lvds_priv *lvds_priv =
- (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
-
- lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
- lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
- lvds_priv->saveLVDS = REG_READ(LVDS);
- lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL);
- lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE);
- /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/
- lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
- lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL);
- lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
-
- /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/
- dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
- BACKLIGHT_DUTY_CYCLE_MASK);
-
- /*
- * If the light is off at server startup,
- * just make it full brightness
- */
- if (dev_priv->backlight_duty_cycle == 0)
- dev_priv->backlight_duty_cycle =
- psb_intel_lvds_get_max_backlight(dev);
-
- dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
- lvds_priv->savePP_ON,
- lvds_priv->savePP_OFF,
- lvds_priv->saveLVDS,
- lvds_priv->savePP_CONTROL,
- lvds_priv->savePP_CYCLE,
- lvds_priv->saveBLC_PWM_CTL);
-}
-
-static void psb_intel_lvds_restore(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- u32 pp_status;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_lvds_priv *lvds_priv =
- (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
-
- dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
- lvds_priv->savePP_ON,
- lvds_priv->savePP_OFF,
- lvds_priv->saveLVDS,
- lvds_priv->savePP_CONTROL,
- lvds_priv->savePP_CYCLE,
- lvds_priv->saveBLC_PWM_CTL);
-
- REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL);
- REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL);
- REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS);
- REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON);
- REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF);
- /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/
- REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE);
- REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL);
- REG_WRITE(LVDS, lvds_priv->saveLVDS);
-
- if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) {
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
- POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
- } else {
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
- ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while (pp_status & PP_ON);
- }
-}
-
-int psb_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct drm_display_mode *fixed_mode =
- psb_intel_output->mode_dev->panel_fixed_mode;
-
- if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
- fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- /* just in case */
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- return MODE_NO_INTERLACE;
-
- if (fixed_mode) {
- if (mode->hdisplay > fixed_mode->hdisplay)
- return MODE_PANEL;
- if (mode->vdisplay > fixed_mode->vdisplay)
- return MODE_PANEL;
- }
- return MODE_OK;
-}
-
-bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct psb_intel_mode_device *mode_dev =
- enc_to_psb_intel_output(encoder)->mode_dev;
- struct drm_device *dev = encoder->dev;
- struct psb_intel_crtc *psb_intel_crtc =
- to_psb_intel_crtc(encoder->crtc);
- struct drm_encoder *tmp_encoder;
- struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
- struct psb_intel_output *psb_intel_output =
- enc_to_psb_intel_output(encoder);
-
- if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
- panel_fixed_mode = mode_dev->panel_fixed_mode2;
-
- /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
- if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
- printk(KERN_ERR "Can't support LVDS on pipe A\n");
- return false;
- }
- if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) {
- printk(KERN_ERR "Must use PIPE A\n");
- return false;
- }
- /* Should never happen!! */
- list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
- head) {
- if (tmp_encoder != encoder
- && tmp_encoder->crtc == encoder->crtc) {
- printk(KERN_ERR "Can't enable LVDS and another "
- "encoder on the same pipe\n");
- return false;
- }
- }
-
- /*
- * If we have timings from the BIOS for the panel, put them in
- * to the adjusted mode. The CRTC will be set up for this mode,
- * with the panel scaling set up to source from the H/VDisplay
- * of the original mode.
- */
- if (panel_fixed_mode != NULL) {
- adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
- adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
- adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
- adjusted_mode->htotal = panel_fixed_mode->htotal;
- adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
- adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
- adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
- adjusted_mode->vtotal = panel_fixed_mode->vtotal;
- adjusted_mode->clock = panel_fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode,
- CRTC_INTERLACE_HALVE_V);
- }
-
- /*
- * XXX: It would be nice to support lower refresh rates on the
- * panels to reduce power consumption, and perhaps match the
- * user's requested refresh rate.
- */
-
- return true;
-}
-
-static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (!gma_power_begin(dev, true))
- return;
-
- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
- BACKLIGHT_DUTY_CYCLE_MASK);
-
- psb_intel_lvds_set_power(dev, output, false);
-
- gma_power_end(dev);
-}
-
-static void psb_intel_lvds_commit(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
- struct psb_intel_mode_device *mode_dev = output->mode_dev;
-
- if (mode_dev->backlight_duty_cycle == 0)
- mode_dev->backlight_duty_cycle =
- psb_intel_lvds_get_max_backlight(dev);
-
- psb_intel_lvds_set_power(dev, output, true);
-}
-
-static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pfit_control;
-
- /*
- * The LVDS pin pair will already have been turned on in the
- * psb_intel_crtc_mode_set since it has a large impact on the DPLL
- * settings.
- */
-
- /*
- * Enable automatic panel scaling so that non-native modes fill the
- * screen. Should be enabled before the pipe is enabled, according to
- * register description and PRM.
- */
- if (mode->hdisplay != adjusted_mode->hdisplay ||
- mode->vdisplay != adjusted_mode->vdisplay)
- pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
- HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- else
- pfit_control = 0;
-
- if (dev_priv->lvds_dither)
- pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
- REG_WRITE(PFIT_CONTROL, pfit_control);
-}
-
-/*
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/*
- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
- */
-static int psb_intel_lvds_get_modes(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_mode_device *mode_dev =
- psb_intel_output->mode_dev;
- int ret = 0;
-
- if (!IS_MRST(dev))
- ret = psb_intel_ddc_get_modes(psb_intel_output);
-
- if (ret)
- return ret;
-
- /* Didn't get an EDID, so
- * Set wide sync ranges so we get all modes
- * handed to valid_mode for checking
- */
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
-
- if (mode_dev->panel_fixed_mode != NULL) {
- struct drm_display_mode *mode =
- drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
- drm_mode_probed_add(connector, mode);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * psb_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
-void psb_intel_lvds_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-int psb_intel_lvds_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- struct drm_encoder *encoder = connector->encoder;
-
- if (!encoder)
- return -1;
-
- if (!strcmp(property->name, "scaling mode")) {
- struct psb_intel_crtc *crtc =
- to_psb_intel_crtc(encoder->crtc);
- uint64_t curval;
-
- if (!crtc)
- goto set_prop_error;
-
- switch (value) {
- case DRM_MODE_SCALE_FULLSCREEN:
- break;
- case DRM_MODE_SCALE_NO_SCALE:
- break;
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- goto set_prop_error;
- }
-
- if (drm_connector_property_get_value(connector,
- property,
- &curval))
- goto set_prop_error;
-
- if (curval == value)
- goto set_prop_done;
-
- if (drm_connector_property_set_value(connector,
- property,
- value))
- goto set_prop_error;
-
- if (crtc->saved_mode.hdisplay != 0 &&
- crtc->saved_mode.vdisplay != 0) {
- if (!drm_crtc_helper_set_mode(encoder->crtc,
- &crtc->saved_mode,
- encoder->crtc->x,
- encoder->crtc->y,
- encoder->crtc->fb))
- goto set_prop_error;
- }
- } else if (!strcmp(property->name, "backlight")) {
- if (drm_connector_property_set_value(connector,
- property,
- value))
- goto set_prop_error;
- else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *devp =
- encoder->dev->dev_private;
- struct backlight_device *bd = devp->backlight_device;
- if (bd) {
- bd->props.brightness = value;
- backlight_update_status(bd);
- }
-#endif
- }
- } else if (!strcmp(property->name, "DPMS")) {
- struct drm_encoder_helper_funcs *hfuncs
- = encoder->helper_private;
- hfuncs->dpms(encoder, value);
- }
-
-set_prop_done:
- return 0;
-set_prop_error:
- return -1;
-}
-
-static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = {
- .dpms = psb_intel_lvds_encoder_dpms,
- .mode_fixup = psb_intel_lvds_mode_fixup,
- .prepare = psb_intel_lvds_prepare,
- .mode_set = psb_intel_lvds_mode_set,
- .commit = psb_intel_lvds_commit,
-};
-
-const struct drm_connector_helper_funcs
- psb_intel_lvds_connector_helper_funcs = {
- .get_modes = psb_intel_lvds_get_modes,
- .mode_valid = psb_intel_lvds_mode_valid,
- .best_encoder = psb_intel_best_encoder,
-};
-
-const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .save = psb_intel_lvds_save,
- .restore = psb_intel_lvds_restore,
- .detect = psb_intel_lvds_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = psb_intel_lvds_set_property,
- .destroy = psb_intel_lvds_destroy,
-};
-
-
-static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
- .destroy = psb_intel_lvds_enc_destroy,
-};
-
-
-
-/**
- * psb_intel_lvds_init - setup LVDS connectors on this device
- * @dev: drm device
- *
- * Create the connector, register the LVDS DDC bus, and try to figure out what
- * modes we can display on the LVDS panel (if present).
- */
-void psb_intel_lvds_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev)
-{
- struct psb_intel_output *psb_intel_output;
- struct psb_intel_lvds_priv *lvds_priv;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- struct drm_display_mode *scan; /* *modes, *bios_mode; */
- struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 lvds;
- int pipe;
-
- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
- if (!lvds_priv) {
- kfree(psb_intel_output);
- dev_err(dev->dev, "LVDS private allocation error\n");
- return;
- }
-
- psb_intel_output->dev_priv = lvds_priv;
- psb_intel_output->mode_dev = mode_dev;
-
- connector = &psb_intel_output->base;
- encoder = &psb_intel_output->enc;
- drm_connector_init(dev, &psb_intel_output->base,
- &psb_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
-
- drm_encoder_init(dev, &psb_intel_output->enc,
- &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
- psb_intel_output->type = INTEL_OUTPUT_LVDS;
-
- drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
- drm_connector_helper_add(connector,
- &psb_intel_lvds_connector_helper_funcs);
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- /*Attach connector properties*/
- drm_connector_attach_property(connector,
- dev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_FULLSCREEN);
- drm_connector_attach_property(connector,
- dev_priv->backlight_property,
- BRIGHTNESS_MAX_LEVEL);
-
- /*
- * Set up I2C bus
- * FIXME: distroy i2c_bus when exit
- */
- psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
- GPIOB,
- "LVDSBLC_B");
- if (!psb_intel_output->i2c_bus) {
- dev_printk(KERN_ERR,
- &dev->pdev->dev, "I2C bus registration failed.\n");
- goto failed_blc_i2c;
- }
- psb_intel_output->i2c_bus->slave_addr = 0x2C;
- dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
-
- /*
- * LVDS discovery:
- * 1) check for EDID on DDC
- * 2) check for VBT data
- * 3) check to see if LVDS is already on
- * if none of the above, no panel
- * 4) make sure lid is open
- * if closed, act like it's not there for now
- */
-
- /* Set up the DDC bus. */
- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
- GPIOC,
- "LVDSDDC_C");
- if (!psb_intel_output->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev,
- "DDC bus registration " "failed.\n");
- goto failed_ddc;
- }
-
- /*
- * Attempt to get the fixed panel mode from DDC. Assume that the
- * preferred mode is the right one.
- */
- psb_intel_ddc_get_modes(psb_intel_output);
- list_for_each_entry(scan, &connector->probed_modes, head) {
- if (scan->type & DRM_MODE_TYPE_PREFERRED) {
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, scan);
- goto out; /* FIXME: check for quirks */
- }
- }
-
- /* Failed to get EDID, what about VBT? do we need this? */
- if (mode_dev->vbt_mode)
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, mode_dev->vbt_mode);
-
- if (!mode_dev->panel_fixed_mode)
- if (dev_priv->lfp_lvds_vbt_mode)
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev,
- dev_priv->lfp_lvds_vbt_mode);
-
- /*
- * If we didn't get EDID, try checking if the panel is already turned
- * on. If so, assume that whatever is currently programmed is the
- * correct mode.
- */
- lvds = REG_READ(LVDS);
- pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
- crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
-
- if (crtc && (lvds & LVDS_PORT_EN)) {
- mode_dev->panel_fixed_mode =
- psb_intel_crtc_mode_get(dev, crtc);
- if (mode_dev->panel_fixed_mode) {
- mode_dev->panel_fixed_mode->type |=
- DRM_MODE_TYPE_PREFERRED;
- goto out; /* FIXME: check for quirks */
- }
- }
-
- /* If we still don't have a mode after all that, give up. */
- if (!mode_dev->panel_fixed_mode) {
- dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
- }
-
- /*
- * Blacklist machines with BIOSes that list an LVDS panel without
- * actually having one.
- */
-out:
- drm_sysfs_connector_add(connector);
- return;
-
-failed_find:
- if (psb_intel_output->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
-failed_ddc:
- if (psb_intel_output->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-failed_blc_i2c:
- drm_encoder_cleanup(encoder);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c
deleted file mode 100644
index bde1aff96190..000000000000
--- a/drivers/staging/gma500/psb_intel_modes.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2007 Intel Corporation
- *
- * 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.
- *
- * Authers: Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <drm/drmP.h>
-#include "psb_intel_drv.h"
-
-/**
- * psb_intel_ddc_probe
- *
- */
-bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output)
-{
- u8 out_buf[] = { 0x0, 0x0 };
- u8 buf[2];
- int ret;
- struct i2c_msg msgs[] = {
- {
- .addr = 0x50,
- .flags = 0,
- .len = 1,
- .buf = out_buf,
- },
- {
- .addr = 0x50,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = buf,
- }
- };
-
- ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2);
- if (ret == 2)
- return true;
-
- return false;
-}
-
-/**
- * psb_intel_ddc_get_modes - get modelist from monitor
- * @connector: DRM connector device to use
- *
- * Fetch the EDID information from @connector using the DDC bus.
- */
-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output)
-{
- struct edid *edid;
- int ret = 0;
-
- edid =
- drm_get_edid(&psb_intel_output->base,
- &psb_intel_output->ddc_bus->adapter);
- if (edid) {
- drm_mode_connector_update_edid_property(&psb_intel_output->
- base, edid);
- ret = drm_add_edid_modes(&psb_intel_output->base, edid);
- kfree(edid);
- }
- return ret;
-}
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
deleted file mode 100644
index 1ac16aa791c9..000000000000
--- a/drivers/staging/gma500/psb_intel_reg.h
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * Copyright (c) 2009, Intel Corporation.
- *
- * 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.
- */
-#ifndef __PSB_INTEL_REG_H__
-#define __PSB_INTEL_REG_H__
-
-#define BLC_PWM_CTL 0x61254
-#define BLC_PWM_CTL2 0x61250
-#define BLC_PWM_CTL_C 0x62254
-#define BLC_PWM_CTL2_C 0x62250
-#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
-/*
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
-#define BLM_LEGACY_MODE (1 << 16)
-/*
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
-#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
-
-#define I915_GCFGC 0xf0
-#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
-#define I915_DISPLAY_CLOCK_MASK (7 << 4)
-
-#define I855_HPLLCC 0xc0
-#define I855_CLOCK_CONTROL_MASK (3 << 0)
-#define I855_CLOCK_133_200 (0 << 0)
-#define I855_CLOCK_100_200 (1 << 0)
-#define I855_CLOCK_100_133 (2 << 0)
-#define I855_CLOCK_166_250 (3 << 0)
-
-/* I830 CRTC registers */
-#define HTOTAL_A 0x60000
-#define HBLANK_A 0x60004
-#define HSYNC_A 0x60008
-#define VTOTAL_A 0x6000c
-#define VBLANK_A 0x60010
-#define VSYNC_A 0x60014
-#define PIPEASRC 0x6001c
-#define BCLRPAT_A 0x60020
-#define VSYNCSHIFT_A 0x60028
-
-#define HTOTAL_B 0x61000
-#define HBLANK_B 0x61004
-#define HSYNC_B 0x61008
-#define VTOTAL_B 0x6100c
-#define VBLANK_B 0x61010
-#define VSYNC_B 0x61014
-#define PIPEBSRC 0x6101c
-#define BCLRPAT_B 0x61020
-#define VSYNCSHIFT_B 0x61028
-
-#define HTOTAL_C 0x62000
-#define HBLANK_C 0x62004
-#define HSYNC_C 0x62008
-#define VTOTAL_C 0x6200c
-#define VBLANK_C 0x62010
-#define VSYNC_C 0x62014
-#define PIPECSRC 0x6201c
-#define BCLRPAT_C 0x62020
-#define VSYNCSHIFT_C 0x62028
-
-#define PP_STATUS 0x61200
-# define PP_ON (1 << 31)
-/*
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-#define PP_READY (1 << 30)
-#define PP_SEQUENCE_NONE (0 << 28)
-#define PP_SEQUENCE_ON (1 << 28)
-#define PP_SEQUENCE_OFF (2 << 28)
-#define PP_SEQUENCE_MASK 0x30000000
-#define PP_CONTROL 0x61204
-#define POWER_TARGET_ON (1 << 0)
-
-#define LVDSPP_ON 0x61208
-#define LVDSPP_OFF 0x6120c
-#define PP_CYCLE 0x61210
-
-#define PFIT_CONTROL 0x61230
-#define PFIT_ENABLE (1 << 31)
-#define PFIT_PIPE_MASK (3 << 29)
-#define PFIT_PIPE_SHIFT 29
-#define PFIT_SCALING_MODE_PILLARBOX (1 << 27)
-#define PFIT_SCALING_MODE_LETTERBOX (3 << 26)
-#define VERT_INTERP_DISABLE (0 << 10)
-#define VERT_INTERP_BILINEAR (1 << 10)
-#define VERT_INTERP_MASK (3 << 10)
-#define VERT_AUTO_SCALE (1 << 9)
-#define HORIZ_INTERP_DISABLE (0 << 6)
-#define HORIZ_INTERP_BILINEAR (1 << 6)
-#define HORIZ_INTERP_MASK (3 << 6)
-#define HORIZ_AUTO_SCALE (1 << 5)
-#define PANEL_8TO6_DITHER_ENABLE (1 << 3)
-
-#define PFIT_PGM_RATIOS 0x61234
-#define PFIT_VERT_SCALE_MASK 0xfff00000
-#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
-
-#define PFIT_AUTO_RATIOS 0x61238
-
-#define DPLL_A 0x06014
-#define DPLL_B 0x06018
-#define DPLL_VCO_ENABLE (1 << 31)
-#define DPLL_DVO_HIGH_SPEED (1 << 30)
-#define DPLL_SYNCLOCK_ENABLE (1 << 29)
-#define DPLL_VGA_MODE_DIS (1 << 28)
-#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
-#define DPLLB_MODE_LVDS (2 << 26) /* i915 */
-#define DPLL_MODE_MASK (3 << 26)
-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
-#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
-#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
-#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
-#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
-#define DPLL_LOCK (1 << 15) /* CDV */
-
-/*
- * The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
-/*
- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
- * this field (only one bit may be set).
- */
-#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
-#define DPLL_FPA01_P1_POST_DIV_SHIFT 16
-#define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required
- * in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
-#define PLL_REF_INPUT_DREFCLK (0 << 13)
-#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
-#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO
- * TVCLKIN */
-#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
-#define PLL_REF_INPUT_MASK (3 << 13)
-#define PLL_LOAD_PULSE_PHASE_SHIFT 9
-/*
- * Parallel to Serial Load Pulse phase selection.
- * Selects the phase for the 10X DPLL clock for the PCIe
- * digital display port. The range is 4 to 13; 10 or more
- * is just a flip delay. The default is 6
- */
-#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-#define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
-
-/*
- * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_MULTIPLIER_MASK 0x000000ff
-#define SDVO_MULTIPLIER_SHIFT_HIRES 4
-#define SDVO_MULTIPLIER_SHIFT_VGA 0
-
-/*
- * PLL_MD
- */
-/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD 0x0601c
-/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD 0x06020
-/*
- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
- *
- * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
- */
-#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
-#define DPLL_MD_UDI_DIVIDER_SHIFT 24
-/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
-#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
-/*
- * SDVO/UDI pixel multiplier.
- *
- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
- * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
- * dummy bytes in the datastream at an increased clock rate, with both sides of
- * the link knowing how many bytes are fill.
- *
- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
- * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
- * through an SDVO command.
- *
- * This register field has values of multiplication factor minus 1, with
- * a maximum multiplier of 5 for SDVO.
- */
-#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
-#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
-/*
- * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
- * This best be set to the default value (3) or the CRT won't work. No,
- * I don't entirely understand what this does...
- */
-#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
-#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
-
-#define DPLL_TEST 0x606c
-#define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
-#define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
-#define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
-#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
-#define DPLLB_TEST_N_BYPASS (1 << 19)
-#define DPLLB_TEST_M_BYPASS (1 << 18)
-#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
-#define DPLLA_TEST_N_BYPASS (1 << 3)
-#define DPLLA_TEST_M_BYPASS (1 << 2)
-#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
-
-#define ADPA 0x61100
-#define ADPA_DAC_ENABLE (1 << 31)
-#define ADPA_DAC_DISABLE 0
-#define ADPA_PIPE_SELECT_MASK (1 << 30)
-#define ADPA_PIPE_A_SELECT 0
-#define ADPA_PIPE_B_SELECT (1 << 30)
-#define ADPA_USE_VGA_HVPOLARITY (1 << 15)
-#define ADPA_SETS_HVPOLARITY 0
-#define ADPA_VSYNC_CNTL_DISABLE (1 << 11)
-#define ADPA_VSYNC_CNTL_ENABLE 0
-#define ADPA_HSYNC_CNTL_DISABLE (1 << 10)
-#define ADPA_HSYNC_CNTL_ENABLE 0
-#define ADPA_VSYNC_ACTIVE_HIGH (1 << 4)
-#define ADPA_VSYNC_ACTIVE_LOW 0
-#define ADPA_HSYNC_ACTIVE_HIGH (1 << 3)
-#define ADPA_HSYNC_ACTIVE_LOW 0
-
-#define FPA0 0x06040
-#define FPA1 0x06044
-#define FPB0 0x06048
-#define FPB1 0x0604c
-#define FP_N_DIV_MASK 0x003f0000
-#define FP_N_DIV_SHIFT 16
-#define FP_M1_DIV_MASK 0x00003f00
-#define FP_M1_DIV_SHIFT 8
-#define FP_M2_DIV_MASK 0x0000003f
-#define FP_M2_DIV_SHIFT 0
-
-#define PORT_HOTPLUG_EN 0x61110
-#define SDVOB_HOTPLUG_INT_EN (1 << 26)
-#define SDVOC_HOTPLUG_INT_EN (1 << 25)
-#define TV_HOTPLUG_INT_EN (1 << 18)
-#define CRT_HOTPLUG_INT_EN (1 << 9)
-#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
-/* CDV.. */
-#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
-#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
-#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
-#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
-#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
-#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
-#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
-#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
-#define CRT_HOTPLUG_DETECT_MASK 0x000000F8
-
-#define PORT_HOTPLUG_STAT 0x61114
-#define CRT_HOTPLUG_INT_STATUS (1 << 11)
-#define TV_HOTPLUG_INT_STATUS (1 << 10)
-#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
-#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
-#define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
-#define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
-#define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
-#define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
-
-#define SDVOB 0x61140
-#define SDVOC 0x61160
-#define SDVO_ENABLE (1 << 31)
-#define SDVO_PIPE_B_SELECT (1 << 30)
-#define SDVO_STALL_SELECT (1 << 29)
-#define SDVO_INTERRUPT_ENABLE (1 << 26)
-
-/**
- * 915G/GM SDVO pixel multiplier.
- *
- * Programmed value is multiplier - 1, up to 5x.
- *
- * DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT 23
-#define SDVO_PHASE_SELECT_MASK (15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
-#define SDVOC_GANG_MODE (1 << 16)
-#define SDVO_BORDER_ENABLE (1 << 7)
-#define SDVOB_PCIE_CONCURRENCY (1 << 3)
-#define SDVO_DETECTED (1 << 2)
-/* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK (1 << 17)
-
-/*
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
- *
- * All of the clock/data pairs are force powered down by power sequencing.
- */
-#define LVDS 0x61180
-/*
- * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
- * the DPLL semantics change when the LVDS is assigned to that pipe.
- */
-#define LVDS_PORT_EN (1 << 31)
-/* Selects pipe B for LVDS data. Must be set on pre-965. */
-#define LVDS_PIPEB_SELECT (1 << 30)
-
-/* Turns on border drawing to allow centered display. */
-#define LVDS_BORDER_EN (1 << 15)
-
-/*
- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
- * pixel.
- */
-#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
-#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
-#define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
-/*
- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
- * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
- * on.
- */
-#define LVDS_A3_POWER_MASK (3 << 6)
-#define LVDS_A3_POWER_DOWN (0 << 6)
-#define LVDS_A3_POWER_UP (3 << 6)
-/*
- * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
- * is set.
- */
-#define LVDS_CLKB_POWER_MASK (3 << 4)
-#define LVDS_CLKB_POWER_DOWN (0 << 4)
-#define LVDS_CLKB_POWER_UP (3 << 4)
-/*
- * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
- * setting for whether we are in dual-channel mode. The B3 pair will
- * additionally only be powered up when LVDS_A3_POWER_UP is set.
- */
-#define LVDS_B0B3_POWER_MASK (3 << 2)
-#define LVDS_B0B3_POWER_DOWN (0 << 2)
-#define LVDS_B0B3_POWER_UP (3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE (1 << 31)
-#define PIPEACONF_DISABLE 0
-#define PIPEACONF_DOUBLE_WIDE (1 << 30)
-#define PIPECONF_ACTIVE (1 << 30)
-#define I965_PIPECONF_ACTIVE (1 << 30)
-#define PIPECONF_DSIPLL_LOCK (1 << 29)
-#define PIPEACONF_SINGLE_WIDE 0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_DSR (1 << 26)
-#define PIPEACONF_PIPE_LOCKED (1 << 25)
-#define PIPEACONF_PALETTE 0
-#define PIPECONF_FORCE_BORDER (1 << 25)
-#define PIPEACONF_GAMMA (1 << 24)
-#define PIPECONF_PROGRESSIVE (0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
-#define PIPECONF_PLANE_OFF (1 << 19)
-#define PIPECONF_CURSOR_OFF (1 << 18)
-
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE (1 << 31)
-#define PIPEBCONF_DISABLE 0
-#define PIPEBCONF_DOUBLE_WIDE (1 << 30)
-#define PIPEBCONF_DISABLE 0
-#define PIPEBCONF_GAMMA (1 << 24)
-#define PIPEBCONF_PALETTE 0
-
-#define PIPECCONF 0x72008
-
-#define PIPEBGCMAXRED 0x71010
-#define PIPEBGCMAXGREEN 0x71014
-#define PIPEBGCMAXBLUE 0x71018
-
-#define PIPEASTAT 0x70024
-#define PIPEBSTAT 0x71024
-#define PIPECSTAT 0x72024
-#define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1)
-#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2)
-#define PIPE_VBLANK_CLEAR (1 << 1)
-#define PIPE_VBLANK_STATUS (1 << 1)
-#define PIPE_TE_STATUS (1UL << 6)
-#define PIPE_DPST_EVENT_STATUS (1UL << 7)
-#define PIPE_VSYNC_CLEAR (1UL << 9)
-#define PIPE_VSYNC_STATUS (1UL << 9)
-#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11)
-#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17)
-#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18)
-#define PIPE_TE_ENABLE (1UL << 22)
-#define PIPE_DPST_EVENT_ENABLE (1UL << 23)
-#define PIPE_VSYNC_ENABL (1UL << 25)
-#define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27)
-#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \
- PIPE_HDMI_AUDIO_BUFFER_DONE)
-#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
-#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17))
-#define HISTOGRAM_INT_CONTROL 0x61268
-#define HISTOGRAM_BIN_DATA 0X61264
-#define HISTOGRAM_LOGIC_CONTROL 0x61260
-#define PWM_CONTROL_LOGIC 0x61250
-#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10)
-#define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31)
-#define HISTOGRAM_LOGIC_ENABLE (1UL << 31)
-#define PWM_LOGIC_ENABLE (1UL << 31)
-#define PWM_PHASEIN_ENABLE (1UL << 25)
-#define PWM_PHASEIN_INT_ENABLE (1UL << 24)
-#define PWM_PHASEIN_VB_COUNT 0x00001f00
-#define PWM_PHASEIN_INC 0x0000001f
-#define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30)
-#define DPST_YUV_LUMA_MODE 0
-
-struct dpst_ie_histogram_control {
- union {
- uint32_t data;
- struct {
- uint32_t bin_reg_index:7;
- uint32_t reserved:4;
- uint32_t bin_reg_func_select:1;
- uint32_t sync_to_phase_in:1;
- uint32_t alt_enhancement_mode:2;
- uint32_t reserved1:1;
- uint32_t sync_to_phase_in_count:8;
- uint32_t histogram_mode_select:1;
- uint32_t reserved2:4;
- uint32_t ie_pipe_assignment:1;
- uint32_t ie_mode_table_enabled:1;
- uint32_t ie_histogram_enable:1;
- };
- };
-};
-
-struct dpst_guardband {
- union {
- uint32_t data;
- struct {
- uint32_t guardband:22;
- uint32_t guardband_interrupt_delay:8;
- uint32_t interrupt_status:1;
- uint32_t interrupt_enable:1;
- };
- };
-};
-
-#define PIPEAFRAMEHIGH 0x70040
-#define PIPEAFRAMEPIXEL 0x70044
-#define PIPEBFRAMEHIGH 0x71040
-#define PIPEBFRAMEPIXEL 0x71044
-#define PIPECFRAMEHIGH 0x72040
-#define PIPECFRAMEPIXEL 0x72044
-#define PIPE_FRAME_HIGH_MASK 0x0000ffff
-#define PIPE_FRAME_HIGH_SHIFT 0
-#define PIPE_FRAME_LOW_MASK 0xff000000
-#define PIPE_FRAME_LOW_SHIFT 24
-#define PIPE_PIXEL_MASK 0x00ffffff
-#define PIPE_PIXEL_SHIFT 0
-
-#define DSPARB 0x70030
-#define DSPFW1 0x70034
-#define DSPFW2 0x70038
-#define DSPFW3 0x7003c
-#define DSPFW4 0x70050
-#define DSPFW5 0x70054
-#define DSPFW6 0x70058
-#define DSPCHICKENBIT 0x70400
-#define DSPACNTR 0x70180
-#define DSPBCNTR 0x71180
-#define DSPCCNTR 0x72180
-#define DISPLAY_PLANE_ENABLE (1 << 31)
-#define DISPLAY_PLANE_DISABLE 0
-#define DISPPLANE_GAMMA_ENABLE (1 << 30)
-#define DISPPLANE_GAMMA_DISABLE 0
-#define DISPPLANE_PIXFORMAT_MASK (0xf << 26)
-#define DISPPLANE_8BPP (0x2 << 26)
-#define DISPPLANE_15_16BPP (0x4 << 26)
-#define DISPPLANE_16BPP (0x5 << 26)
-#define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26)
-#define DISPPLANE_32BPP (0x7 << 26)
-#define DISPPLANE_STEREO_ENABLE (1 << 25)
-#define DISPPLANE_STEREO_DISABLE 0
-#define DISPPLANE_SEL_PIPE_MASK (1 << 24)
-#define DISPPLANE_SEL_PIPE_POS 24
-#define DISPPLANE_SEL_PIPE_A 0
-#define DISPPLANE_SEL_PIPE_B (1 << 24)
-#define DISPPLANE_SRC_KEY_ENABLE (1 << 22)
-#define DISPPLANE_SRC_KEY_DISABLE 0
-#define DISPPLANE_LINE_DOUBLE (1 << 20)
-#define DISPPLANE_NO_LINE_DOUBLE 0
-#define DISPPLANE_STEREO_POLARITY_FIRST 0
-#define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE 0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
-#define DISPPLANE_BOTTOM (4)
-
-#define DSPABASE 0x70184
-#define DSPALINOFF 0x70184
-#define DSPASTRIDE 0x70188
-
-#define DSPBBASE 0x71184
-#define DSPBLINOFF 0X71184
-#define DSPBADDR DSPBBASE
-#define DSPBSTRIDE 0x71188
-
-#define DSPCBASE 0x72184
-#define DSPCLINOFF 0x72184
-#define DSPCSTRIDE 0x72188
-
-#define DSPAKEYVAL 0x70194
-#define DSPAKEYMASK 0x70198
-
-#define DSPAPOS 0x7018C /* reserved */
-#define DSPASIZE 0x70190
-#define DSPBPOS 0x7118C
-#define DSPBSIZE 0x71190
-#define DSPCPOS 0x7218C
-#define DSPCSIZE 0x72190
-
-#define DSPASURF 0x7019C
-#define DSPATILEOFF 0x701A4
-
-#define DSPBSURF 0x7119C
-#define DSPBTILEOFF 0x711A4
-
-#define DSPCSURF 0x7219C
-#define DSPCTILEOFF 0x721A4
-#define DSPCKEYMAXVAL 0x721A0
-#define DSPCKEYMINVAL 0x72194
-#define DSPCKEYMSK 0x72198
-
-#define VGACNTRL 0x71400
-#define VGA_DISP_DISABLE (1 << 31)
-#define VGA_2X_MODE (1 << 30)
-#define VGA_PIPE_B_SELECT (1 << 29)
-
-/*
- * Overlay registers
- */
-#define OV_C_OFFSET 0x08000
-#define OV_OVADD 0x30000
-#define OV_DOVASTA 0x30008
-# define OV_PIPE_SELECT ((1 << 6)|(1 << 7))
-# define OV_PIPE_SELECT_POS 6
-# define OV_PIPE_A 0
-# define OV_PIPE_C 1
-#define OV_OGAMC5 0x30010
-#define OV_OGAMC4 0x30014
-#define OV_OGAMC3 0x30018
-#define OV_OGAMC2 0x3001C
-#define OV_OGAMC1 0x30020
-#define OV_OGAMC0 0x30024
-#define OVC_OVADD 0x38000
-#define OVC_DOVCSTA 0x38008
-#define OVC_OGAMC5 0x38010
-#define OVC_OGAMC4 0x38014
-#define OVC_OGAMC3 0x38018
-#define OVC_OGAMC2 0x3801C
-#define OVC_OGAMC1 0x38020
-#define OVC_OGAMC0 0x38024
-
-/*
- * Some BIOS scratch area registers. The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-#define SWF0 0x71410
-#define SWF1 0x71414
-#define SWF2 0x71418
-#define SWF3 0x7141c
-#define SWF4 0x71420
-#define SWF5 0x71424
-#define SWF6 0x71428
-
-/*
- * 855 scratch registers.
- */
-#define SWF00 0x70410
-#define SWF01 0x70414
-#define SWF02 0x70418
-#define SWF03 0x7041c
-#define SWF04 0x70420
-#define SWF05 0x70424
-#define SWF06 0x70428
-
-#define SWF10 SWF0
-#define SWF11 SWF1
-#define SWF12 SWF2
-#define SWF13 SWF3
-#define SWF14 SWF4
-#define SWF15 SWF5
-#define SWF16 SWF6
-
-#define SWF30 0x72414
-#define SWF31 0x72418
-#define SWF32 0x7241c
-
-
-/*
- * Palette registers
- */
-#define PALETTE_A 0x0a000
-#define PALETTE_B 0x0a800
-#define PALETTE_C 0x0ac00
-
-/* Cursor A & B regs */
-#define CURACNTR 0x70080
-#define CURSOR_MODE_DISABLE 0x00
-#define CURSOR_MODE_64_32B_AX 0x07
-#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
-#define MCURSOR_GAMMA_ENABLE (1 << 26)
-#define CURABASE 0x70084
-#define CURAPOS 0x70088
-#define CURSOR_POS_MASK 0x007FF
-#define CURSOR_POS_SIGN 0x8000
-#define CURSOR_X_SHIFT 0
-#define CURSOR_Y_SHIFT 16
-#define CURBCNTR 0x700c0
-#define CURBBASE 0x700c4
-#define CURBPOS 0x700c8
-#define CURCCNTR 0x700e0
-#define CURCBASE 0x700e4
-#define CURCPOS 0x700e8
-
-/*
- * Interrupt Registers
- */
-#define IER 0x020a0
-#define IIR 0x020a4
-#define IMR 0x020a8
-#define ISR 0x020ac
-
-/*
- * MOORESTOWN delta registers
- */
-#define MRST_DPLL_A 0x0f014
-#define MDFLD_DPLL_B 0x0f018
-#define MDFLD_INPUT_REF_SEL (1 << 14)
-#define MDFLD_VCO_SEL (1 << 16)
-#define DPLLA_MODE_LVDS (2 << 26) /* mrst */
-#define MDFLD_PLL_LATCHEN (1 << 28)
-#define MDFLD_PWR_GATE_EN (1 << 30)
-#define MDFLD_P1_MASK (0x1FF << 17)
-#define MRST_FPA0 0x0f040
-#define MRST_FPA1 0x0f044
-#define MDFLD_DPLL_DIV0 0x0f048
-#define MDFLD_DPLL_DIV1 0x0f04c
-#define MRST_PERF_MODE 0x020f4
-
-/*
- * MEDFIELD HDMI registers
- */
-#define HDMIPHYMISCCTL 0x61134
-#define HDMI_PHY_POWER_DOWN 0x7f
-#define HDMIB_CONTROL 0x61140
-#define HDMIB_PORT_EN (1 << 31)
-#define HDMIB_PIPE_B_SELECT (1 << 30)
-#define HDMIB_NULL_PACKET (1 << 9)
-#define HDMIB_HDCP_PORT (1 << 5)
-
-/* #define LVDS 0x61180 */
-#define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25)
-#define MRST_PANEL_24_DOT_1_FORMAT (1 << 24)
-#define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6)
-
-#define MIPI 0x61190
-#define MIPI_C 0x62190
-#define MIPI_PORT_EN (1 << 31)
-/* Turns on border drawing to allow centered display. */
-#define SEL_FLOPPED_HSTX (1 << 23)
-#define PASS_FROM_SPHY_TO_AFE (1 << 16)
-#define MIPI_BORDER_EN (1 << 15)
-#define MIPIA_3LANE_MIPIC_1LANE 0x1
-#define MIPIA_2LANE_MIPIC_2LANE 0x2
-#define TE_TRIGGER_DSI_PROTOCOL (1 << 2)
-#define TE_TRIGGER_GPIO_PIN (1 << 3)
-#define MIPI_TE_COUNT 0x61194
-
-/* #define PP_CONTROL 0x61204 */
-#define POWER_DOWN_ON_RESET (1 << 1)
-
-/* #define PFIT_CONTROL 0x61230 */
-#define PFIT_PIPE_SELECT (3 << 29)
-#define PFIT_PIPE_SELECT_SHIFT (29)
-
-/* #define BLC_PWM_CTL 0x61254 */
-#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16)
-#define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16)
-
-/* #define PIPEACONF 0x70008 */
-#define PIPEACONF_PIPE_STATE (1 << 30)
-/* #define DSPACNTR 0x70180 */
-
-#define MRST_DSPABASE 0x7019c
-#define MRST_DSPBBASE 0x7119c
-#define MDFLD_DSPCBASE 0x7219c
-
-/*
- * Moorestown registers.
- */
-
-/*
- * MIPI IP registers
- */
-#define MIPIC_REG_OFFSET 0x800
-
-#define DEVICE_READY_REG 0xb000
-#define LP_OUTPUT_HOLD (1 << 16)
-#define EXIT_ULPS_DEV_READY 0x3
-#define LP_OUTPUT_HOLD_RELEASE 0x810000
-# define ENTERING_ULPS (2 << 1)
-# define EXITING_ULPS (1 << 1)
-# define ULPS_MASK (3 << 1)
-# define BUS_POSSESSION (1 << 3)
-#define INTR_STAT_REG 0xb004
-#define RX_SOT_ERROR (1 << 0)
-#define RX_SOT_SYNC_ERROR (1 << 1)
-#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3)
-#define RX_LP_TX_SYNC_ERROR (1 << 4)
-#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5)
-#define RX_FALSE_CONTROL_ERROR (1 << 6)
-#define RX_ECC_SINGLE_BIT_ERROR (1 << 7)
-#define RX_ECC_MULTI_BIT_ERROR (1 << 8)
-#define RX_CHECKSUM_ERROR (1 << 9)
-#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10)
-#define RX_DSI_VC_ID_INVALID (1 << 11)
-#define TX_FALSE_CONTROL_ERROR (1 << 12)
-#define TX_ECC_SINGLE_BIT_ERROR (1 << 13)
-#define TX_ECC_MULTI_BIT_ERROR (1 << 14)
-#define TX_CHECKSUM_ERROR (1 << 15)
-#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16)
-#define TX_DSI_VC_ID_INVALID (1 << 17)
-#define HIGH_CONTENTION (1 << 18)
-#define LOW_CONTENTION (1 << 19)
-#define DPI_FIFO_UNDER_RUN (1 << 20)
-#define HS_TX_TIMEOUT (1 << 21)
-#define LP_RX_TIMEOUT (1 << 22)
-#define TURN_AROUND_ACK_TIMEOUT (1 << 23)
-#define ACK_WITH_NO_ERROR (1 << 24)
-#define HS_GENERIC_WR_FIFO_FULL (1 << 27)
-#define LP_GENERIC_WR_FIFO_FULL (1 << 28)
-#define SPL_PKT_SENT (1 << 30)
-#define INTR_EN_REG 0xb008
-#define DSI_FUNC_PRG_REG 0xb00c
-#define DPI_CHANNEL_NUMBER_POS 0x03
-#define DBI_CHANNEL_NUMBER_POS 0x05
-#define FMT_DPI_POS 0x07
-#define FMT_DBI_POS 0x0A
-#define DBI_DATA_WIDTH_POS 0x0D
-
-/* DPI PIXEL FORMATS */
-#define RGB_565_FMT 0x01 /* RGB 565 FORMAT */
-#define RGB_666_FMT 0x02 /* RGB 666 FORMAT */
-#define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED
- * 666 FORMAT
- */
-#define RGB_888_FMT 0x04 /* RGB 888 FORMAT */
-#define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */
-#define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */
-#define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */
-#define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */
-
-#define DBI_NOT_SUPPORTED 0x00 /* command mode
- * is not supported
- */
-#define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */
-#define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */
-#define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */
-#define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */
-#define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */
-
-#define HS_TX_TIMEOUT_REG 0xb010
-#define LP_RX_TIMEOUT_REG 0xb014
-#define TURN_AROUND_TIMEOUT_REG 0xb018
-#define DEVICE_RESET_REG 0xb01C
-#define DPI_RESOLUTION_REG 0xb020
-#define RES_V_POS 0x10
-#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */
-#define HORIZ_SYNC_PAD_COUNT_REG 0xb028
-#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C
-#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030
-#define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034
-#define VERT_SYNC_PAD_COUNT_REG 0xb038
-#define VERT_BACK_PORCH_COUNT_REG 0xb03c
-#define VERT_FRONT_PORCH_COUNT_REG 0xb040
-#define HIGH_LOW_SWITCH_COUNT_REG 0xb044
-#define DPI_CONTROL_REG 0xb048
-#define DPI_SHUT_DOWN (1 << 0)
-#define DPI_TURN_ON (1 << 1)
-#define DPI_COLOR_MODE_ON (1 << 2)
-#define DPI_COLOR_MODE_OFF (1 << 3)
-#define DPI_BACK_LIGHT_ON (1 << 4)
-#define DPI_BACK_LIGHT_OFF (1 << 5)
-#define DPI_LP (1 << 6)
-#define DPI_DATA_REG 0xb04c
-#define DPI_BACK_LIGHT_ON_DATA 0x07
-#define DPI_BACK_LIGHT_OFF_DATA 0x17
-#define INIT_COUNT_REG 0xb050
-#define MAX_RET_PAK_REG 0xb054
-#define VIDEO_FMT_REG 0xb058
-#define COMPLETE_LAST_PCKT (1 << 2)
-#define EOT_DISABLE_REG 0xb05c
-#define ENABLE_CLOCK_STOPPING (1 << 1)
-#define LP_BYTECLK_REG 0xb060
-#define LP_GEN_DATA_REG 0xb064
-#define HS_GEN_DATA_REG 0xb068
-#define LP_GEN_CTRL_REG 0xb06C
-#define HS_GEN_CTRL_REG 0xb070
-#define DCS_CHANNEL_NUMBER_POS 0x6
-#define MCS_COMMANDS_POS 0x8
-#define WORD_COUNTS_POS 0x8
-#define MCS_PARAMETER_POS 0x10
-#define GEN_FIFO_STAT_REG 0xb074
-#define HS_DATA_FIFO_FULL (1 << 0)
-#define HS_DATA_FIFO_HALF_EMPTY (1 << 1)
-#define HS_DATA_FIFO_EMPTY (1 << 2)
-#define LP_DATA_FIFO_FULL (1 << 8)
-#define LP_DATA_FIFO_HALF_EMPTY (1 << 9)
-#define LP_DATA_FIFO_EMPTY (1 << 10)
-#define HS_CTRL_FIFO_FULL (1 << 16)
-#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17)
-#define HS_CTRL_FIFO_EMPTY (1 << 18)
-#define LP_CTRL_FIFO_FULL (1 << 24)
-#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25)
-#define LP_CTRL_FIFO_EMPTY (1 << 26)
-#define DBI_FIFO_EMPTY (1 << 27)
-#define DPI_FIFO_EMPTY (1 << 28)
-#define HS_LS_DBI_ENABLE_REG 0xb078
-#define TXCLKESC_REG 0xb07c
-#define DPHY_PARAM_REG 0xb080
-#define DBI_BW_CTRL_REG 0xb084
-#define CLK_LANE_SWT_REG 0xb088
-
-/*
- * MIPI Adapter registers
- */
-#define MIPI_CONTROL_REG 0xb104
-#define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1))
-#define MIPI_DATA_ADDRESS_REG 0xb108
-#define MIPI_DATA_LENGTH_REG 0xb10C
-#define MIPI_COMMAND_ADDRESS_REG 0xb110
-#define MIPI_COMMAND_LENGTH_REG 0xb114
-#define MIPI_READ_DATA_RETURN_REG0 0xb118
-#define MIPI_READ_DATA_RETURN_REG1 0xb11C
-#define MIPI_READ_DATA_RETURN_REG2 0xb120
-#define MIPI_READ_DATA_RETURN_REG3 0xb124
-#define MIPI_READ_DATA_RETURN_REG4 0xb128
-#define MIPI_READ_DATA_RETURN_REG5 0xb12C
-#define MIPI_READ_DATA_RETURN_REG6 0xb130
-#define MIPI_READ_DATA_RETURN_REG7 0xb134
-#define MIPI_READ_DATA_VALID_REG 0xb138
-
-/* DBI COMMANDS */
-#define soft_reset 0x01
-/*
- * The display module performs a software reset.
- * Registers are written with their SW Reset default values.
- */
-#define get_power_mode 0x0a
-/*
- * The display module returns the current power mode
- */
-#define get_address_mode 0x0b
-/*
- * The display module returns the current status.
- */
-#define get_pixel_format 0x0c
-/*
- * This command gets the pixel format for the RGB image data
- * used by the interface.
- */
-#define get_display_mode 0x0d
-/*
- * The display module returns the Display Image Mode status.
- */
-#define get_signal_mode 0x0e
-/*
- * The display module returns the Display Signal Mode.
- */
-#define get_diagnostic_result 0x0f
-/*
- * The display module returns the self-diagnostic results following
- * a Sleep Out command.
- */
-#define enter_sleep_mode 0x10
-/*
- * This command causes the display module to enter the Sleep mode.
- * In this mode, all unnecessary blocks inside the display module are
- * disabled except interface communication. This is the lowest power
- * mode the display module supports.
- */
-#define exit_sleep_mode 0x11
-/*
- * This command causes the display module to exit Sleep mode.
- * All blocks inside the display module are enabled.
- */
-#define enter_partial_mode 0x12
-/*
- * This command causes the display module to enter the Partial Display
- * Mode. The Partial Display Mode window is described by the
- * set_partial_area command.
- */
-#define enter_normal_mode 0x13
-/*
- * This command causes the display module to enter the Normal mode.
- * Normal Mode is defined as Partial Display mode and Scroll mode are off
- */
-#define exit_invert_mode 0x20
-/*
- * This command causes the display module to stop inverting the image
- * data on the display device. The frame memory contents remain unchanged.
- * No status bits are changed.
- */
-#define enter_invert_mode 0x21
-/*
- * This command causes the display module to invert the image data only on
- * the display device. The frame memory contents remain unchanged.
- * No status bits are changed.
- */
-#define set_gamma_curve 0x26
-/*
- * This command selects the desired gamma curve for the display device.
- * Four fixed gamma curves are defined in section DCS spec.
- */
-#define set_display_off 0x28
-/* ************************************************************************* *\
-This command causes the display module to stop displaying the image data
-on the display device. The frame memory contents remain unchanged.
-No status bits are changed.
-\* ************************************************************************* */
-#define set_display_on 0x29
-/* ************************************************************************* *\
-This command causes the display module to start displaying the image data
-on the display device. The frame memory contents remain unchanged.
-No status bits are changed.
-\* ************************************************************************* */
-#define set_column_address 0x2a
-/*
- * This command defines the column extent of the frame memory accessed by
- * the hostprocessor with the read_memory_continue and
- * write_memory_continue commands.
- * No status bits are changed.
- */
-#define set_page_addr 0x2b
-/*
- * This command defines the page extent of the frame memory accessed by
- * the host processor with the write_memory_continue and
- * read_memory_continue command.
- * No status bits are changed.
- */
-#define write_mem_start 0x2c
-/*
- * This command transfers image data from the host processor to the
- * display modules frame memory starting at the pixel location specified
- * by preceding set_column_address and set_page_address commands.
- */
-#define set_partial_area 0x30
-/*
- * This command defines the Partial Display mode s display area.
- * There are two parameters associated with this command, the first
- * defines the Start Row (SR) and the second the End Row (ER). SR and ER
- * refer to the Frame Memory Line Pointer.
- */
-#define set_scroll_area 0x33
-/*
- * This command defines the display modules Vertical Scrolling Area.
- */
-#define set_tear_off 0x34
-/*
- * This command turns off the display modules Tearing Effect output
- * signal on the TE signal line.
- */
-#define set_tear_on 0x35
-/*
- * This command turns on the display modules Tearing Effect output signal
- * on the TE signal line.
- */
-#define set_address_mode 0x36
-/*
- * This command sets the data order for transfers from the host processor
- * to display modules frame memory,bits B[7:5] and B3, and from the
- * display modules frame memory to the display device, bits B[2:0] and B4.
- */
-#define set_scroll_start 0x37
-/*
- * This command sets the start of the vertical scrolling area in the frame
- * memory. The vertical scrolling area is fully defined when this command
- * is used with the set_scroll_area command The set_scroll_start command
- * has one parameter, the Vertical Scroll Pointer. The VSP defines the
- * line in the frame memory that is written to the display device as the
- * first line of the vertical scroll area.
- */
-#define exit_idle_mode 0x38
-/*
- * This command causes the display module to exit Idle mode.
- */
-#define enter_idle_mode 0x39
-/*
- * This command causes the display module to enter Idle Mode.
- * In Idle Mode, color expression is reduced. Colors are shown on the
- * display device using the MSB of each of the R, G and B color
- * components in the frame memory
- */
-#define set_pixel_format 0x3a
-/*
- * This command sets the pixel format for the RGB image data used by the
- * interface.
- * Bits D[6:4] DPI Pixel Format Definition
- * Bits D[2:0] DBI Pixel Format Definition
- * Bits D7 and D3 are not used.
- */
-#define DCS_PIXEL_FORMAT_3bpp 0x1
-#define DCS_PIXEL_FORMAT_8bpp 0x2
-#define DCS_PIXEL_FORMAT_12bpp 0x3
-#define DCS_PIXEL_FORMAT_16bpp 0x5
-#define DCS_PIXEL_FORMAT_18bpp 0x6
-#define DCS_PIXEL_FORMAT_24bpp 0x7
-
-#define write_mem_cont 0x3c
-
-/*
- * This command transfers image data from the host processor to the
- * display module's frame memory continuing from the pixel location
- * following the previous write_memory_continue or write_memory_start
- * command.
- */
-#define set_tear_scanline 0x44
-/*
- * This command turns on the display modules Tearing Effect output signal
- * on the TE signal line when the display module reaches line N.
- */
-#define get_scanline 0x45
-/*
- * The display module returns the current scanline, N, used to update the
- * display device. The total number of scanlines on a display device is
- * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as
- * the first line of V Sync and is denoted as Line 0.
- * When in Sleep Mode, the value returned by get_scanline is undefined.
- */
-
-/* MCS or Generic COMMANDS */
-/* MCS/generic data type */
-#define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */
-#define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */
-#define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */
-#define GEN_READ_0 0x04 /* generic read, no parameters */
-#define GEN_READ_1 0x14 /* generic read, 1 parameters */
-#define GEN_READ_2 0x24 /* generic read, 2 parameters */
-#define GEN_LONG_WRITE 0x29 /* generic long write */
-#define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */
-#define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */
-#define MCS_READ 0x06 /* MCS read, no parameters */
-#define MCS_LONG_WRITE 0x39 /* MCS long write */
-/* MCS/generic commands */
-/* TPO MCS */
-#define write_display_profile 0x50
-#define write_display_brightness 0x51
-#define write_ctrl_display 0x53
-#define write_ctrl_cabc 0x55
- #define UI_IMAGE 0x01
- #define STILL_IMAGE 0x02
- #define MOVING_IMAGE 0x03
-#define write_hysteresis 0x57
-#define write_gamma_setting 0x58
-#define write_cabc_min_bright 0x5e
-#define write_kbbc_profile 0x60
-/* TMD MCS */
-#define tmd_write_display_brightness 0x8c
-
-/*
- * This command is used to control ambient light, panel backlight
- * brightness and gamma settings.
- */
-#define BRIGHT_CNTL_BLOCK_ON (1 << 5)
-#define AMBIENT_LIGHT_SENSE_ON (1 << 4)
-#define DISPLAY_DIMMING_ON (1 << 3)
-#define BACKLIGHT_ON (1 << 2)
-#define DISPLAY_BRIGHTNESS_AUTO (1 << 1)
-#define GAMMA_AUTO (1 << 0)
-
-/* DCS Interface Pixel Formats */
-#define DCS_PIXEL_FORMAT_3BPP 0x1
-#define DCS_PIXEL_FORMAT_8BPP 0x2
-#define DCS_PIXEL_FORMAT_12BPP 0x3
-#define DCS_PIXEL_FORMAT_16BPP 0x5
-#define DCS_PIXEL_FORMAT_18BPP 0x6
-#define DCS_PIXEL_FORMAT_24BPP 0x7
-/* ONE PARAMETER READ DATA */
-#define addr_mode_data 0xfc
-#define diag_res_data 0x00
-#define disp_mode_data 0x23
-#define pxl_fmt_data 0x77
-#define pwr_mode_data 0x74
-#define sig_mode_data 0x00
-/* TWO PARAMETERS READ DATA */
-#define scanline_data1 0xff
-#define scanline_data2 0xff
-#define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode
- * with Sync Pulse
- */
-#define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode
- * with Sync events
- */
-#define BURST_MODE 0x03 /* Burst Mode */
-#define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */
- /* Allocate at least
- * 0x100 Byte with 32
- * byte alignment
- */
-#define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least
- * 0x100 Byte with 32
- * byte alignment
- */
-#define DBI_CB_TIME_OUT 0xFFFF
-
-#define GEN_FB_TIME_OUT 2000
-
-#define SKU_83 0x01
-#define SKU_100 0x02
-#define SKU_100L 0x04
-#define SKU_BYPASS 0x08
-
-/* Some handy macros for playing with bitfields. */
-#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low))
-#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK)
-#define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT)
-
-#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
-
-/* PCI config space */
-
-#define SB_PCKT 0x02100 /* cedarview */
-# define SB_OPCODE_MASK PSB_MASK(31, 16)
-# define SB_OPCODE_SHIFT 16
-# define SB_OPCODE_READ 0
-# define SB_OPCODE_WRITE 1
-# define SB_DEST_MASK PSB_MASK(15, 8)
-# define SB_DEST_SHIFT 8
-# define SB_DEST_DPLL 0x88
-# define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4)
-# define SB_BYTE_ENABLE_SHIFT 4
-# define SB_BUSY (1 << 0)
-
-
-/* 32-bit value read/written from the DPIO reg. */
-#define SB_DATA 0x02104 /* cedarview */
-/* 32-bit address of the DPIO reg to be read/written. */
-#define SB_ADDR 0x02108 /* cedarview */
-#define DPIO_CFG 0x02110 /* cedarview */
-# define DPIO_MODE_SELECT_1 (1 << 3)
-# define DPIO_MODE_SELECT_0 (1 << 2)
-# define DPIO_SFR_BYPASS (1 << 1)
-/* reset is active low */
-# define DPIO_CMN_RESET_N (1 << 0)
-
-/* Cedarview sideband registers */
-#define _SB_M_A 0x8008
-#define _SB_M_B 0x8028
-#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B)
-# define SB_M_DIVIDER_MASK (0xFF << 24)
-# define SB_M_DIVIDER_SHIFT 24
-
-#define _SB_N_VCO_A 0x8014
-#define _SB_N_VCO_B 0x8034
-#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B)
-#define SB_N_VCO_SEL_MASK PSB_MASK(31, 30)
-#define SB_N_VCO_SEL_SHIFT 30
-#define SB_N_DIVIDER_MASK PSB_MASK(29, 26)
-#define SB_N_DIVIDER_SHIFT 26
-#define SB_N_CB_TUNE_MASK PSB_MASK(25, 24)
-#define SB_N_CB_TUNE_SHIFT 24
-
-#define _SB_REF_A 0x8018
-#define _SB_REF_B 0x8038
-#define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B)
-
-#define _SB_P_A 0x801c
-#define _SB_P_B 0x803c
-#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B)
-#define SB_P2_DIVIDER_MASK PSB_MASK(31, 30)
-#define SB_P2_DIVIDER_SHIFT 30
-#define SB_P2_10 0 /* HDMI, DP, DAC */
-#define SB_P2_5 1 /* DAC */
-#define SB_P2_14 2 /* LVDS single */
-#define SB_P2_7 3 /* LVDS double */
-#define SB_P1_DIVIDER_MASK PSB_MASK(15, 12)
-#define SB_P1_DIVIDER_SHIFT 12
-
-#define PSB_LANE0 0x120
-#define PSB_LANE1 0x220
-#define PSB_LANE2 0x2320
-#define PSB_LANE3 0x2420
-
-#define LANE_PLL_MASK (0x7 << 20)
-#define LANE_PLL_ENABLE (0x3 << 20)
-
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
deleted file mode 100644
index a4bad1af4b7c..000000000000
--- a/drivers/staging/gma500/psb_intel_sdvo.c
+++ /dev/null
@@ -1,1293 +0,0 @@
-/*
- * Copyright (c) 2006-2007 Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-/* #include <drm/drm_crtc.h> */
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_sdvo_regs.h"
-
-struct psb_intel_sdvo_priv {
- struct psb_intel_i2c_chan *i2c_bus;
- int slaveaddr;
- int output_device;
-
- u16 active_outputs;
-
- struct psb_intel_sdvo_caps caps;
- int pixel_clock_min, pixel_clock_max;
-
- int save_sdvo_mult;
- u16 save_active_outputs;
- struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
- struct psb_intel_sdvo_dtd save_output_dtd[16];
- u32 save_SDVOX;
- u8 in_out_map[4];
-
- u8 by_input_wiring;
- u32 active_device;
-};
-
-/**
- * Writes the SDVOB or SDVOC with the given value, but always writes both
- * SDVOB and SDVOC to work around apparent hardware issues (according to
- * comments in the BIOS).
- */
-void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output,
- u32 val)
-{
- struct drm_device *dev = psb_intel_output->base.dev;
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- u32 bval = val, cval = val;
- int i;
-
- if (sdvo_priv->output_device == SDVOB)
- cval = REG_READ(SDVOC);
- else
- bval = REG_READ(SDVOB);
- /*
- * Write the registers twice for luck. Sometimes,
- * writing them only once doesn't appear to 'stick'.
- * The BIOS does this too. Yay, magic
- */
- for (i = 0; i < 2; i++) {
- REG_WRITE(SDVOB, bval);
- REG_READ(SDVOB);
- REG_WRITE(SDVOC, cval);
- REG_READ(SDVOC);
- }
-}
-
-static bool psb_intel_sdvo_read_byte(
- struct psb_intel_output *psb_intel_output,
- u8 addr, u8 *ch)
-{
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- u8 out_buf[2];
- u8 buf[2];
- int ret;
-
- struct i2c_msg msgs[] = {
- {
- .addr = sdvo_priv->i2c_bus->slave_addr,
- .flags = 0,
- .len = 1,
- .buf = out_buf,
- },
- {
- .addr = sdvo_priv->i2c_bus->slave_addr,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = buf,
- }
- };
-
- out_buf[0] = addr;
- out_buf[1] = 0;
-
- ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2);
- if (ret == 2) {
- *ch = buf[0];
- return true;
- }
-
- return false;
-}
-
-static bool psb_intel_sdvo_write_byte(
- struct psb_intel_output *psb_intel_output,
- int addr, u8 ch)
-{
- u8 out_buf[2];
- struct i2c_msg msgs[] = {
- {
- .addr = psb_intel_output->i2c_bus->slave_addr,
- .flags = 0,
- .len = 2,
- .buf = out_buf,
- }
- };
-
- out_buf[0] = addr;
- out_buf[1] = ch;
-
- if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1)
- return true;
- return false;
-}
-
-#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
-/** Mapping of command numbers to names, for debug output */
-static const struct _sdvo_cmd_name {
- u8 cmd;
- char *name;
-} sdvo_cmd_names[] = {
-SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
- SDVO_CMD_NAME_ENTRY
- (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),};
-
-#define SDVO_NAME(dev_priv) \
- ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
-#define SDVO_PRIV(output) ((struct psb_intel_sdvo_priv *) (output)->dev_priv)
-
-static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
- u8 cmd,
- void *args,
- int args_len)
-{
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- int i;
-
- if (0) {
- printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
- for (i = 0; i < args_len; i++)
- printk(KERN_CONT "%02X ", ((u8 *) args)[i]);
- for (; i < 8; i++)
- printk(KERN_CONT " ");
- for (i = 0;
- i <
- sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
- i++) {
- if (cmd == sdvo_cmd_names[i].cmd) {
- printk(KERN_CONT
- "(%s)", sdvo_cmd_names[i].name);
- break;
- }
- }
- if (i ==
- sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
- printk(KERN_CONT "(%02X)", cmd);
- printk(KERN_CONT "\n");
- }
-
- for (i = 0; i < args_len; i++) {
- psb_intel_sdvo_write_byte(psb_intel_output,
- SDVO_I2C_ARG_0 - i,
- ((u8 *) args)[i]);
- }
-
- psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd);
-}
-
-static const char *const cmd_status_names[] = {
- "Power on",
- "Success",
- "Not supported",
- "Invalid arg",
- "Pending",
- "Target not specified",
- "Scaling not supported"
-};
-
-static u8 psb_intel_sdvo_read_response(
- struct psb_intel_output *psb_intel_output,
- void *response, int response_len)
-{
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- int i;
- u8 status;
- u8 retry = 50;
-
- while (retry--) {
- /* Read the command response */
- for (i = 0; i < response_len; i++) {
- psb_intel_sdvo_read_byte(psb_intel_output,
- SDVO_I2C_RETURN_0 + i,
- &((u8 *) response)[i]);
- }
-
- /* read the return status */
- psb_intel_sdvo_read_byte(psb_intel_output,
- SDVO_I2C_CMD_STATUS,
- &status);
-
- if (0) {
- pr_debug("%s: R: ", SDVO_NAME(sdvo_priv));
- for (i = 0; i < response_len; i++)
- printk(KERN_CONT "%02X ", ((u8 *) response)[i]);
- for (; i < 8; i++)
- printk(" ");
- if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
- printk(KERN_CONT "(%s)",
- cmd_status_names[status]);
- else
- printk(KERN_CONT "(??? %d)", status);
- printk(KERN_CONT "\n");
- }
-
- if (status != SDVO_CMD_STATUS_PENDING)
- return status;
-
- mdelay(50);
- }
-
- return status;
-}
-
-int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
-{
- if (mode->clock >= 100000)
- return 1;
- else if (mode->clock >= 50000)
- return 2;
- else
- return 4;
-}
-
-/**
- * Don't check status code from this as it switches the bus back to the
- * SDVO chips which defeats the purpose of doing a bus switch in the first
- * place.
- */
-void psb_intel_sdvo_set_control_bus_switch(
- struct psb_intel_output *psb_intel_output,
- u8 target)
-{
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_CONTROL_BUS_SWITCH,
- &target,
- 1);
-}
-
-static bool psb_intel_sdvo_set_target_input(
- struct psb_intel_output *psb_intel_output,
- bool target_0, bool target_1)
-{
- struct psb_intel_sdvo_set_target_input_args targets = { 0 };
- u8 status;
-
- if (target_0 && target_1)
- return SDVO_CMD_STATUS_NOTSUPP;
-
- if (target_1)
- targets.target_1 = 1;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT,
- &targets, sizeof(targets));
-
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-
- return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-/**
- * Return whether each input is trained.
- *
- * This function is making an assumption about the layout of the response,
- * which should be checked against the docs.
- */
-static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output
- *psb_intel_output, bool *input_1,
- bool *input_2)
-{
- struct psb_intel_sdvo_get_trained_inputs_response response;
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS,
- NULL, 0);
- status =
- psb_intel_sdvo_read_response(psb_intel_output, &response,
- sizeof(response));
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- *input_1 = response.input0_trained;
- *input_2 = response.input1_trained;
- return true;
-}
-
-static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output
- *psb_intel_output, u16 *outputs)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS,
- NULL, 0);
- status =
- psb_intel_sdvo_read_response(psb_intel_output, outputs,
- sizeof(*outputs));
-
- return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output
- *psb_intel_output, u16 outputs)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS,
- &outputs, sizeof(outputs));
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
- return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output
- *psb_intel_output, int mode)
-{
- u8 status, state = SDVO_ENCODER_STATE_ON;
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- state = SDVO_ENCODER_STATE_ON;
- break;
- case DRM_MODE_DPMS_STANDBY:
- state = SDVO_ENCODER_STATE_STANDBY;
- break;
- case DRM_MODE_DPMS_SUSPEND:
- state = SDVO_ENCODER_STATE_SUSPEND;
- break;
- case DRM_MODE_DPMS_OFF:
- state = SDVO_ENCODER_STATE_OFF;
- break;
- }
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
- sizeof(state));
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-
- return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output
- *psb_intel_output,
- int *clock_min,
- int *clock_max)
-{
- struct psb_intel_sdvo_pixel_clock_range clocks;
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL,
- 0);
-
- status =
- psb_intel_sdvo_read_response(psb_intel_output, &clocks,
- sizeof(clocks));
-
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- /* Convert the values from units of 10 kHz to kHz. */
- *clock_min = clocks.min * 10;
- *clock_max = clocks.max * 10;
-
- return true;
-}
-
-static bool psb_intel_sdvo_set_target_output(
- struct psb_intel_output *psb_intel_output,
- u16 outputs)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT,
- &outputs, sizeof(outputs));
-
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
- return status == SDVO_CMD_STATUS_SUCCESS;
-}
-
-static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output,
- u8 cmd, struct psb_intel_sdvo_dtd *dtd)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0);
- status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1,
- sizeof(dtd->part1));
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0);
- status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2,
- sizeof(dtd->part2));
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- return true;
-}
-
-static bool psb_intel_sdvo_get_input_timing(
- struct psb_intel_output *psb_intel_output,
- struct psb_intel_sdvo_dtd *dtd)
-{
- return psb_intel_sdvo_get_timing(psb_intel_output,
- SDVO_CMD_GET_INPUT_TIMINGS_PART1,
- dtd);
-}
-
-static bool psb_intel_sdvo_set_timing(
- struct psb_intel_output *psb_intel_output,
- u8 cmd,
- struct psb_intel_sdvo_dtd *dtd)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1,
- sizeof(dtd->part1));
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2,
- sizeof(dtd->part2));
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- return true;
-}
-
-static bool psb_intel_sdvo_set_input_timing(
- struct psb_intel_output *psb_intel_output,
- struct psb_intel_sdvo_dtd *dtd)
-{
- return psb_intel_sdvo_set_timing(psb_intel_output,
- SDVO_CMD_SET_INPUT_TIMINGS_PART1,
- dtd);
-}
-
-static bool psb_intel_sdvo_set_output_timing(
- struct psb_intel_output *psb_intel_output,
- struct psb_intel_sdvo_dtd *dtd)
-{
- return psb_intel_sdvo_set_timing(psb_intel_output,
- SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
- dtd);
-}
-
-static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output
- *psb_intel_output)
-{
- u8 response, status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_CLOCK_RATE_MULT,
- NULL,
- 0);
-
- status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1);
-
- if (status != SDVO_CMD_STATUS_SUCCESS) {
- DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
- return SDVO_CLOCK_RATE_MULT_1X;
- } else {
- DRM_DEBUG("Current clock rate multiplier: %d\n", response);
- }
-
- return response;
-}
-
-static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output
- *psb_intel_output, u8 val)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_CLOCK_RATE_MULT,
- &val,
- 1);
-
- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- return true;
-}
-
-static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output,
- u32 in0outputmask,
- u32 in1outputmask)
-{
- u8 byArgs[4];
- u8 status;
- int i;
- struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
-
- /* Make all fields of the args/ret to zero */
- memset(byArgs, 0, sizeof(byArgs));
-
- /* Fill up the argument values; */
- byArgs[0] = (u8) (in0outputmask & 0xFF);
- byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF);
- byArgs[2] = (u8) (in1outputmask & 0xFF);
- byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF);
-
-
- /*save inoutmap arg here*/
- for (i = 0; i < 4; i++)
- sdvo_priv->in_out_map[i] = byArgs[0];
-
- psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4);
- status = psb_intel_sdvo_read_response(output, NULL, 0);
-
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
- return true;
-}
-
-
-static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output)
-{
- u32 dwCurrentSDVOIn0 = 0;
- u32 dwCurrentSDVOIn1 = 0;
- u32 dwDevMask = 0;
-
-
- struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
-
- /* Please DO NOT change the following code. */
- /* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */
- /* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */
- if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) {
- switch (sdvo_priv->active_device) {
- case SDVO_DEVICE_LVDS:
- dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
- break;
- case SDVO_DEVICE_TMDS:
- dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
- break;
- case SDVO_DEVICE_TV:
- dwDevMask =
- SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
- SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
- SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
- SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
- break;
- case SDVO_DEVICE_CRT:
- dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
- break;
- }
- dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask);
- } else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) {
- switch (sdvo_priv->active_device) {
- case SDVO_DEVICE_LVDS:
- dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
- break;
- case SDVO_DEVICE_TMDS:
- dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
- break;
- case SDVO_DEVICE_TV:
- dwDevMask =
- SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
- SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
- SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
- SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
- break;
- case SDVO_DEVICE_CRT:
- dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
- break;
- }
- dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask);
- }
-
- psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0,
- dwCurrentSDVOIn1);
-}
-
-
-static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO
- * device will be told of the multiplier during mode_set.
- */
- adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode);
- return true;
-}
-
-static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct drm_device *dev = encoder->dev;
- struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_output *psb_intel_output =
- enc_to_psb_intel_output(encoder);
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- u16 width, height;
- u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
- u16 h_sync_offset, v_sync_offset;
- u32 sdvox;
- struct psb_intel_sdvo_dtd output_dtd;
- int sdvo_pixel_multiply;
-
- if (!mode)
- return;
-
- psb_intel_sdvo_set_target_output(psb_intel_output, 0);
-
- width = mode->crtc_hdisplay;
- height = mode->crtc_vdisplay;
-
- /* do some mode translations */
- h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
- h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
-
- v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
- v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
-
- h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
- v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
-
- output_dtd.part1.clock = mode->clock / 10;
- output_dtd.part1.h_active = width & 0xff;
- output_dtd.part1.h_blank = h_blank_len & 0xff;
- output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
- ((h_blank_len >> 8) & 0xf);
- output_dtd.part1.v_active = height & 0xff;
- output_dtd.part1.v_blank = v_blank_len & 0xff;
- output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
- ((v_blank_len >> 8) & 0xf);
-
- output_dtd.part2.h_sync_off = h_sync_offset;
- output_dtd.part2.h_sync_width = h_sync_len & 0xff;
- output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
- (v_sync_len & 0xf);
- output_dtd.part2.sync_off_width_high =
- ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) |
- ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4);
-
- output_dtd.part2.dtd_flags = 0x18;
- if (mode->flags & DRM_MODE_FLAG_PHSYNC)
- output_dtd.part2.dtd_flags |= 0x2;
- if (mode->flags & DRM_MODE_FLAG_PVSYNC)
- output_dtd.part2.dtd_flags |= 0x4;
-
- output_dtd.part2.sdvo_flags = 0;
- output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
- output_dtd.part2.reserved = 0;
-
- /* Set the output timing to the screen */
- psb_intel_sdvo_set_target_output(psb_intel_output,
- sdvo_priv->active_outputs);
-
- /* Set the input timing to the screen. Assume always input 0. */
- psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
-
- psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd);
-
- /* We would like to use i830_sdvo_create_preferred_input_timing() to
- * provide the device with a timing it can support, if it supports that
- * feature. However, presumably we would need to adjust the CRTC to
- * output the preferred timing, and we don't support that currently.
- */
- psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd);
-
- switch (psb_intel_sdvo_get_pixel_multiplier(mode)) {
- case 1:
- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
- SDVO_CLOCK_RATE_MULT_1X);
- break;
- case 2:
- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
- SDVO_CLOCK_RATE_MULT_2X);
- break;
- case 4:
- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
- SDVO_CLOCK_RATE_MULT_4X);
- break;
- }
-
- /* Set the SDVO control regs. */
- sdvox = REG_READ(sdvo_priv->output_device);
- switch (sdvo_priv->output_device) {
- case SDVOB:
- sdvox &= SDVOB_PRESERVE_MASK;
- break;
- case SDVOC:
- sdvox &= SDVOC_PRESERVE_MASK;
- break;
- }
- sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
- if (psb_intel_crtc->pipe == 1)
- sdvox |= SDVO_PIPE_B_SELECT;
-
- sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode);
-
- psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox);
-
- psb_intel_sdvo_set_iomap(psb_intel_output);
-}
-
-static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct psb_intel_output *psb_intel_output =
- enc_to_psb_intel_output(encoder);
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- u32 temp;
-
- if (mode != DRM_MODE_DPMS_ON) {
- psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
- if (0)
- psb_intel_sdvo_set_encoder_power_state(
- psb_intel_output,
- mode);
-
- if (mode == DRM_MODE_DPMS_OFF) {
- temp = REG_READ(sdvo_priv->output_device);
- if ((temp & SDVO_ENABLE) != 0) {
- psb_intel_sdvo_write_sdvox(psb_intel_output,
- temp &
- ~SDVO_ENABLE);
- }
- }
- } else {
- bool input1, input2;
- int i;
- u8 status;
-
- temp = REG_READ(sdvo_priv->output_device);
- if ((temp & SDVO_ENABLE) == 0)
- psb_intel_sdvo_write_sdvox(psb_intel_output,
- temp | SDVO_ENABLE);
- for (i = 0; i < 2; i++)
- psb_intel_wait_for_vblank(dev);
-
- status =
- psb_intel_sdvo_get_trained_inputs(psb_intel_output,
- &input1,
- &input2);
-
-
- /* Warn if the device reported failure to sync.
- * A lot of SDVO devices fail to notify of sync, but it's
- * a given it the status is a success, we succeeded.
- */
- if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
- DRM_DEBUG
- ("First %s output reported failure to sync\n",
- SDVO_NAME(sdvo_priv));
- }
-
- if (0)
- psb_intel_sdvo_set_encoder_power_state(
- psb_intel_output,
- mode);
- psb_intel_sdvo_set_active_outputs(psb_intel_output,
- sdvo_priv->active_outputs);
- }
- return;
-}
-
-static void psb_intel_sdvo_save(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- /*int o;*/
-
- sdvo_priv->save_sdvo_mult =
- psb_intel_sdvo_get_clock_rate_mult(psb_intel_output);
- psb_intel_sdvo_get_active_outputs(psb_intel_output,
- &sdvo_priv->save_active_outputs);
-
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
- psb_intel_sdvo_set_target_input(psb_intel_output,
- true,
- false);
- psb_intel_sdvo_get_input_timing(psb_intel_output,
- &sdvo_priv->save_input_dtd_1);
- }
-
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
- psb_intel_sdvo_set_target_input(psb_intel_output,
- false,
- true);
- psb_intel_sdvo_get_input_timing(psb_intel_output,
- &sdvo_priv->save_input_dtd_2);
- }
- sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device);
-
- /*TODO: save the in_out_map state*/
-}
-
-static void psb_intel_sdvo_restore(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
- /*int o;*/
- int i;
- bool input1, input2;
- u8 status;
-
- psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
-
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
- psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
- psb_intel_sdvo_set_input_timing(psb_intel_output,
- &sdvo_priv->save_input_dtd_1);
- }
-
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
- psb_intel_sdvo_set_target_input(psb_intel_output, false, true);
- psb_intel_sdvo_set_input_timing(psb_intel_output,
- &sdvo_priv->save_input_dtd_2);
- }
-
- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
- sdvo_priv->save_sdvo_mult);
-
- REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX);
-
- if (sdvo_priv->save_SDVOX & SDVO_ENABLE) {
- for (i = 0; i < 2; i++)
- psb_intel_wait_for_vblank(dev);
- status =
- psb_intel_sdvo_get_trained_inputs(psb_intel_output,
- &input1,
- &input2);
- if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
- DRM_DEBUG
- ("First %s output reported failure to sync\n",
- SDVO_NAME(sdvo_priv));
- }
-
- psb_intel_sdvo_set_active_outputs(psb_intel_output,
- sdvo_priv->save_active_outputs);
-
- /*TODO: restore in_out_map*/
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_IN_OUT_MAP,
- sdvo_priv->in_out_map,
- 4);
-
- psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
-}
-
-static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
-
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- if (sdvo_priv->pixel_clock_min > mode->clock)
- return MODE_CLOCK_LOW;
-
- if (sdvo_priv->pixel_clock_max < mode->clock)
- return MODE_CLOCK_HIGH;
-
- return MODE_OK;
-}
-
-static bool psb_intel_sdvo_get_capabilities(
- struct psb_intel_output *psb_intel_output,
- struct psb_intel_sdvo_caps *caps)
-{
- u8 status;
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_DEVICE_CAPS,
- NULL,
- 0);
- status = psb_intel_sdvo_read_response(psb_intel_output,
- caps,
- sizeof(*caps));
- if (status != SDVO_CMD_STATUS_SUCCESS)
- return false;
-
- return true;
-}
-
-struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB)
-{
- struct drm_connector *connector = NULL;
- struct psb_intel_output *iout = NULL;
- struct psb_intel_sdvo_priv *sdvo;
-
- /* find the sdvo connector */
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- iout = to_psb_intel_output(connector);
-
- if (iout->type != INTEL_OUTPUT_SDVO)
- continue;
-
- sdvo = iout->dev_priv;
-
- if (sdvo->output_device == SDVOB && sdvoB)
- return connector;
-
- if (sdvo->output_device == SDVOC && !sdvoB)
- return connector;
-
- }
-
- return NULL;
-}
-
-int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
-{
- u8 response[2];
- u8 status;
- struct psb_intel_output *psb_intel_output;
-
- if (!connector)
- return 0;
-
- psb_intel_output = to_psb_intel_output(connector);
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_HOT_PLUG_SUPPORT,
- NULL,
- 0);
- status = psb_intel_sdvo_read_response(psb_intel_output,
- &response,
- 2);
-
- if (response[0] != 0)
- return 1;
-
- return 0;
-}
-
-void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
-{
- u8 response[2];
- u8 status;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_ACTIVE_HOT_PLUG,
- NULL,
- 0);
- psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-
- if (on) {
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL,
- 0);
- status = psb_intel_sdvo_read_response(psb_intel_output,
- &response,
- 2);
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_ACTIVE_HOT_PLUG,
- &response, 2);
- } else {
- response[0] = 0;
- response[1] = 0;
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_SET_ACTIVE_HOT_PLUG,
- &response, 2);
- }
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_ACTIVE_HOT_PLUG,
- NULL,
- 0);
- psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-}
-
-static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector
- *connector, bool force)
-{
- u8 response[2];
- u8 status;
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- psb_intel_sdvo_write_cmd(psb_intel_output,
- SDVO_CMD_GET_ATTACHED_DISPLAYS,
- NULL,
- 0);
- status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
-
- DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
- if ((response[0] != 0) || (response[1] != 0))
- return connector_status_connected;
- else
- return connector_status_disconnected;
-}
-
-static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- /* set the bus switch and get the modes */
- psb_intel_sdvo_set_control_bus_switch(psb_intel_output,
- SDVO_CONTROL_BUS_DDC2);
- psb_intel_ddc_get_modes(psb_intel_output);
-
- if (list_empty(&connector->probed_modes))
- return 0;
- return 1;
-}
-
-static void psb_intel_sdvo_destroy(struct drm_connector *connector)
-{
- struct psb_intel_output *psb_intel_output =
- to_psb_intel_output(connector);
-
- if (psb_intel_output->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(psb_intel_output);
-}
-
-static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
- .dpms = psb_intel_sdvo_dpms,
- .mode_fixup = psb_intel_sdvo_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
- .mode_set = psb_intel_sdvo_mode_set,
- .commit = psb_intel_encoder_commit,
-};
-
-static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .save = psb_intel_sdvo_save,
- .restore = psb_intel_sdvo_restore,
- .detect = psb_intel_sdvo_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = psb_intel_sdvo_destroy,
-};
-
-static const struct drm_connector_helper_funcs
- psb_intel_sdvo_connector_helper_funcs = {
- .get_modes = psb_intel_sdvo_get_modes,
- .mode_valid = psb_intel_sdvo_mode_valid,
- .best_encoder = psb_intel_best_encoder,
-};
-
-void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = {
- .destroy = psb_intel_sdvo_enc_destroy,
-};
-
-
-void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
-{
- struct drm_connector *connector;
- struct psb_intel_output *psb_intel_output;
- struct psb_intel_sdvo_priv *sdvo_priv;
- struct psb_intel_i2c_chan *i2cbus = NULL;
- int connector_type;
- u8 ch[0x40];
- int i;
- int encoder_type, output_id;
-
- psb_intel_output =
- kcalloc(sizeof(struct psb_intel_output) +
- sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL);
- if (!psb_intel_output)
- return;
-
- connector = &psb_intel_output->base;
-
- drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs,
- DRM_MODE_CONNECTOR_Unknown);
- drm_connector_helper_add(connector,
- &psb_intel_sdvo_connector_helper_funcs);
- sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1);
- psb_intel_output->type = INTEL_OUTPUT_SDVO;
-
- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
-
- /* setup the DDC bus. */
- if (output_device == SDVOB)
- i2cbus =
- psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
- else
- i2cbus =
- psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
-
- if (!i2cbus)
- goto err_connector;
-
- sdvo_priv->i2c_bus = i2cbus;
-
- if (output_device == SDVOB) {
- output_id = 1;
- sdvo_priv->by_input_wiring = SDVOB_IN0;
- sdvo_priv->i2c_bus->slave_addr = 0x38;
- } else {
- output_id = 2;
- sdvo_priv->i2c_bus->slave_addr = 0x39;
- }
-
- sdvo_priv->output_device = output_device;
- psb_intel_output->i2c_bus = i2cbus;
- psb_intel_output->dev_priv = sdvo_priv;
-
-
- /* Read the regs to test if we can talk to the device */
- for (i = 0; i < 0x40; i++) {
- if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) {
- dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n",
- output_device == SDVOB ? 'B' : 'C');
- goto err_i2c;
- }
- }
-
- psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps);
-
- memset(&sdvo_priv->active_outputs, 0,
- sizeof(sdvo_priv->active_outputs));
-
- /* TODO, CVBS, SVID, YPRPB & SCART outputs. */
- if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) {
- sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
- sdvo_priv->active_device = SDVO_DEVICE_CRT;
- connector->display_info.subpixel_order =
- SubPixelHorizontalRGB;
- encoder_type = DRM_MODE_ENCODER_DAC;
- connector_type = DRM_MODE_CONNECTOR_VGA;
- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) {
- sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
- sdvo_priv->active_outputs = SDVO_DEVICE_CRT;
- connector->display_info.subpixel_order =
- SubPixelHorizontalRGB;
- encoder_type = DRM_MODE_ENCODER_DAC;
- connector_type = DRM_MODE_CONNECTOR_VGA;
- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) {
- sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
- sdvo_priv->active_device = SDVO_DEVICE_TMDS;
- connector->display_info.subpixel_order =
- SubPixelHorizontalRGB;
- encoder_type = DRM_MODE_ENCODER_TMDS;
- connector_type = DRM_MODE_CONNECTOR_DVID;
- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) {
- sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
- sdvo_priv->active_device = SDVO_DEVICE_TMDS;
- connector->display_info.subpixel_order =
- SubPixelHorizontalRGB;
- encoder_type = DRM_MODE_ENCODER_TMDS;
- connector_type = DRM_MODE_CONNECTOR_DVID;
- } else {
- unsigned char bytes[2];
-
- memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
- dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
- SDVO_NAME(sdvo_priv), bytes[0], bytes[1]);
- goto err_i2c;
- }
-
- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs,
- encoder_type);
- drm_encoder_helper_add(&psb_intel_output->enc,
- &psb_intel_sdvo_helper_funcs);
- connector->connector_type = connector_type;
-
- drm_mode_connector_attach_encoder(&psb_intel_output->base,
- &psb_intel_output->enc);
- drm_sysfs_connector_add(connector);
-
- /* Set the input timing to the screen. Assume always input 0. */
- psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
-
- psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output,
- &sdvo_priv->pixel_clock_min,
- &sdvo_priv->
- pixel_clock_max);
-
-
- dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, "
- "clock range %dMHz - %dMHz, "
- "input 1: %c, input 2: %c, "
- "output 1: %c, output 2: %c\n",
- SDVO_NAME(sdvo_priv),
- sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
- sdvo_priv->caps.device_rev_id,
- sdvo_priv->pixel_clock_min / 1000,
- sdvo_priv->pixel_clock_max / 1000,
- (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
- (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
- /* check currently supported outputs */
- sdvo_priv->caps.output_flags &
- (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
- sdvo_priv->caps.output_flags &
- (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
-
- psb_intel_output->ddc_bus = i2cbus;
-
- return;
-
-err_i2c:
- psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
-err_connector:
- drm_connector_cleanup(connector);
- kfree(psb_intel_output);
-
- return;
-}
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h
deleted file mode 100644
index 96862ea65aba..000000000000
--- a/drivers/staging/gma500/psb_intel_sdvo_regs.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * SDVO command definitions and structures.
- *
- * Copyright (c) 2008, Intel Corporation
- *
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#define SDVO_OUTPUT_FIRST (0)
-#define SDVO_OUTPUT_TMDS0 (1 << 0)
-#define SDVO_OUTPUT_RGB0 (1 << 1)
-#define SDVO_OUTPUT_CVBS0 (1 << 2)
-#define SDVO_OUTPUT_SVID0 (1 << 3)
-#define SDVO_OUTPUT_YPRPB0 (1 << 4)
-#define SDVO_OUTPUT_SCART0 (1 << 5)
-#define SDVO_OUTPUT_LVDS0 (1 << 6)
-#define SDVO_OUTPUT_TMDS1 (1 << 8)
-#define SDVO_OUTPUT_RGB1 (1 << 9)
-#define SDVO_OUTPUT_CVBS1 (1 << 10)
-#define SDVO_OUTPUT_SVID1 (1 << 11)
-#define SDVO_OUTPUT_YPRPB1 (1 << 12)
-#define SDVO_OUTPUT_SCART1 (1 << 13)
-#define SDVO_OUTPUT_LVDS1 (1 << 14)
-#define SDVO_OUTPUT_LAST (14)
-
-struct psb_intel_sdvo_caps {
- u8 vendor_id;
- u8 device_id;
- u8 device_rev_id;
- u8 sdvo_version_major;
- u8 sdvo_version_minor;
- unsigned int sdvo_inputs_mask:2;
- unsigned int smooth_scaling:1;
- unsigned int sharp_scaling:1;
- unsigned int up_scaling:1;
- unsigned int down_scaling:1;
- unsigned int stall_support:1;
- unsigned int pad:1;
- u16 output_flags;
-} __packed;
-
-/** This matches the EDID DTD structure, more or less */
-struct psb_intel_sdvo_dtd {
- struct {
- u16 clock; /**< pixel clock, in 10kHz units */
- u8 h_active; /**< lower 8 bits (pixels) */
- u8 h_blank; /**< lower 8 bits (pixels) */
- u8 h_high; /**< upper 4 bits each h_active, h_blank */
- u8 v_active; /**< lower 8 bits (lines) */
- u8 v_blank; /**< lower 8 bits (lines) */
- u8 v_high; /**< upper 4 bits each v_active, v_blank */
- } part1;
-
- struct {
- u8 h_sync_off;
- /**< lower 8 bits, from hblank start */
- u8 h_sync_width;/**< lower 8 bits (pixels) */
- /** lower 4 bits each vsync offset, vsync width */
- u8 v_sync_off_width;
- /**
- * 2 high bits of hsync offset, 2 high bits of hsync width,
- * bits 4-5 of vsync offset, and 2 high bits of vsync width.
- */
- u8 sync_off_width_high;
- u8 dtd_flags;
- u8 sdvo_flags;
- /** bits 6-7 of vsync offset at bits 6-7 */
- u8 v_sync_off_high;
- u8 reserved;
- } part2;
-} __packed;
-
-struct psb_intel_sdvo_pixel_clock_range {
- u16 min; /**< pixel clock, in 10kHz units */
- u16 max; /**< pixel clock, in 10kHz units */
-} __packed;
-
-struct psb_intel_sdvo_preferred_input_timing_args {
- u16 clock;
- u16 width;
- u16 height;
-} __packed;
-
-/* I2C registers for SDVO */
-#define SDVO_I2C_ARG_0 0x07
-#define SDVO_I2C_ARG_1 0x06
-#define SDVO_I2C_ARG_2 0x05
-#define SDVO_I2C_ARG_3 0x04
-#define SDVO_I2C_ARG_4 0x03
-#define SDVO_I2C_ARG_5 0x02
-#define SDVO_I2C_ARG_6 0x01
-#define SDVO_I2C_ARG_7 0x00
-#define SDVO_I2C_OPCODE 0x08
-#define SDVO_I2C_CMD_STATUS 0x09
-#define SDVO_I2C_RETURN_0 0x0a
-#define SDVO_I2C_RETURN_1 0x0b
-#define SDVO_I2C_RETURN_2 0x0c
-#define SDVO_I2C_RETURN_3 0x0d
-#define SDVO_I2C_RETURN_4 0x0e
-#define SDVO_I2C_RETURN_5 0x0f
-#define SDVO_I2C_RETURN_6 0x10
-#define SDVO_I2C_RETURN_7 0x11
-#define SDVO_I2C_VENDOR_BEGIN 0x20
-
-/* Status results */
-#define SDVO_CMD_STATUS_POWER_ON 0x0
-#define SDVO_CMD_STATUS_SUCCESS 0x1
-#define SDVO_CMD_STATUS_NOTSUPP 0x2
-#define SDVO_CMD_STATUS_INVALID_ARG 0x3
-#define SDVO_CMD_STATUS_PENDING 0x4
-#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5
-#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
-
-/* SDVO commands, argument/result registers */
-
-#define SDVO_CMD_RESET 0x01
-
-/** Returns a struct psb_intel_sdvo_caps */
-#define SDVO_CMD_GET_DEVICE_CAPS 0x02
-
-#define SDVO_CMD_GET_FIRMWARE_REV 0x86
-# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
-# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
-# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2
-
-/**
- * Reports which inputs are trained (managed to sync).
- *
- * Devices must have trained within 2 vsyncs of a mode change.
- */
-#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
-struct psb_intel_sdvo_get_trained_inputs_response {
- unsigned int input0_trained:1;
- unsigned int input1_trained:1;
- unsigned int pad:6;
-} __packed;
-
-/** Returns a struct psb_intel_sdvo_output_flags of active outputs. */
-#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
-
-/**
- * Sets the current set of active outputs.
- *
- * Takes a struct psb_intel_sdvo_output_flags.
- * Must be preceded by a SET_IN_OUT_MAP
- * on multi-output devices.
- */
-#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
-
-/**
- * Returns the current mapping of SDVO inputs to outputs on the device.
- *
- * Returns two struct psb_intel_sdvo_output_flags structures.
- */
-#define SDVO_CMD_GET_IN_OUT_MAP 0x06
-
-/**
- * Sets the current mapping of SDVO inputs to outputs on the device.
- *
- * Takes two struct i380_sdvo_output_flags structures.
- */
-#define SDVO_CMD_SET_IN_OUT_MAP 0x07
-
-/**
- * Returns a struct psb_intel_sdvo_output_flags of attached displays.
- */
-#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
-
-/**
- * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging.
- */
-#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
-
-/**
- * Takes a struct psb_intel_sdvo_output_flags.
- */
-#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
-
-/**
- * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug
- * interrupts enabled.
- */
-#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
-
-#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
-struct psb_intel_sdvo_get_interrupt_event_source_response {
- u16 interrupt_status;
- unsigned int ambient_light_interrupt:1;
- unsigned int pad:7;
-} __packed;
-
-/**
- * Selects which input is affected by future input commands.
- *
- * Commands affected include SET_INPUT_TIMINGS_PART[12],
- * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
- * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
- */
-#define SDVO_CMD_SET_TARGET_INPUT 0x10
-struct psb_intel_sdvo_set_target_input_args {
- unsigned int target_1:1;
- unsigned int pad:7;
-} __packed;
-
-/**
- * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by
- * future output commands.
- *
- * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
- * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
- */
-#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
-
-#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
-#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
-#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
-#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
-/* Part 1 */
-# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
-# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
-# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
-# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
-# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
-# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
-# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
-# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
-/* Part 2 */
-# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
-# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
-# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
-# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
-# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
-# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
-# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
-# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
-# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
-# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
-# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
-# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6)
-# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6)
-# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4)
-# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4)
-# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
-
-/**
- * Generates a DTD based on the given width, height, and flags.
- *
- * This will be supported by any device supporting scaling or interlaced
- * modes.
- */
-#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
-
-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
-
-/** Returns a struct psb_intel_sdvo_pixel_clock_range */
-#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
-/** Returns a struct psb_intel_sdvo_pixel_clock_range */
-#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
-
-/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
-#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
-
-/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
-#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
-/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
-#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
-# define SDVO_CLOCK_RATE_MULT_1X (1 << 0)
-# define SDVO_CLOCK_RATE_MULT_2X (1 << 1)
-# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
-
-#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
-
-#define SDVO_CMD_GET_TV_FORMAT 0x28
-
-#define SDVO_CMD_SET_TV_FORMAT 0x29
-
-#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a
-#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b
-#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c
-# define SDVO_ENCODER_STATE_ON (1 << 0)
-# define SDVO_ENCODER_STATE_STANDBY (1 << 1)
-# define SDVO_ENCODER_STATE_SUSPEND (1 << 2)
-# define SDVO_ENCODER_STATE_OFF (1 << 3)
-
-#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
-
-#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
-# define SDVO_CONTROL_BUS_PROM 0x0
-# define SDVO_CONTROL_BUS_DDC1 0x1
-# define SDVO_CONTROL_BUS_DDC2 0x2
-# define SDVO_CONTROL_BUS_DDC3 0x3
-
-/* SDVO Bus & SDVO Inputs wiring details*/
-/* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/
-/* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/
-/* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/
-/* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/
-#define SDVOB_IN0 0x01
-#define SDVOB_IN1 0x02
-#define SDVOC_IN0 0x04
-#define SDVOC_IN1 0x08
-
-#define SDVO_DEVICE_NONE 0x00
-#define SDVO_DEVICE_CRT 0x01
-#define SDVO_DEVICE_TV 0x02
-#define SDVO_DEVICE_LVDS 0x04
-#define SDVO_DEVICE_TMDS 0x08
-
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
deleted file mode 100644
index 36dd63044b06..000000000000
--- a/drivers/staging/gma500/psb_irq.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-/*
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "power.h"
-#include "mdfld_output.h"
-
-/*
- * inline functions
- */
-
-static inline u32
-psb_pipestat(int pipe)
-{
- if (pipe == 0)
- return PIPEASTAT;
- if (pipe == 1)
- return PIPEBSTAT;
- if (pipe == 2)
- return PIPECSTAT;
- BUG();
-}
-
-static inline u32
-mid_pipe_event(int pipe)
-{
- if (pipe == 0)
- return _PSB_PIPEA_EVENT_FLAG;
- if (pipe == 1)
- return _MDFLD_PIPEB_EVENT_FLAG;
- if (pipe == 2)
- return _MDFLD_PIPEC_EVENT_FLAG;
- BUG();
-}
-
-static inline u32
-mid_pipe_vsync(int pipe)
-{
- if (pipe == 0)
- return _PSB_VSYNC_PIPEA_FLAG;
- if (pipe == 1)
- return _PSB_VSYNC_PIPEB_FLAG;
- if (pipe == 2)
- return _MDFLD_PIPEC_VBLANK_FLAG;
- BUG();
-}
-
-static inline u32
-mid_pipeconf(int pipe)
-{
- if (pipe == 0)
- return PIPEACONF;
- if (pipe == 1)
- return PIPEBCONF;
- if (pipe == 2)
- return PIPECCONF;
- BUG();
-}
-
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
-{
- if ((dev_priv->pipestat[pipe] & mask) != mask) {
- u32 reg = psb_pipestat(pipe);
- dev_priv->pipestat[pipe] |= mask;
- /* Enable the interrupt, clear any pending status */
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 writeVal = PSB_RVDC32(reg);
- writeVal |= (mask | (mask >> 16));
- PSB_WVDC32(writeVal, reg);
- (void) PSB_RVDC32(reg);
- gma_power_end(dev_priv->dev);
- }
- }
-}
-
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
-{
- if ((dev_priv->pipestat[pipe] & mask) != 0) {
- u32 reg = psb_pipestat(pipe);
- dev_priv->pipestat[pipe] &= ~mask;
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 writeVal = PSB_RVDC32(reg);
- writeVal &= ~mask;
- PSB_WVDC32(writeVal, reg);
- (void) PSB_RVDC32(reg);
- gma_power_end(dev_priv->dev);
- }
- }
-}
-
-void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 pipe_event = mid_pipe_event(pipe);
- dev_priv->vdc_irq_mask |= pipe_event;
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- gma_power_end(dev_priv->dev);
- }
-}
-
-void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
- if (dev_priv->pipestat[pipe] == 0) {
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 pipe_event = mid_pipe_event(pipe);
- dev_priv->vdc_irq_mask &= ~pipe_event;
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- gma_power_end(dev_priv->dev);
- }
- }
-}
-
-/**
- * Display controller interrupt handler for pipe event.
- *
- */
-static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
-
- uint32_t pipe_stat_val = 0;
- uint32_t pipe_stat_reg = psb_pipestat(pipe);
- uint32_t pipe_enable = dev_priv->pipestat[pipe];
- uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
- uint32_t pipe_clear;
- uint32_t i = 0;
-
- spin_lock(&dev_priv->irqmask_lock);
-
- pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
- pipe_stat_val &= pipe_enable | pipe_status;
- pipe_stat_val &= pipe_stat_val >> 16;
-
- spin_unlock(&dev_priv->irqmask_lock);
-
- /* Clear the 2nd level interrupt status bits
- * Sometimes the bits are very sticky so we repeat until they unstick */
- for (i = 0; i < 0xffff; i++) {
- PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
- pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status;
-
- if (pipe_clear == 0)
- break;
- }
-
- if (pipe_clear)
- dev_err(dev->dev,
- "%s, can't clear status bits for pipe %d, its value = 0x%x.\n",
- __func__, pipe, PSB_RVDC32(pipe_stat_reg));
-
- if (pipe_stat_val & PIPE_VBLANK_STATUS)
- drm_handle_vblank(dev, pipe);
-
- if (pipe_stat_val & PIPE_TE_STATUS)
- drm_handle_vblank(dev, pipe);
-}
-
-/*
- * Display controller interrupt handler.
- */
-static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
-{
- if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
- mid_pipe_event_handler(dev, 0);
-
- if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)
- mid_pipe_event_handler(dev, 1);
-}
-
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
-{
- struct drm_device *dev = (struct drm_device *) arg;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
-
- uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
- int handled = 0;
-
- spin_lock(&dev_priv->irqmask_lock);
-
- vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
-
- if (vdc_stat & _PSB_PIPE_EVENT_FLAG)
- dsp_int = 1;
-
- /* FIXME: Handle Medfield
- if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
- dsp_int = 1;
- */
-
- if (vdc_stat & _PSB_IRQ_SGX_FLAG)
- sgx_int = 1;
-
- vdc_stat &= dev_priv->vdc_irq_mask;
- spin_unlock(&dev_priv->irqmask_lock);
-
- if (dsp_int && gma_power_is_on(dev)) {
- psb_vdc_interrupt(dev, vdc_stat);
- handled = 1;
- }
-
- if (sgx_int) {
- /* Not expected - we have it masked, shut it up */
- u32 s, s2;
- s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
- s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
- PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
- PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
- /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
- we may as well poll even if we add that ! */
- handled = 1;
- }
-
- PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
- (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
- DRM_READMEMORYBARRIER();
-
- if (!handled)
- return IRQ_NONE;
-
- return IRQ_HANDLED;
-}
-
-void psb_irq_preinstall(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- if (gma_power_is_on(dev))
- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- if (dev->vblank_enabled[0])
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
- if (dev->vblank_enabled[1])
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
-
- /* FIXME: Handle Medfield irq mask
- if (dev->vblank_enabled[1])
- dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
- if (dev->vblank_enabled[2])
- dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
- */
-
- /* This register is safe even if display island is off */
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-int psb_irq_postinstall(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- /* This register is safe even if display island is off */
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-
- if (dev->vblank_enabled[0])
- psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
- else
- psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- if (dev->vblank_enabled[1])
- psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
- else
- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- if (dev->vblank_enabled[2])
- psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
- else
- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- return 0;
-}
-
-void psb_irq_uninstall(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
-
- if (dev->vblank_enabled[0])
- psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- if (dev->vblank_enabled[1])
- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- if (dev->vblank_enabled[2])
- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
- _PSB_IRQ_MSVDX_FLAG |
- _LNC_IRQ_TOPAZ_FLAG;
-
- /* These two registers are safe even if display island is off */
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
-
- wmb();
-
- /* This register is safe even if display island is off */
- PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-void psb_irq_turn_on_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- u32 hist_reg;
- u32 pwm_reg;
-
- if (gma_power_begin(dev, false)) {
- PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
- PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
- PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
- | PWM_PHASEIN_INT_ENABLE,
- PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
- psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
- PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
- HISTOGRAM_INT_CONTROL);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
- PWM_CONTROL_LOGIC);
-
- gma_power_end(dev);
- }
-}
-
-int psb_irq_enable_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- /* enable DPST */
- mid_enable_pipe_event(dev_priv, 0);
- psb_irq_turn_on_dpst(dev);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- return 0;
-}
-
-void psb_irq_turn_off_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- u32 hist_reg;
- u32 pwm_reg;
-
- if (gma_power_begin(dev, false)) {
- PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
- psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
- PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
- gma_power_end(dev);
- }
-}
-
-int psb_irq_disable_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- mid_disable_pipe_event(dev_priv, 0);
- psb_irq_turn_off_dpst(dev);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
- return 0;
-}
-
-#ifdef PSB_FIXME
-static int psb_vblank_do_wait(struct drm_device *dev,
- unsigned int *sequence, atomic_t *counter)
-{
- unsigned int cur_vblank;
- int ret = 0;
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(counter))
- - *sequence) <= (1 << 23)));
- *sequence = cur_vblank;
-
- return ret;
-}
-#endif
-
-/*
- * It is used to enable VBLANK interrupt
- */
-int psb_enable_vblank(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long irqflags;
- uint32_t reg_val = 0;
- uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
-#if defined(CONFIG_DRM_PSB_MFLD)
- /* Medfield is different - we should perhaps extract out vblank
- and blacklight etc ops */
- if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
- return mdfld_enable_te(dev, pipe);
-#endif
- if (gma_power_begin(dev, false)) {
- reg_val = REG_READ(pipeconf_reg);
- gma_power_end(dev);
- }
-
- if (!(reg_val & PIPEACONF_ENABLE))
- return -EINVAL;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- if (pipe == 0)
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
- else if (pipe == 1)
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
-
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
- return 0;
-}
-
-/*
- * It is used to disable VBLANK interrupt
- */
-void psb_disable_vblank(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long irqflags;
-
-#if defined(CONFIG_DRM_PSB_MFLD)
- if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
- mdfld_disable_te(dev, pipe);
-#endif
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- if (pipe == 0)
- dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG;
- else if (pipe == 1)
- dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG;
-
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-/**
- * mdfld_enable_te - enable TE events
- * @dev: our DRM device
- * @pipe: which pipe to work on
- *
- * Enable TE events on a Medfield display pipe. Medfield specific.
- */
-int mdfld_enable_te(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long flags;
- uint32_t reg_val = 0;
- uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
- if (gma_power_begin(dev, false)) {
- reg_val = REG_READ(pipeconf_reg);
- gma_power_end(dev);
- }
-
- if (!(reg_val & PIPEACONF_ENABLE))
- return -EINVAL;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
-
- mid_enable_pipe_event(dev_priv, pipe);
- psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
-
- return 0;
-}
-
-/**
- * mdfld_disable_te - disable TE events
- * @dev: our DRM device
- * @pipe: which pipe to work on
- *
- * Disable TE events on a Medfield display pipe. Medfield specific.
- */
-void mdfld_disable_te(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long flags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
-
- mid_disable_pipe_event(dev_priv, pipe);
- psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
-}
-
-/* Called from drm generic code, passed a 'crtc', which
- * we use as a pipe index
- */
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
-{
- uint32_t high_frame = PIPEAFRAMEHIGH;
- uint32_t low_frame = PIPEAFRAMEPIXEL;
- uint32_t pipeconf_reg = PIPEACONF;
- uint32_t reg_val = 0;
- uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
-
- switch (pipe) {
- case 0:
- break;
- case 1:
- high_frame = PIPEBFRAMEHIGH;
- low_frame = PIPEBFRAMEPIXEL;
- pipeconf_reg = PIPEBCONF;
- break;
- case 2:
- high_frame = PIPECFRAMEHIGH;
- low_frame = PIPECFRAMEPIXEL;
- pipeconf_reg = PIPECCONF;
- break;
- default:
- dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
- return 0;
- }
-
- if (!gma_power_begin(dev, false))
- return 0;
-
- reg_val = REG_READ(pipeconf_reg);
-
- if (!(reg_val & PIPEACONF_ENABLE)) {
- dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
- pipe);
- goto psb_get_vblank_counter_exit;
- }
-
- /*
- * High & low register fields aren't synchronized, so make sure
- * we get a low value that's stable across two reads of the high
- * register.
- */
- do {
- high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
- PIPE_FRAME_HIGH_SHIFT);
- low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
- PIPE_FRAME_LOW_SHIFT);
- high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
- PIPE_FRAME_HIGH_SHIFT);
- } while (high1 != high2);
-
- count = (high1 << 8) | low;
-
-psb_get_vblank_counter_exit:
-
- gma_power_end(dev);
-
- return count;
-}
-
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
deleted file mode 100644
index 216fda38b57d..000000000000
--- a/drivers/staging/gma500/psb_irq.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Authors:
- * Benjamin Defnet <benjamin.r.defnet@intel.com>
- * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- *
- **************************************************************************/
-
-#ifndef _SYSIRQ_H_
-#define _SYSIRQ_H_
-
-#include <drm/drmP.h>
-
-bool sysirq_init(struct drm_device *dev);
-void sysirq_uninit(struct drm_device *dev);
-
-void psb_irq_preinstall(struct drm_device *dev);
-int psb_irq_postinstall(struct drm_device *dev);
-void psb_irq_uninstall(struct drm_device *dev);
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
-
-int psb_irq_enable_dpst(struct drm_device *dev);
-int psb_irq_disable_dpst(struct drm_device *dev);
-void psb_irq_turn_on_dpst(struct drm_device *dev);
-void psb_irq_turn_off_dpst(struct drm_device *dev);
-int psb_enable_vblank(struct drm_device *dev, int pipe);
-void psb_disable_vblank(struct drm_device *dev, int pipe);
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
-
-#endif /* _SYSIRQ_H_ */
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c
deleted file mode 100644
index b867aabe6bf3..000000000000
--- a/drivers/staging/gma500/psb_lid.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * 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.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/spinlock.h>
-
-static void psb_lid_timer_func(unsigned long data)
-{
- struct drm_psb_private * dev_priv = (struct drm_psb_private *)data;
- struct drm_device *dev = (struct drm_device *)dev_priv->dev;
- struct timer_list *lid_timer = &dev_priv->lid_timer;
- unsigned long irq_flags;
- u32 *lid_state = dev_priv->lid_state;
- u32 pp_status;
-
- if (readl(lid_state) == dev_priv->lid_last_state)
- goto lid_timer_schedule;
-
- if ((readl(lid_state)) & 0x01) {
- /*lid state is open*/
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
-
- /*FIXME: should be backlight level before*/
- psb_intel_lvds_set_brightness(dev, 100);
- } else {
- psb_intel_lvds_set_brightness(dev, 0);
-
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
- }
- dev_priv->lid_last_state = readl(lid_state);
-
-lid_timer_schedule:
- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
- if (!timer_pending(lid_timer)) {
- lid_timer->expires = jiffies + PSB_LID_DELAY;
- add_timer(lid_timer);
- }
- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
-{
- struct timer_list *lid_timer = &dev_priv->lid_timer;
- unsigned long irq_flags;
-
- spin_lock_init(&dev_priv->lid_lock);
- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-
- init_timer(lid_timer);
-
- lid_timer->data = (unsigned long)dev_priv;
- lid_timer->function = psb_lid_timer_func;
- lid_timer->expires = jiffies + PSB_LID_DELAY;
-
- add_timer(lid_timer);
- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
-{
- del_timer_sync(&dev_priv->lid_timer);
-}
-
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
deleted file mode 100644
index b81c7c1e9c2d..000000000000
--- a/drivers/staging/gma500/psb_reg.h
+++ /dev/null
@@ -1,582 +0,0 @@
-/**************************************************************************
- *
- * Copyright (c) (2005-2007) Imagination Technologies Limited.
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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..
- *
- **************************************************************************/
-
-#ifndef _PSB_REG_H_
-#define _PSB_REG_H_
-
-#define PSB_CR_CLKGATECTL 0x0000
-#define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24)
-#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
-#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16)
-#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12)
-#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4)
-#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0)
-#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0)
-#define _PSB_C_CLKGATECTL_CLKG_ENABLED (0)
-#define _PSB_C_CLKGATECTL_CLKG_DISABLED (1)
-#define _PSB_C_CLKGATECTL_CLKG_AUTO (2)
-
-#define PSB_CR_CORE_ID 0x0010
-#define _PSB_CC_ID_ID_SHIFT (16)
-#define _PSB_CC_ID_ID_MASK (0xFFFF << 16)
-#define _PSB_CC_ID_CONFIG_SHIFT (0)
-#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0)
-
-#define PSB_CR_CORE_REVISION 0x0014
-#define _PSB_CC_REVISION_DESIGNER_SHIFT (24)
-#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24)
-#define _PSB_CC_REVISION_MAJOR_SHIFT (16)
-#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16)
-#define _PSB_CC_REVISION_MINOR_SHIFT (8)
-#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8)
-#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
-#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD1 0x0018
-
-#define PSB_CR_SOFT_RESET 0x0080
-#define _PSB_CS_RESET_TSP_RESET (1 << 6)
-#define _PSB_CS_RESET_ISP_RESET (1 << 5)
-#define _PSB_CS_RESET_USE_RESET (1 << 4)
-#define _PSB_CS_RESET_TA_RESET (1 << 3)
-#define _PSB_CS_RESET_DPM_RESET (1 << 2)
-#define _PSB_CS_RESET_TWOD_RESET (1 << 1)
-#define _PSB_CS_RESET_BIF_RESET (1 << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD2 0x001C
-
-#define PSB_CR_EVENT_HOST_ENABLE2 0x0110
-
-#define PSB_CR_EVENT_STATUS2 0x0118
-
-#define PSB_CR_EVENT_HOST_CLEAR2 0x0114
-#define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4)
-
-#define PSB_CR_EVENT_STATUS 0x012C
-
-#define PSB_CR_EVENT_HOST_ENABLE 0x0130
-
-#define PSB_CR_EVENT_HOST_CLEAR 0x0134
-#define _PSB_CE_MASTER_INTERRUPT (1 << 31)
-#define _PSB_CE_TA_DPM_FAULT (1 << 28)
-#define _PSB_CE_TWOD_COMPLETE (1 << 27)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25)
-#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24)
-#define _PSB_CE_PIXELBE_END_RENDER (1 << 18)
-#define _PSB_CE_SW_EVENT (1 << 14)
-#define _PSB_CE_TA_FINISHED (1 << 13)
-#define _PSB_CE_TA_TERMINATE (1 << 12)
-#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1)
-#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0)
-
-
-#define PSB_USE_OFFSET_MASK 0x0007FFFF
-#define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1)
-#define PSB_CR_USE_CODE_BASE0 0x0A0C
-#define PSB_CR_USE_CODE_BASE1 0x0A10
-#define PSB_CR_USE_CODE_BASE2 0x0A14
-#define PSB_CR_USE_CODE_BASE3 0x0A18
-#define PSB_CR_USE_CODE_BASE4 0x0A1C
-#define PSB_CR_USE_CODE_BASE5 0x0A20
-#define PSB_CR_USE_CODE_BASE6 0x0A24
-#define PSB_CR_USE_CODE_BASE7 0x0A28
-#define PSB_CR_USE_CODE_BASE8 0x0A2C
-#define PSB_CR_USE_CODE_BASE9 0x0A30
-#define PSB_CR_USE_CODE_BASE10 0x0A34
-#define PSB_CR_USE_CODE_BASE11 0x0A38
-#define PSB_CR_USE_CODE_BASE12 0x0A3C
-#define PSB_CR_USE_CODE_BASE13 0x0A40
-#define PSB_CR_USE_CODE_BASE14 0x0A44
-#define PSB_CR_USE_CODE_BASE15 0x0A48
-#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2))
-#define _PSB_CUC_BASE_DM_SHIFT (25)
-#define _PSB_CUC_BASE_DM_MASK (0x3 << 25)
-#define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */
-#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7)
-#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0)
-#define _PSB_CUC_DM_VERTEX (0)
-#define _PSB_CUC_DM_PIXEL (1)
-#define _PSB_CUC_DM_RESERVED (2)
-#define _PSB_CUC_DM_EDM (3)
-
-#define PSB_CR_PDS_EXEC_BASE 0x0AB8
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
-
-#define PSB_CR_EVENT_KICKER 0x0AC4
-#define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */
-
-#define PSB_CR_EVENT_KICK 0x0AC8
-#define _PSB_CE_KICK_NOW (1 << 0)
-
-#define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38
-
-#define PSB_CR_BIF_CTRL 0x0C00
-#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4)
-#define _PSB_CB_CTRL_INVALDC (1 << 3)
-#define _PSB_CB_CTRL_FLUSH (1 << 2)
-
-#define PSB_CR_BIF_INT_STAT 0x0C04
-
-#define PSB_CR_BIF_FAULT 0x0C08
-#define _PSB_CBI_STAT_PF_N_RW (1 << 14)
-#define _PSB_CBI_STAT_FAULT_SHIFT (0)
-#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0)
-#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1)
-#define _PSB_CBI_STAT_FAULT_TA (1 << 2)
-#define _PSB_CBI_STAT_FAULT_VDM (1 << 3)
-#define _PSB_CBI_STAT_FAULT_2D (1 << 4)
-#define _PSB_CBI_STAT_FAULT_PBE (1 << 5)
-#define _PSB_CBI_STAT_FAULT_TSP (1 << 6)
-#define _PSB_CBI_STAT_FAULT_ISP (1 << 7)
-#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8)
-#define _PSB_CBI_STAT_FAULT_HOST (1 << 9)
-
-#define PSB_CR_BIF_BANK0 0x0C78
-#define PSB_CR_BIF_BANK1 0x0C7C
-#define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84
-#define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88
-#define PSB_CR_BIF_3D_REQ_BASE 0x0CAC
-
-#define PSB_CR_2D_SOCIF 0x0E18
-#define _PSB_C2_SOCIF_FREESPACE_SHIFT (0)
-#define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0)
-#define _PSB_C2_SOCIF_EMPTY (0x80 << 0)
-
-#define PSB_CR_2D_BLIT_STATUS 0x0E04
-#define _PSB_C2B_STATUS_BUSY (1 << 24)
-#define _PSB_C2B_STATUS_COMPLETE_SHIFT (0)
-#define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0)
-
-/*
- * 2D defs.
- */
-
-/*
- * 2D Slave Port Data : Block Header's Object Type
- */
-
-#define PSB_2D_CLIP_BH (0x00000000)
-#define PSB_2D_PAT_BH (0x10000000)
-#define PSB_2D_CTRL_BH (0x20000000)
-#define PSB_2D_SRC_OFF_BH (0x30000000)
-#define PSB_2D_MASK_OFF_BH (0x40000000)
-#define PSB_2D_RESERVED1_BH (0x50000000)
-#define PSB_2D_RESERVED2_BH (0x60000000)
-#define PSB_2D_FENCE_BH (0x70000000)
-#define PSB_2D_BLIT_BH (0x80000000)
-#define PSB_2D_SRC_SURF_BH (0x90000000)
-#define PSB_2D_DST_SURF_BH (0xA0000000)
-#define PSB_2D_PAT_SURF_BH (0xB0000000)
-#define PSB_2D_SRC_PAL_BH (0xC0000000)
-#define PSB_2D_PAT_PAL_BH (0xD0000000)
-#define PSB_2D_MASK_SURF_BH (0xE0000000)
-#define PSB_2D_FLUSH_BH (0xF0000000)
-
-/*
- * Clip Definition block (PSB_2D_CLIP_BH)
- */
-#define PSB_2D_CLIPCOUNT_MAX (1)
-#define PSB_2D_CLIPCOUNT_MASK (0x00000000)
-#define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF)
-#define PSB_2D_CLIPCOUNT_SHIFT (0)
-/* clip rectangle min & max */
-#define PSB_2D_CLIP_XMAX_MASK (0x00FFF000)
-#define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF)
-#define PSB_2D_CLIP_XMAX_SHIFT (12)
-#define PSB_2D_CLIP_XMIN_MASK (0x00000FFF)
-#define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000)
-#define PSB_2D_CLIP_XMIN_SHIFT (0)
-/* clip rectangle offset */
-#define PSB_2D_CLIP_YMAX_MASK (0x00FFF000)
-#define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF)
-#define PSB_2D_CLIP_YMAX_SHIFT (12)
-#define PSB_2D_CLIP_YMIN_MASK (0x00000FFF)
-#define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000)
-#define PSB_2D_CLIP_YMIN_SHIFT (0)
-
-/*
- * Pattern Control (PSB_2D_PAT_BH)
- */
-#define PSB_2D_PAT_HEIGHT_MASK (0x0000001F)
-#define PSB_2D_PAT_HEIGHT_SHIFT (0)
-#define PSB_2D_PAT_WIDTH_MASK (0x000003E0)
-#define PSB_2D_PAT_WIDTH_SHIFT (5)
-#define PSB_2D_PAT_YSTART_MASK (0x00007C00)
-#define PSB_2D_PAT_YSTART_SHIFT (10)
-#define PSB_2D_PAT_XSTART_MASK (0x000F8000)
-#define PSB_2D_PAT_XSTART_SHIFT (15)
-
-/*
- * 2D Control block (PSB_2D_CTRL_BH)
- */
-/* Present Flags */
-#define PSB_2D_SRCCK_CTRL (0x00000001)
-#define PSB_2D_DSTCK_CTRL (0x00000002)
-#define PSB_2D_ALPHA_CTRL (0x00000004)
-/* Colour Key Colour (SRC/DST)*/
-#define PSB_2D_CK_COL_MASK (0xFFFFFFFF)
-#define PSB_2D_CK_COL_CLRMASK (0x00000000)
-#define PSB_2D_CK_COL_SHIFT (0)
-/* Colour Key Mask (SRC/DST)*/
-#define PSB_2D_CK_MASK_MASK (0xFFFFFFFF)
-#define PSB_2D_CK_MASK_CLRMASK (0x00000000)
-#define PSB_2D_CK_MASK_SHIFT (0)
-/* Alpha Control (Alpha/RGB)*/
-#define PSB_2D_GBLALPHA_MASK (0x000FF000)
-#define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF)
-#define PSB_2D_GBLALPHA_SHIFT (12)
-#define PSB_2D_SRCALPHA_OP_MASK (0x00700000)
-#define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF)
-#define PSB_2D_SRCALPHA_OP_SHIFT (20)
-#define PSB_2D_SRCALPHA_OP_ONE (0x00000000)
-#define PSB_2D_SRCALPHA_OP_SRC (0x00100000)
-#define PSB_2D_SRCALPHA_OP_DST (0x00200000)
-#define PSB_2D_SRCALPHA_OP_SG (0x00300000)
-#define PSB_2D_SRCALPHA_OP_DG (0x00400000)
-#define PSB_2D_SRCALPHA_OP_GBL (0x00500000)
-#define PSB_2D_SRCALPHA_OP_ZERO (0x00600000)
-#define PSB_2D_SRCALPHA_INVERT (0x00800000)
-#define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF)
-#define PSB_2D_DSTALPHA_OP_MASK (0x07000000)
-#define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF)
-#define PSB_2D_DSTALPHA_OP_SHIFT (24)
-#define PSB_2D_DSTALPHA_OP_ONE (0x00000000)
-#define PSB_2D_DSTALPHA_OP_SRC (0x01000000)
-#define PSB_2D_DSTALPHA_OP_DST (0x02000000)
-#define PSB_2D_DSTALPHA_OP_SG (0x03000000)
-#define PSB_2D_DSTALPHA_OP_DG (0x04000000)
-#define PSB_2D_DSTALPHA_OP_GBL (0x05000000)
-#define PSB_2D_DSTALPHA_OP_ZERO (0x06000000)
-#define PSB_2D_DSTALPHA_INVERT (0x08000000)
-#define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF)
-
-#define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000)
-#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
-#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000)
-#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF)
-
-/*
- *Source Offset (PSB_2D_SRC_OFF_BH)
- */
-#define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12)
-#define PSB_2D_SRCOFF_XSTART_SHIFT (12)
-#define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF)
-#define PSB_2D_SRCOFF_YSTART_SHIFT (0)
-
-/*
- * Mask Offset (PSB_2D_MASK_OFF_BH)
- */
-#define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12)
-#define PSB_2D_MASKOFF_XSTART_SHIFT (12)
-#define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF)
-#define PSB_2D_MASKOFF_YSTART_SHIFT (0)
-
-/*
- * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
- */
-
-/*
- *Blit Rectangle (PSB_2D_BLIT_BH)
- */
-
-#define PSB_2D_ROT_MASK (3 << 25)
-#define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK)
-#define PSB_2D_ROT_NONE (0 << 25)
-#define PSB_2D_ROT_90DEGS (1 << 25)
-#define PSB_2D_ROT_180DEGS (2 << 25)
-#define PSB_2D_ROT_270DEGS (3 << 25)
-
-#define PSB_2D_COPYORDER_MASK (3 << 23)
-#define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK)
-#define PSB_2D_COPYORDER_TL2BR (0 << 23)
-#define PSB_2D_COPYORDER_BR2TL (1 << 23)
-#define PSB_2D_COPYORDER_TR2BL (2 << 23)
-#define PSB_2D_COPYORDER_BL2TR (3 << 23)
-
-#define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF)
-#define PSB_2D_DSTCK_DISABLE (0x00000000)
-#define PSB_2D_DSTCK_PASS (0x00200000)
-#define PSB_2D_DSTCK_REJECT (0x00400000)
-
-#define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF)
-#define PSB_2D_SRCCK_DISABLE (0x00000000)
-#define PSB_2D_SRCCK_PASS (0x00080000)
-#define PSB_2D_SRCCK_REJECT (0x00100000)
-
-#define PSB_2D_CLIP_ENABLE (0x00040000)
-
-#define PSB_2D_ALPHA_ENABLE (0x00020000)
-
-#define PSB_2D_PAT_CLRMASK (0xFFFEFFFF)
-#define PSB_2D_PAT_MASK (0x00010000)
-#define PSB_2D_USE_PAT (0x00010000)
-#define PSB_2D_USE_FILL (0x00000000)
-/*
- * Tungsten Graphics note on rop codes: If rop A and rop B are
- * identical, the mask surface will not be read and need not be
- * set up.
- */
-
-#define PSB_2D_ROP3B_MASK (0x0000FF00)
-#define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF)
-#define PSB_2D_ROP3B_SHIFT (8)
-/* rop code A */
-#define PSB_2D_ROP3A_MASK (0x000000FF)
-#define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00)
-#define PSB_2D_ROP3A_SHIFT (0)
-
-#define PSB_2D_ROP4_MASK (0x0000FFFF)
-/*
- * DWORD0: (Only pass if Pattern control == Use Fill Colour)
- * Fill Colour RGBA8888
- */
-#define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF)
-#define PSB_2D_FILLCOLOUR_SHIFT (0)
-/*
- * DWORD1: (Always Present)
- * X Start (Dest)
- * Y Start (Dest)
- */
-#define PSB_2D_DST_XSTART_MASK (0x00FFF000)
-#define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF)
-#define PSB_2D_DST_XSTART_SHIFT (12)
-#define PSB_2D_DST_YSTART_MASK (0x00000FFF)
-#define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000)
-#define PSB_2D_DST_YSTART_SHIFT (0)
-/*
- * DWORD2: (Always Present)
- * X Size (Dest)
- * Y Size (Dest)
- */
-#define PSB_2D_DST_XSIZE_MASK (0x00FFF000)
-#define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF)
-#define PSB_2D_DST_XSIZE_SHIFT (12)
-#define PSB_2D_DST_YSIZE_MASK (0x00000FFF)
-#define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000)
-#define PSB_2D_DST_YSIZE_SHIFT (0)
-
-/*
- * Source Surface (PSB_2D_SRC_SURF_BH)
- */
-/*
- * WORD 0
- */
-
-#define PSB_2D_SRC_FORMAT_MASK (0x00078000)
-#define PSB_2D_SRC_1_PAL (0x00000000)
-#define PSB_2D_SRC_2_PAL (0x00008000)
-#define PSB_2D_SRC_4_PAL (0x00010000)
-#define PSB_2D_SRC_8_PAL (0x00018000)
-#define PSB_2D_SRC_8_ALPHA (0x00020000)
-#define PSB_2D_SRC_4_ALPHA (0x00028000)
-#define PSB_2D_SRC_332RGB (0x00030000)
-#define PSB_2D_SRC_4444ARGB (0x00038000)
-#define PSB_2D_SRC_555RGB (0x00040000)
-#define PSB_2D_SRC_1555ARGB (0x00048000)
-#define PSB_2D_SRC_565RGB (0x00050000)
-#define PSB_2D_SRC_0888ARGB (0x00058000)
-#define PSB_2D_SRC_8888ARGB (0x00060000)
-#define PSB_2D_SRC_8888UYVY (0x00068000)
-#define PSB_2D_SRC_RESERVED (0x00070000)
-#define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000)
-
-
-#define PSB_2D_SRC_STRIDE_MASK (0x00007FFF)
-#define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000)
-#define PSB_2D_SRC_STRIDE_SHIFT (0)
-/*
- * WORD 1 - Base Address
- */
-#define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC)
-#define PSB_2D_SRC_ADDR_CLRMASK (0x00000003)
-#define PSB_2D_SRC_ADDR_SHIFT (2)
-#define PSB_2D_SRC_ADDR_ALIGNSHIFT (2)
-
-/*
- * Pattern Surface (PSB_2D_PAT_SURF_BH)
- */
-/*
- * WORD 0
- */
-
-#define PSB_2D_PAT_FORMAT_MASK (0x00078000)
-#define PSB_2D_PAT_1_PAL (0x00000000)
-#define PSB_2D_PAT_2_PAL (0x00008000)
-#define PSB_2D_PAT_4_PAL (0x00010000)
-#define PSB_2D_PAT_8_PAL (0x00018000)
-#define PSB_2D_PAT_8_ALPHA (0x00020000)
-#define PSB_2D_PAT_4_ALPHA (0x00028000)
-#define PSB_2D_PAT_332RGB (0x00030000)
-#define PSB_2D_PAT_4444ARGB (0x00038000)
-#define PSB_2D_PAT_555RGB (0x00040000)
-#define PSB_2D_PAT_1555ARGB (0x00048000)
-#define PSB_2D_PAT_565RGB (0x00050000)
-#define PSB_2D_PAT_0888ARGB (0x00058000)
-#define PSB_2D_PAT_8888ARGB (0x00060000)
-
-#define PSB_2D_PAT_STRIDE_MASK (0x00007FFF)
-#define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000)
-#define PSB_2D_PAT_STRIDE_SHIFT (0)
-/*
- * WORD 1 - Base Address
- */
-#define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC)
-#define PSB_2D_PAT_ADDR_CLRMASK (0x00000003)
-#define PSB_2D_PAT_ADDR_SHIFT (2)
-#define PSB_2D_PAT_ADDR_ALIGNSHIFT (2)
-
-/*
- * Destination Surface (PSB_2D_DST_SURF_BH)
- */
-/*
- * WORD 0
- */
-
-#define PSB_2D_DST_FORMAT_MASK (0x00078000)
-#define PSB_2D_DST_332RGB (0x00030000)
-#define PSB_2D_DST_4444ARGB (0x00038000)
-#define PSB_2D_DST_555RGB (0x00040000)
-#define PSB_2D_DST_1555ARGB (0x00048000)
-#define PSB_2D_DST_565RGB (0x00050000)
-#define PSB_2D_DST_0888ARGB (0x00058000)
-#define PSB_2D_DST_8888ARGB (0x00060000)
-#define PSB_2D_DST_8888AYUV (0x00070000)
-
-#define PSB_2D_DST_STRIDE_MASK (0x00007FFF)
-#define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000)
-#define PSB_2D_DST_STRIDE_SHIFT (0)
-/*
- * WORD 1 - Base Address
- */
-#define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC)
-#define PSB_2D_DST_ADDR_CLRMASK (0x00000003)
-#define PSB_2D_DST_ADDR_SHIFT (2)
-#define PSB_2D_DST_ADDR_ALIGNSHIFT (2)
-
-/*
- * Mask Surface (PSB_2D_MASK_SURF_BH)
- */
-/*
- * WORD 0
- */
-#define PSB_2D_MASK_STRIDE_MASK (0x00007FFF)
-#define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000)
-#define PSB_2D_MASK_STRIDE_SHIFT (0)
-/*
- * WORD 1 - Base Address
- */
-#define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC)
-#define PSB_2D_MASK_ADDR_CLRMASK (0x00000003)
-#define PSB_2D_MASK_ADDR_SHIFT (2)
-#define PSB_2D_MASK_ADDR_ALIGNSHIFT (2)
-
-/*
- * Source Palette (PSB_2D_SRC_PAL_BH)
- */
-
-#define PSB_2D_SRCPAL_ADDR_SHIFT (0)
-#define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007)
-#define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8)
-#define PSB_2D_SRCPAL_BYTEALIGN (1024)
-
-/*
- * Pattern Palette (PSB_2D_PAT_PAL_BH)
- */
-
-#define PSB_2D_PATPAL_ADDR_SHIFT (0)
-#define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007)
-#define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8)
-#define PSB_2D_PATPAL_BYTEALIGN (1024)
-
-/*
- * Rop3 Codes (2 LS bytes)
- */
-
-#define PSB_2D_ROP3_SRCCOPY (0xCCCC)
-#define PSB_2D_ROP3_PATCOPY (0xF0F0)
-#define PSB_2D_ROP3_WHITENESS (0xFFFF)
-#define PSB_2D_ROP3_BLACKNESS (0x0000)
-#define PSB_2D_ROP3_SRC (0xCC)
-#define PSB_2D_ROP3_PAT (0xF0)
-#define PSB_2D_ROP3_DST (0xAA)
-
-/*
- * Sizes.
- */
-
-#define PSB_SCENE_HW_COOKIE_SIZE 16
-#define PSB_TA_MEM_HW_COOKIE_SIZE 16
-
-/*
- * Scene stuff.
- */
-
-#define PSB_NUM_HW_SCENES 2
-
-/*
- * Scheduler completion actions.
- */
-
-#define PSB_RASTER_BLOCK 0
-#define PSB_RASTER 1
-#define PSB_RETURN 2
-#define PSB_TA 3
-
-/* Power management */
-#define PSB_PUNIT_PORT 0x04
-#define PSB_OSPMBA 0x78
-#define PSB_APMBA 0x7a
-#define PSB_APM_CMD 0x0
-#define PSB_APM_STS 0x04
-#define PSB_PWRGT_VID_ENC_MASK 0x30
-#define PSB_PWRGT_VID_DEC_MASK 0xc
-#define PSB_PWRGT_GL3_MASK 0xc0
-
-#define PSB_PM_SSC 0x20
-#define PSB_PM_SSS 0x30
-#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/
-#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000
-#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */
-/* Display SSS register bits are different in A0 vs. B0 */
-#define PSB_PWRGT_GFX_MASK 0x3
-#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0
-#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300
-#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00
-#define PSB_PWRGT_GFX_MASK_B0 0xc3
-#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000
-#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
-#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
-#endif
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index 70e006b50f29..5443e25086e9 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = {
};
module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile
index 592cf69020cd..d9cdc120d122 100644
--- a/drivers/staging/omapdrm/Makefile
+++ b/drivers/staging/omapdrm/Makefile
@@ -7,6 +7,7 @@ ccflags-y := -Iinclude/drm -Werror
omapdrm-y := omap_drv.o \
omap_debugfs.o \
omap_crtc.o \
+ omap_plane.o \
omap_encoder.o \
omap_connector.o \
omap_fb.o \
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c
index cffdf5e12394..17ca163e5896 100644
--- a/drivers/staging/omapdrm/omap_crtc.c
+++ b/drivers/staging/omapdrm/omap_crtc.c
@@ -27,196 +27,95 @@
struct omap_crtc {
struct drm_crtc base;
- struct omap_overlay *ovl;
- struct omap_overlay_info info;
+ struct drm_plane *plane;
+ const char *name;
int id;
- /* if there is a pending flip, this will be non-null: */
+ /* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;
+ struct drm_framebuffer *old_fb;
};
-/* push changes down to dss2 */
-static int commit(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct omap_overlay *ovl = omap_crtc->ovl;
- struct omap_overlay_info *info = &omap_crtc->info;
- int ret;
-
- DBG("%s", omap_crtc->ovl->name);
- DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
- info->out_height, info->screen_width);
- DBG("%d,%d %08x", info->pos_x, info->pos_y, info->paddr);
-
- /* NOTE: do we want to do this at all here, or just wait
- * for dpms(ON) since other CRTC's may not have their mode
- * set yet, so fb dimensions may still change..
- */
- ret = ovl->set_overlay_info(ovl, info);
- if (ret) {
- dev_err(dev->dev, "could not set overlay info\n");
- return ret;
- }
-
- /* our encoder doesn't necessarily get a commit() after this, in
- * particular in the dpms() and mode_set_base() cases, so force the
- * manager to update:
- *
- * could this be in the encoder somehow?
- */
- if (ovl->manager) {
- ret = ovl->manager->apply(ovl->manager);
- if (ret) {
- dev_err(dev->dev, "could not apply settings\n");
- return ret;
- }
- }
-
- if (info->enabled) {
- omap_framebuffer_flush(crtc->fb, crtc->x, crtc->y,
- crtc->fb->width, crtc->fb->height);
- }
-
- return 0;
-}
-
-/* update parameters that are dependent on the framebuffer dimensions and
- * position within the fb that this crtc scans out from. This is called
- * when framebuffer dimensions or x,y base may have changed, either due
- * to our mode, or a change in another crtc that is scanning out of the
- * same fb.
- */
-static void update_scanout(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- dma_addr_t paddr;
- unsigned int screen_width;
-
- omap_framebuffer_get_buffer(crtc->fb, crtc->x, crtc->y,
- NULL, &paddr, &screen_width);
-
- DBG("%s: %d,%d: %08x (%d)", omap_crtc->ovl->name,
- crtc->x, crtc->y, (u32)paddr, screen_width);
-
- omap_crtc->info.paddr = paddr;
- omap_crtc->info.screen_width = screen_width;
-}
-
static void omap_crtc_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size)
{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->ovl->name);
+ /* not supported.. at least not yet */
}
static void omap_crtc_destroy(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->ovl->name);
+ omap_crtc->plane->funcs->destroy(omap_crtc->plane);
drm_crtc_cleanup(crtc);
kfree(omap_crtc);
}
static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
{
+ struct omap_drm_private *priv = crtc->dev->dev_private;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ int i;
- DBG("%s: %d", omap_crtc->ovl->name, mode);
+ WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
- if (mode == DRM_MODE_DPMS_ON) {
- update_scanout(crtc);
- omap_crtc->info.enabled = true;
- } else {
- omap_crtc->info.enabled = false;
+ for (i = 0; i < priv->num_planes; i++) {
+ struct drm_plane *plane = priv->planes[i];
+ if (plane->crtc == crtc)
+ WARN_ON(omap_plane_dpms(plane, mode));
}
-
- WARN_ON(commit(crtc));
}
static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->ovl->name);
return true;
}
static int omap_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct drm_plane *plane = omap_crtc->plane;
- DBG("%s: %d,%d: %dx%d", omap_crtc->ovl->name, x, y,
- mode->hdisplay, mode->vdisplay);
-
- /* just use adjusted mode */
- mode = adjusted_mode;
-
- omap_crtc->info.width = mode->hdisplay;
- omap_crtc->info.height = mode->vdisplay;
- omap_crtc->info.out_width = mode->hdisplay;
- omap_crtc->info.out_height = mode->vdisplay;
- omap_crtc->info.color_mode = OMAP_DSS_COLOR_RGB24U;
- omap_crtc->info.rotation_type = OMAP_DSS_ROT_DMA;
- omap_crtc->info.rotation = OMAP_DSS_ROT_0;
- omap_crtc->info.global_alpha = 0xff;
- omap_crtc->info.mirror = 0;
- omap_crtc->info.mirror = 0;
- omap_crtc->info.pos_x = 0;
- omap_crtc->info.pos_y = 0;
-#if 0 /* re-enable when these are available in DSS2 driver */
- omap_crtc->info.zorder = 3; /* GUI in the front, video behind */
- omap_crtc->info.min_x_decim = 1;
- omap_crtc->info.max_x_decim = 1;
- omap_crtc->info.min_y_decim = 1;
- omap_crtc->info.max_y_decim = 1;
-#endif
-
- update_scanout(crtc);
-
- return 0;
+ return omap_plane_mode_set(plane, crtc, crtc->fb,
+ 0, 0, mode->hdisplay, mode->vdisplay,
+ x << 16, y << 16,
+ mode->hdisplay << 16, mode->vdisplay << 16);
}
static void omap_crtc_prepare(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct omap_overlay *ovl = omap_crtc->ovl;
-
- DBG("%s", omap_crtc->ovl->name);
-
- ovl->get_overlay_info(ovl, &omap_crtc->info);
-
+ DBG("%s", omap_crtc->name);
omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}
static void omap_crtc_commit(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->ovl->name);
+ DBG("%s", omap_crtc->name);
omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
+ struct drm_framebuffer *old_fb)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct drm_plane *plane = omap_crtc->plane;
+ struct drm_display_mode *mode = &crtc->mode;
- DBG("%s %d,%d: fb=%p", omap_crtc->ovl->name, x, y, old_fb);
-
- update_scanout(crtc);
-
- return commit(crtc);
+ return plane->funcs->update_plane(plane, crtc, crtc->fb,
+ 0, 0, mode->hdisplay, mode->vdisplay,
+ x << 16, y << 16,
+ mode->hdisplay << 16, mode->vdisplay << 16);
}
static void omap_crtc_load_lut(struct drm_crtc *crtc)
{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->ovl->name);
}
static void page_flip_cb(void *arg)
@@ -225,15 +124,16 @@ static void page_flip_cb(void *arg)
struct drm_device *dev = crtc->dev;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct drm_pending_vblank_event *event = omap_crtc->event;
+ struct drm_framebuffer *old_fb = omap_crtc->old_fb;
struct timeval now;
unsigned long flags;
WARN_ON(!event);
omap_crtc->event = NULL;
+ omap_crtc->old_fb = NULL;
- update_scanout(crtc);
- WARN_ON(commit(crtc));
+ omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
/* wakeup userspace */
/* TODO: this should happen *after* flip in vsync IRQ handler */
@@ -264,10 +164,11 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
return -EINVAL;
}
- crtc->fb = fb;
+ omap_crtc->old_fb = crtc->fb;
omap_crtc->event = event;
+ crtc->fb = fb;
- omap_gem_op_async(omap_framebuffer_bo(fb), OMAP_GEM_READ,
+ omap_gem_op_async(omap_framebuffer_bo(fb, 0), OMAP_GEM_READ,
page_flip_cb, crtc);
return 0;
@@ -290,12 +191,6 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
.load_lut = omap_crtc_load_lut,
};
-struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- return omap_crtc->ovl;
-}
-
/* initialize crtc */
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct omap_overlay *ovl, int id)
@@ -310,9 +205,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
goto fail;
}
- omap_crtc->ovl = ovl;
- omap_crtc->id = id;
crtc = &omap_crtc->base;
+
+ omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true);
+ omap_crtc->plane->crtc = crtc;
+ omap_crtc->name = ovl->name;
+ omap_crtc->id = id;
+
drm_crtc_init(dev, crtc, &omap_crtc_funcs);
drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 602aa2dd49c8..3bbea9aac404 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -204,12 +204,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
struct omap_overlay_manager *mgr = NULL;
struct drm_crtc *crtc;
- if (ovl->manager) {
- DBG("disconnecting %s from %s", ovl->name,
- ovl->manager->name);
- ovl->unset_manager(ovl);
- }
-
/* find next best connector, ones with detected connection first
*/
while (*j < priv->num_connectors && !mgr) {
@@ -245,11 +239,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
(*j)++;
}
- if (mgr) {
- DBG("connecting %s to %s", ovl->name, mgr->name);
- ovl->set_manager(ovl, mgr);
- }
-
crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
if (!crtc) {
@@ -265,6 +254,26 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
return 0;
}
+static int create_plane(struct drm_device *dev, struct omap_overlay *ovl,
+ unsigned int possible_crtcs)
+{
+ struct omap_drm_private *priv = dev->dev_private;
+ struct drm_plane *plane =
+ omap_plane_init(dev, ovl, possible_crtcs, false);
+
+ if (!plane) {
+ dev_err(dev->dev, "could not create plane: %s\n",
+ ovl->name);
+ return -ENOMEM;
+ }
+
+ BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
+
+ priv->planes[priv->num_planes++] = plane;
+
+ return 0;
+}
+
static int match_dev_name(struct omap_dss_device *dssdev, void *data)
{
return !strcmp(dssdev->name, data);
@@ -332,6 +341,12 @@ static int omap_modeset_init(struct drm_device *dev)
omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
create_crtc(dev, ovl, &j, connected_connectors);
}
+
+ for (i = 0; i < kms_pdata->pln_cnt; i++) {
+ struct omap_overlay *ovl =
+ omap_dss_get_overlay(kms_pdata->pln_ids[i]);
+ create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
+ }
} else {
/* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
* to make educated guesses about everything else
@@ -353,6 +368,12 @@ static int omap_modeset_init(struct drm_device *dev)
create_crtc(dev, omap_dss_get_overlay(i),
&j, connected_connectors);
}
+
+ /* use any remaining overlays as drm planes */
+ for (; i < omap_dss_get_num_overlays(); i++) {
+ struct omap_overlay *ovl = omap_dss_get_overlay(i);
+ create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
+ }
}
/* for now keep the mapping of CRTCs and encoders static.. */
@@ -361,15 +382,7 @@ static int omap_modeset_init(struct drm_device *dev)
struct omap_overlay_manager *mgr =
omap_encoder_get_manager(encoder);
- encoder->possible_crtcs = 0;
-
- for (j = 0; j < priv->num_crtcs; j++) {
- struct omap_overlay *ovl =
- omap_crtc_get_overlay(priv->crtcs[j]);
- if (ovl->manager == mgr) {
- encoder->possible_crtcs |= (1 << j);
- }
- }
+ encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
DBG("%s: possible_crtcs=%08x", mgr->name,
encoder->possible_crtcs);
@@ -377,8 +390,8 @@ static int omap_modeset_init(struct drm_device *dev)
dump_video_chains();
- dev->mode_config.min_width = 256;
- dev->mode_config.min_height = 256;
+ dev->mode_config.min_width = 32;
+ dev->mode_config.min_height = 32;
/* note: eventually will need some cpu_is_omapXYZ() type stuff here
* to fill in these limits properly on different OMAP generations..
@@ -708,6 +721,18 @@ static struct vm_operations_struct omap_gem_vm_ops = {
.close = drm_gem_vm_close,
};
+static const struct file_operations omapdriver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .unlocked_ioctl = drm_ioctl,
+ .release = drm_release,
+ .mmap = omap_gem_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ .read = drm_read,
+ .llseek = noop_llseek,
+};
+
static struct drm_driver omap_drm_driver = {
.driver_features =
DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM,
@@ -738,17 +763,7 @@ static struct drm_driver omap_drm_driver = {
.dumb_destroy = omap_gem_dumb_destroy,
.ioctls = ioctls,
.num_ioctls = DRM_OMAP_NUM_IOCTLS,
- .fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .unlocked_ioctl = drm_ioctl,
- .release = drm_release,
- .mmap = omap_gem_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
- .llseek = noop_llseek,
- },
+ .fops = &omapdriver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index 76c42515ecc5..61fe022dda5b 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
#include "omap_drm.h"
#include "omap_priv.h"
@@ -41,6 +42,8 @@
struct omap_drm_private {
unsigned int num_crtcs;
struct drm_crtc *crtcs[8];
+ unsigned int num_planes;
+ struct drm_plane *planes[8];
unsigned int num_encoders;
struct drm_encoder *encoders[8];
unsigned int num_connectors;
@@ -61,7 +64,17 @@ void omap_fbdev_free(struct drm_device *dev);
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct omap_overlay *ovl, int id);
-struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc);
+
+struct drm_plane *omap_plane_init(struct drm_device *dev,
+ struct omap_overlay *ovl, unsigned int possible_crtcs,
+ bool priv);
+int omap_plane_dpms(struct drm_plane *plane, int mode);
+int omap_plane_mode_set(struct drm_plane *plane,
+ struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h);
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_overlay_manager *mgr);
@@ -80,12 +93,14 @@ void omap_connector_flush(struct drm_connector *connector,
int x, int y, int w, int h);
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd);
+ struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo);
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb);
-int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
- void **vaddr, dma_addr_t *paddr, unsigned int *screen_width);
+ struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
+int omap_framebuffer_pin(struct drm_framebuffer *fb);
+void omap_framebuffer_unpin(struct drm_framebuffer *fb);
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
+ struct omap_overlay_info *info);
struct drm_connector *omap_framebuffer_get_next_connector(
struct drm_framebuffer *fb, struct drm_connector *from);
void omap_framebuffer_flush(struct drm_framebuffer *fb,
@@ -132,4 +147,29 @@ static inline int align_pitch(int pitch, int width, int bpp)
return ALIGN(pitch, 8 * bytespp);
}
+/* should these be made into common util helpers?
+ */
+
+static inline int objects_lookup(struct drm_device *dev,
+ struct drm_file *filp, uint32_t pixel_format,
+ struct drm_gem_object **bos, uint32_t *handles)
+{
+ int i, n = drm_format_num_planes(pixel_format);
+
+ for (i = 0; i < n; i++) {
+ bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
+ if (!bos[i]) {
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ while (--i > 0) {
+ drm_gem_object_unreference_unlocked(bos[i]);
+ }
+ return -ENOENT;
+}
+
#endif /* __OMAP_DRV_H__ */
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 0b50c5b3b564..d021a7ec58df 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -22,18 +22,57 @@
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
-
/*
* framebuffer funcs
*/
+/* per-format info: */
+struct format {
+ enum omap_color_mode dss_format;
+ uint32_t pixel_format;
+ struct {
+ int stride_bpp; /* this times width is stride */
+ int sub_y; /* sub-sample in y dimension */
+ } planes[4];
+ bool yuv;
+};
+
+static const struct format formats[] = {
+ /* 16bpp [A]RGB: */
+ { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565, {{2, 1}}, false }, /* RGB16-565 */
+ { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */
+ { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */
+ { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */
+ { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */
+ { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */
+ { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */
+ /* 24bpp RGB: */
+ { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888, {{3, 1}}, false }, /* RGB24-888 */
+ /* 32bpp [A]RGB: */
+ { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */
+ { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */
+ { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */
+ { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */
+ /* YUV: */
+ { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12, {{1, 1}, {1, 2}}, true },
+ { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV, {{2, 1}}, true },
+ { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY, {{2, 1}}, true },
+};
+
+/* per-plane info for the fb: */
+struct plane {
+ struct drm_gem_object *bo;
+ uint32_t pitch;
+ uint32_t offset;
+ dma_addr_t paddr;
+};
+
#define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
struct omap_framebuffer {
struct drm_framebuffer base;
- struct drm_gem_object *bo;
- int size;
- dma_addr_t paddr;
+ const struct format *format;
+ struct plane planes[4];
};
static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
@@ -41,22 +80,23 @@ static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
unsigned int *handle)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- return drm_gem_handle_create(file_priv, omap_fb->bo, handle);
+ return drm_gem_handle_create(file_priv,
+ omap_fb->planes[0].bo, handle);
}
static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
{
- struct drm_device *dev = fb->dev;
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
drm_framebuffer_cleanup(fb);
- if (omap_fb->bo) {
- if (omap_fb->paddr && omap_gem_put_paddr(omap_fb->bo))
- dev_err(dev->dev, "could not unmap!\n");
- drm_gem_object_unreference_unlocked(omap_fb->bo);
+ for (i = 0; i < n; i++) {
+ struct plane *plane = &omap_fb->planes[i];
+ if (plane->bo)
+ drm_gem_object_unreference_unlocked(plane->bo);
}
kfree(omap_fb);
@@ -83,37 +123,76 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
.dirty = omap_framebuffer_dirty,
};
-/* returns the buffer size */
-int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
- void **vaddr, dma_addr_t *paddr, unsigned int *screen_width)
+/* pins buffer in preparation for scanout */
+int omap_framebuffer_pin(struct drm_framebuffer *fb)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- int bpp = fb->bits_per_pixel / 8;
- unsigned long offset;
+ int ret, i, n = drm_format_num_planes(omap_fb->format->pixel_format);
- offset = (x * bpp) + (y * fb->pitch);
+ for (i = 0; i < n; i++) {
+ struct plane *plane = &omap_fb->planes[i];
+ ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
+ if (ret)
+ goto fail;
+ }
- if (vaddr) {
- void *bo_vaddr = omap_gem_vaddr(omap_fb->bo);
- /* note: we can only count on having a vaddr for buffers that
- * are allocated physically contiguously to begin with (ie.
- * dma_alloc_coherent()). But this should be ok because it
- * is only used by legacy fbdev
- */
- BUG_ON(IS_ERR_OR_NULL(bo_vaddr));
- *vaddr = bo_vaddr + offset;
+ return 0;
+
+fail:
+ while (--i > 0) {
+ struct plane *plane = &omap_fb->planes[i];
+ omap_gem_put_paddr(plane->bo);
}
+ return ret;
+}
- *paddr = omap_fb->paddr + offset;
- *screen_width = fb->pitch / bpp;
+/* releases buffer when done with scanout */
+void omap_framebuffer_unpin(struct drm_framebuffer *fb)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
- return omap_fb->size - offset;
+ for (i = 0; i < n; i++) {
+ struct plane *plane = &omap_fb->planes[i];
+ omap_gem_put_paddr(plane->bo);
+ }
}
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb)
+/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
+ */
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
+ struct omap_overlay_info *info)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- return omap_fb->bo;
+ const struct format *format = omap_fb->format;
+ struct plane *plane = &omap_fb->planes[0];
+ unsigned int offset;
+
+ offset = plane->offset +
+ (x * format->planes[0].stride_bpp) +
+ (y * plane->pitch / format->planes[0].sub_y);
+
+ info->color_mode = format->dss_format;
+ info->paddr = plane->paddr + offset;
+ info->screen_width = plane->pitch / format->planes[0].stride_bpp;
+
+ if (format->dss_format == OMAP_DSS_COLOR_NV12) {
+ plane = &omap_fb->planes[1];
+ offset = plane->offset +
+ (x * format->planes[1].stride_bpp) +
+ (y * plane->pitch / format->planes[1].sub_y);
+ info->p_uv_addr = plane->paddr + offset;
+ } else {
+ info->p_uv_addr = 0;
+ }
+}
+
+struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ if (p >= drm_format_num_planes(omap_fb->format->pixel_format))
+ return NULL;
+ return omap_fb->planes[p].bo;
}
/* iterate thru all the connectors, returning ones that are attached
@@ -171,39 +250,57 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
}
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd)
+ struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
{
- struct drm_gem_object *bo;
+ struct drm_gem_object *bos[4];
struct drm_framebuffer *fb;
- bo = drm_gem_object_lookup(dev, file, mode_cmd->handle);
- if (!bo) {
- return ERR_PTR(-ENOENT);
- }
- fb = omap_framebuffer_init(dev, mode_cmd, bo);
- if (!fb) {
- return ERR_PTR(-ENOMEM);
+ int ret;
+
+ ret = objects_lookup(dev, file, mode_cmd->pixel_format,
+ bos, mode_cmd->handles);
+ if (ret)
+ return ERR_PTR(ret);
+
+ fb = omap_framebuffer_init(dev, mode_cmd, bos);
+ if (IS_ERR(fb)) {
+ int i, n = drm_format_num_planes(mode_cmd->pixel_format);
+ for (i = 0; i < n; i++)
+ drm_gem_object_unreference_unlocked(bos[i]);
+ return fb;
}
return fb;
}
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo)
+ struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
struct omap_framebuffer *omap_fb;
struct drm_framebuffer *fb = NULL;
- int size, ret;
+ const struct format *format = NULL;
+ int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
- DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)",
+ DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
dev, mode_cmd, mode_cmd->width, mode_cmd->height,
- mode_cmd->bpp);
+ (char *)&mode_cmd->pixel_format);
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].pixel_format == mode_cmd->pixel_format) {
+ format = &formats[i];
+ break;
+ }
+ }
- /* in case someone tries to feed us a completely bogus stride: */
- mode_cmd->pitch = align_pitch(mode_cmd->pitch,
- mode_cmd->width, mode_cmd->bpp);
+ if (!format) {
+ dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
+ (char *)&mode_cmd->pixel_format);
+ ret = -EINVAL;
+ goto fail;
+ }
omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
if (!omap_fb) {
dev_err(dev->dev, "could not allocate fb\n");
+ ret = -ENOMEM;
goto fail;
}
@@ -216,19 +313,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
DBG("create: FB ID: %d (%p)", fb->base.id, fb);
- size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height);
+ omap_fb->format = format;
- if (size > bo->size) {
- dev_err(dev->dev, "provided buffer object is too small!\n");
- goto fail;
- }
+ for (i = 0; i < n; i++) {
+ struct plane *plane = &omap_fb->planes[i];
+ int size, pitch = mode_cmd->pitches[i];
+
+ if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
+ dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
+ pitch, mode_cmd->width * format->planes[i].stride_bpp);
+ ret = -EINVAL;
+ goto fail;
+ }
- omap_fb->bo = bo;
- omap_fb->size = size;
+ size = pitch * mode_cmd->height / format->planes[i].sub_y;
- if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) {
- dev_err(dev->dev, "could not map (paddr)!\n");
- goto fail;
+ if (size > (bos[i]->size - mode_cmd->offsets[i])) {
+ dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
+ bos[i]->size - mode_cmd->offsets[i], size);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ plane->bo = bos[i];
+ plane->offset = mode_cmd->offsets[i];
+ plane->pitch = mode_cmd->pitches[i];
+ plane->paddr = pitch;
}
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
@@ -239,5 +349,5 @@ fail:
if (fb) {
omap_framebuffer_destroy(fb);
}
- return NULL;
+ return ERR_PTR(ret);
}
diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c
index 093ae2f87b20..96940bbfc6f4 100644
--- a/drivers/staging/omapdrm/omap_fbdev.c
+++ b/drivers/staging/omapdrm/omap_fbdev.c
@@ -129,10 +129,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
struct drm_framebuffer *fb = NULL;
union omap_gem_size gsize;
struct fb_info *fbi = NULL;
- struct drm_mode_fb_cmd mode_cmd = {0};
+ struct drm_mode_fb_cmd2 mode_cmd = {0};
dma_addr_t paddr;
- void __iomem *vaddr;
- int size, screen_width;
int ret;
/* only doing ARGB32 since this is what is needed to alpha-blend
@@ -145,36 +143,56 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
sizes->surface_height, sizes->surface_bpp,
sizes->fb_width, sizes->fb_height);
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+ sizes->surface_depth);
+
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
- mode_cmd.bpp = sizes->surface_bpp;
- mode_cmd.depth = sizes->surface_depth;
-
- mode_cmd.pitch = align_pitch(
- mode_cmd.width * ((mode_cmd.bpp + 7) / 8),
- mode_cmd.width, mode_cmd.bpp);
+ mode_cmd.pitches[0] = align_pitch(
+ mode_cmd.width * ((sizes->surface_bpp + 7) / 8),
+ mode_cmd.width, sizes->surface_bpp);
fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;
if (fbdev->ywrap_enabled) {
/* need to align pitch to page size if using DMM scrolling */
- mode_cmd.pitch = ALIGN(mode_cmd.pitch, PAGE_SIZE);
+ mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE);
}
/* allocate backing bo */
gsize = (union omap_gem_size){
- .bytes = PAGE_ALIGN(mode_cmd.pitch * mode_cmd.height),
+ .bytes = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height),
};
DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);
fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
if (!fbdev->bo) {
dev_err(dev->dev, "failed to allocate buffer object\n");
+ ret = -ENOMEM;
goto fail;
}
- fb = omap_framebuffer_init(dev, &mode_cmd, fbdev->bo);
- if (!fb) {
+ fb = omap_framebuffer_init(dev, &mode_cmd, &fbdev->bo);
+ if (IS_ERR(fb)) {
dev_err(dev->dev, "failed to allocate fb\n");
+ /* note: if fb creation failed, we can't rely on fb destroy
+ * to unref the bo:
+ */
+ drm_gem_object_unreference(fbdev->bo);
+ ret = PTR_ERR(fb);
+ goto fail;
+ }
+
+ /* note: this keeps the bo pinned.. which is perhaps not ideal,
+ * but is needed as long as we use fb_mmap() to mmap to userspace
+ * (since this happens using fix.smem_start). Possibly we could
+ * implement our own mmap using GEM mmap support to avoid this
+ * (non-tiled buffer doesn't need to be pinned for fbcon to write
+ * to it). Then we just need to be sure that we are able to re-
+ * pin it in case of an opps.
+ */
+ ret = omap_gem_get_paddr(fbdev->bo, &paddr, true);
+ if (ret) {
+ dev_err(dev->dev, "could not map (paddr)!\n");
ret = -ENOMEM;
goto fail;
}
@@ -206,18 +224,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
goto fail_unlock;
}
- drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+ drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
- size = omap_framebuffer_get_buffer(fb, 0, 0,
- &vaddr, &paddr, &screen_width);
-
dev->mode_config.fb_base = paddr;
- fbi->screen_base = vaddr;
- fbi->screen_size = size;
+ fbi->screen_base = omap_gem_vaddr(fbdev->bo);
+ fbi->screen_size = fbdev->bo->size;
fbi->fix.smem_start = paddr;
- fbi->fix.smem_len = size;
+ fbi->fix.smem_len = fbdev->bo->size;
/* if we have DMM, then we can use it for scrolling by just
* shuffling pages around in DMM rather than doing sw blit.
@@ -362,11 +377,11 @@ void omap_fbdev_free(struct drm_device *dev)
fbdev = to_omap_fbdev(priv->fbdev);
- kfree(fbdev);
-
/* this will free the backing object */
if (fbdev->fb)
fbdev->fb->funcs->destroy(fbdev->fb);
+ kfree(fbdev);
+
priv->fbdev = NULL;
}
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index e0ebd1d139f6..b7d6f886c5cf 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -116,6 +116,9 @@ struct omap_gem_object {
} *sync;
};
+static int get_pages(struct drm_gem_object *obj, struct page ***pages);
+static uint64_t mmap_offset(struct drm_gem_object *obj);
+
/* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are
* not necessarily pinned in TILER all the time, and (b) when they are
* they are not necessarily page aligned, we reserve one or more small
@@ -149,7 +152,7 @@ static void evict_entry(struct drm_gem_object *obj,
{
if (obj->dev->dev_mapping) {
size_t size = PAGE_SIZE * usergart[fmt].height;
- loff_t off = omap_gem_mmap_offset(obj) +
+ loff_t off = mmap_offset(obj) +
(entry->obj_pgoff << PAGE_SHIFT);
unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
}
@@ -189,8 +192,6 @@ static inline bool is_shmem(struct drm_gem_object *obj)
return obj->filp != NULL;
}
-static int get_pages(struct drm_gem_object *obj, struct page ***pages);
-
static DEFINE_SPINLOCK(sync_lock);
/** ensure backing pages are allocated */
@@ -251,7 +252,7 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
}
/** get mmap offset */
-uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
+static uint64_t mmap_offset(struct drm_gem_object *obj)
{
if (!obj->map_list.map) {
/* Make it mmapable */
@@ -267,6 +268,15 @@ uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
}
+uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
+{
+ uint64_t offset;
+ mutex_lock(&obj->dev->struct_mutex);
+ offset = mmap_offset(obj);
+ mutex_unlock(&obj->dev->struct_mutex);
+ return offset;
+}
+
/** get mmap size */
size_t omap_gem_mmap_size(struct drm_gem_object *obj)
{
@@ -1034,6 +1044,11 @@ void omap_gem_free_object(struct drm_gem_object *obj)
drm_gem_free_mmap_offset(obj);
}
+ /* this means the object is still pinned.. which really should
+ * not happen. I think..
+ */
+ WARN_ON(omap_obj->paddr_cnt > 0);
+
/* don't free externally allocated backing memory */
if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {
if (omap_obj->pages) {
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
new file mode 100644
index 000000000000..97909124a1fe
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -0,0 +1,344 @@
+/*
+ * drivers/staging/omapdrm/omap_plane.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+/* some hackery because omapdss has an 'enum omap_plane' (which would be
+ * better named omap_plane_id).. and compiler seems unhappy about having
+ * both a 'struct omap_plane' and 'enum omap_plane'
+ */
+#define omap_plane _omap_plane
+
+/*
+ * plane funcs
+ */
+
+#define to_omap_plane(x) container_of(x, struct omap_plane, base)
+
+struct omap_plane {
+ struct drm_plane base;
+ struct omap_overlay *ovl;
+ struct omap_overlay_info info;
+
+ /* Source values, converted to integers because we don't support
+ * fractional positions:
+ */
+ unsigned int src_x, src_y;
+
+ /* last fb that we pinned: */
+ struct drm_framebuffer *pinned_fb;
+};
+
+
+/* push changes down to dss2 */
+static int commit(struct drm_plane *plane)
+{
+ struct drm_device *dev = plane->dev;
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_overlay *ovl = omap_plane->ovl;
+ struct omap_overlay_info *info = &omap_plane->info;
+ int ret;
+
+ DBG("%s", ovl->name);
+ DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
+ info->out_height, info->screen_width);
+ DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
+ info->paddr, info->p_uv_addr);
+
+ /* NOTE: do we want to do this at all here, or just wait
+ * for dpms(ON) since other CRTC's may not have their mode
+ * set yet, so fb dimensions may still change..
+ */
+ ret = ovl->set_overlay_info(ovl, info);
+ if (ret) {
+ dev_err(dev->dev, "could not set overlay info\n");
+ return ret;
+ }
+
+ /* our encoder doesn't necessarily get a commit() after this, in
+ * particular in the dpms() and mode_set_base() cases, so force the
+ * manager to update:
+ *
+ * could this be in the encoder somehow?
+ */
+ if (ovl->manager) {
+ ret = ovl->manager->apply(ovl->manager);
+ if (ret) {
+ dev_err(dev->dev, "could not apply settings\n");
+ return ret;
+ }
+ }
+
+ if (ovl->is_enabled(ovl)) {
+ omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
+ info->out_width, info->out_height);
+ }
+
+ return 0;
+}
+
+/* when CRTC that we are attached to has potentially changed, this checks
+ * if we are attached to proper manager, and if necessary updates.
+ */
+static void update_manager(struct drm_plane *plane)
+{
+ struct omap_drm_private *priv = plane->dev->dev_private;
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_overlay *ovl = omap_plane->ovl;
+ struct omap_overlay_manager *mgr = NULL;
+ int i;
+
+ if (plane->crtc) {
+ for (i = 0; i < priv->num_encoders; i++) {
+ struct drm_encoder *encoder = priv->encoders[i];
+ if (encoder->crtc == plane->crtc) {
+ mgr = omap_encoder_get_manager(encoder);
+ break;
+ }
+ }
+ }
+
+ if (ovl->manager != mgr) {
+ bool enabled = ovl->is_enabled(ovl);
+
+ /* don't switch things around with enabled overlays: */
+ if (enabled)
+ omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+
+ if (ovl->manager) {
+ DBG("disconnecting %s from %s", ovl->name,
+ ovl->manager->name);
+ ovl->unset_manager(ovl);
+ }
+
+ if (mgr) {
+ DBG("connecting %s to %s", ovl->name, mgr->name);
+ ovl->set_manager(ovl, mgr);
+ }
+
+ if (enabled && mgr)
+ omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+ }
+}
+
+/* update which fb (if any) is pinned for scanout */
+static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ int ret = 0;
+
+ if (omap_plane->pinned_fb != fb) {
+ if (omap_plane->pinned_fb)
+ omap_framebuffer_unpin(omap_plane->pinned_fb);
+ omap_plane->pinned_fb = fb;
+ if (fb)
+ ret = omap_framebuffer_pin(fb);
+ }
+
+ return ret;
+}
+
+/* update parameters that are dependent on the framebuffer dimensions and
+ * position within the fb that this plane scans out from. This is called
+ * when framebuffer or x,y base may have changed.
+ */
+static void update_scanout(struct drm_plane *plane)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_overlay_info *info = &omap_plane->info;
+ int ret;
+
+ ret = update_pin(plane, plane->fb);
+ if (ret) {
+ dev_err(plane->dev->dev,
+ "could not pin fb: %d\n", ret);
+ omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+ return;
+ }
+
+ omap_framebuffer_update_scanout(plane->fb,
+ omap_plane->src_x, omap_plane->src_y, info);
+
+ DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name,
+ omap_plane->src_x, omap_plane->src_y,
+ (u32)info->paddr, (u32)info->p_uv_addr,
+ info->screen_width);
+}
+
+int omap_plane_mode_set(struct drm_plane *plane,
+ struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+
+ /* src values are in Q16 fixed point, convert to integer: */
+ src_x = src_x >> 16;
+ src_y = src_y >> 16;
+ src_w = src_w >> 16;
+ src_h = src_h >> 16;
+
+ omap_plane->info.pos_x = crtc_x;
+ omap_plane->info.pos_y = crtc_y;
+ omap_plane->info.out_width = crtc_w;
+ omap_plane->info.out_height = crtc_h;
+ omap_plane->info.width = src_w;
+ omap_plane->info.height = src_h;
+ omap_plane->src_x = src_x;
+ omap_plane->src_y = src_y;
+
+ /* note: this is done after this fxn returns.. but if we need
+ * to do a commit/update_scanout, etc before this returns we
+ * need the current value.
+ */
+ plane->fb = fb;
+ plane->crtc = crtc;
+
+ update_scanout(plane);
+ update_manager(plane);
+
+ return 0;
+}
+
+static int omap_plane_update(struct drm_plane *plane,
+ struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h,
+ src_x, src_y, src_w, src_h);
+ return omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+}
+
+static int omap_plane_disable(struct drm_plane *plane)
+{
+ return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+}
+
+static void omap_plane_destroy(struct drm_plane *plane)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ DBG("%s", omap_plane->ovl->name);
+ omap_plane_disable(plane);
+ drm_plane_cleanup(plane);
+ kfree(omap_plane);
+}
+
+int omap_plane_dpms(struct drm_plane *plane, int mode)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_overlay *ovl = omap_plane->ovl;
+ int r;
+
+ DBG("%s: %d", omap_plane->ovl->name, mode);
+
+ if (mode == DRM_MODE_DPMS_ON) {
+ update_scanout(plane);
+ r = commit(plane);
+ if (!r)
+ r = ovl->enable(ovl);
+ } else {
+ r = ovl->disable(ovl);
+ update_pin(plane, NULL);
+ }
+
+ return r;
+}
+
+static const struct drm_plane_funcs omap_plane_funcs = {
+ .update_plane = omap_plane_update,
+ .disable_plane = omap_plane_disable,
+ .destroy = omap_plane_destroy,
+};
+
+static const uint32_t formats[] = {
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_RGBX4444,
+ DRM_FORMAT_XRGB4444,
+ DRM_FORMAT_RGBA4444,
+ DRM_FORMAT_ABGR4444,
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_UYVY,
+};
+
+/* initialize plane */
+struct drm_plane *omap_plane_init(struct drm_device *dev,
+ struct omap_overlay *ovl, unsigned int possible_crtcs,
+ bool priv)
+{
+ struct drm_plane *plane = NULL;
+ struct omap_plane *omap_plane;
+
+ DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name,
+ possible_crtcs, priv);
+
+ omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
+ if (!omap_plane) {
+ dev_err(dev->dev, "could not allocate plane\n");
+ goto fail;
+ }
+
+ omap_plane->ovl = ovl;
+ plane = &omap_plane->base;
+
+ drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
+ formats, ARRAY_SIZE(formats), priv);
+
+ /* get our starting configuration, set defaults for parameters
+ * we don't currently use, etc:
+ */
+ ovl->get_overlay_info(ovl, &omap_plane->info);
+ omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA;
+ omap_plane->info.rotation = OMAP_DSS_ROT_0;
+ omap_plane->info.global_alpha = 0xff;
+ omap_plane->info.mirror = 0;
+ omap_plane->info.mirror = 0;
+
+ /* Set defaults depending on whether we are a CRTC or overlay
+ * layer.
+ * TODO add ioctl to give userspace an API to change this.. this
+ * will come in a subsequent patch.
+ */
+ if (priv)
+ omap_plane->info.zorder = 0;
+ else
+ omap_plane->info.zorder = 1;
+
+ update_manager(plane);
+
+ return plane;
+
+fail:
+ if (plane) {
+ omap_plane_destroy(plane);
+ }
+ return NULL;
+}
diff --git a/drivers/staging/omapdrm/omap_priv.h b/drivers/staging/omapdrm/omap_priv.h
index c324709aa9a1..ef6441447147 100644
--- a/drivers/staging/omapdrm/omap_priv.h
+++ b/drivers/staging/omapdrm/omap_priv.h
@@ -27,14 +27,22 @@
* pipes/overlays/CRTCs are used.. if this is not provided, then instead the
* first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
* one manager, with priority given to managers that are connected to
- * detected devices. This should be a good default behavior for most cases,
- * but yet there still might be times when you wish to do something different.
+ * detected devices. Remaining overlays are used as video planes. This
+ * should be a good default behavior for most cases, but yet there still
+ * might be times when you wish to do something different.
*/
struct omap_kms_platform_data {
+ /* overlays to use as CRTCs: */
int ovl_cnt;
const int *ovl_ids;
+
+ /* overlays to use as video planes: */
+ int pln_cnt;
+ const int *pln_ids;
+
int mgr_cnt;
const int *mgr_ids;
+
int dev_cnt;
const char **dev_names;
};
diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig
deleted file mode 100644
index 8d53b1a1e715..000000000000
--- a/drivers/staging/pohmelfs/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-config POHMELFS
- tristate "POHMELFS filesystem support"
- depends on NET
- select CONNECTOR
- select CRYPTO
- select CRYPTO_BLKCIPHER
- select CRYPTO_HMAC
- help
- POHMELFS stands for Parallel Optimized Host Message Exchange Layered
- File System. This is a network filesystem which supports coherent
- caching of data and metadata on clients.
-
-config POHMELFS_DEBUG
- bool "POHMELFS debugging"
- depends on POHMELFS
- default n
- help
- Turns on excessive POHMELFS debugging facilities.
- You usually do not want to slow things down noticeably and get really
- lots of kernel messages in syslog.
diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile
deleted file mode 100644
index 196561ca26bc..000000000000
--- a/drivers/staging/pohmelfs/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_POHMELFS) += pohmelfs.o
-
-pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
deleted file mode 100644
index b6c42cb0d1c6..000000000000
--- a/drivers/staging/pohmelfs/config.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/kernel.h>
-#include <linux/connector.h>
-#include <linux/crypto.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-/*
- * Global configuration list.
- * Each client can be asked to get one of them.
- *
- * Allows to provide remote server address (ipv4/v6/whatever), port
- * and so on via kernel connector.
- */
-
-static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL};
-static LIST_HEAD(pohmelfs_config_list);
-static DEFINE_MUTEX(pohmelfs_config_lock);
-
-static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl)
-{
- if (sc->idx == ctl->idx && sc->type == ctl->type &&
- sc->proto == ctl->proto &&
- sc->addrlen == ctl->addrlen &&
- !memcmp(&sc->addr, &ctl->addr, ctl->addrlen))
- return 1;
-
- return 0;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx)
-{
- struct pohmelfs_config_group *g, *group = NULL;
-
- list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
- if (g->idx == idx) {
- group = g;
- break;
- }
- }
-
- return group;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx)
-{
- struct pohmelfs_config_group *g;
-
- g = pohmelfs_find_config_group(idx);
- if (g)
- return g;
-
- g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL);
- if (!g)
- return NULL;
-
- INIT_LIST_HEAD(&g->config_list);
- g->idx = idx;
- g->num_entry = 0;
-
- list_add_tail(&g->group_entry, &pohmelfs_config_list);
-
- return g;
-}
-
-static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst)
-{
- struct pohmelfs_config *tmp;
-
- INIT_LIST_HEAD(&dst->config_entry);
-
- list_for_each_entry(tmp, &psb->state_list, config_entry) {
- if (dst->state.ctl.prio > tmp->state.ctl.prio)
- list_add_tail(&dst->config_entry, &tmp->config_entry);
- }
- if (list_empty(&dst->config_entry))
- list_add_tail(&dst->config_entry, &psb->state_list);
-}
-
-static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb,
- struct pohmelfs_config *dst, struct pohmelfs_config *new)
-{
- if ((dst->state.ctl.prio == new->state.ctl.prio) &&
- (dst->state.ctl.perm == new->state.ctl.perm))
- return 0;
-
- dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n",
- __func__, dst->state.ctl.prio, dst->state.ctl.perm,
- new->state.ctl.prio, new->state.ctl.perm);
- dst->state.ctl.prio = new->state.ctl.prio;
- dst->state.ctl.perm = new->state.ctl.perm;
-
- list_del_init(&dst->config_entry);
- pohmelfs_insert_config_entry(psb, dst);
- return 0;
-}
-
-/*
- * pohmelfs_copy_config() is used to copy new state configs from the
- * config group (controlled by the netlink messages) into the superblock.
- * This happens either at startup time where no transactions can access
- * the list of the configs (and thus list of the network states), or at
- * run-time, where it is protected by the psb->state_lock.
- */
-int pohmelfs_copy_config(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config_group *g;
- struct pohmelfs_config *c, *dst;
- int err = -ENODEV;
-
- mutex_lock(&pohmelfs_config_lock);
-
- g = pohmelfs_find_config_group(psb->idx);
- if (!g)
- goto out_unlock;
-
- /*
- * Run over all entries in given config group and try to create and
- * initialize those, which do not exist in superblock list.
- * Skip all existing entries.
- */
-
- list_for_each_entry(c, &g->config_list, config_entry) {
- err = 0;
- list_for_each_entry(dst, &psb->state_list, config_entry) {
- if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) {
- err = pohmelfs_move_config_entry(psb, dst, c);
- if (!err)
- err = -EEXIST;
- break;
- }
- }
-
- if (err)
- continue;
-
- dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
- if (!dst) {
- err = -ENOMEM;
- break;
- }
-
- memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl));
-
- pohmelfs_insert_config_entry(psb, dst);
-
- err = pohmelfs_state_init_one(psb, dst);
- if (err) {
- list_del(&dst->config_entry);
- kfree(dst);
- }
-
- err = 0;
- }
-
-out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
-
- return err;
-}
-
-int pohmelfs_copy_crypto(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config_group *g;
- int err = -ENOENT;
-
- mutex_lock(&pohmelfs_config_lock);
- g = pohmelfs_find_config_group(psb->idx);
- if (!g)
- goto err_out_exit;
-
- if (g->hash_string) {
- err = -ENOMEM;
- psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL);
- if (!psb->hash_string)
- goto err_out_exit;
- psb->hash_strlen = g->hash_strlen;
- }
-
- if (g->cipher_string) {
- psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL);
- if (!psb->cipher_string)
- goto err_out_free_hash_string;
- psb->cipher_strlen = g->cipher_strlen;
- }
-
- if (g->hash_keysize) {
- psb->hash_key = kmemdup(g->hash_key, g->hash_keysize,
- GFP_KERNEL);
- if (!psb->hash_key)
- goto err_out_free_cipher_string;
- psb->hash_keysize = g->hash_keysize;
- }
-
- if (g->cipher_keysize) {
- psb->cipher_key = kmemdup(g->cipher_key, g->cipher_keysize,
- GFP_KERNEL);
- if (!psb->cipher_key)
- goto err_out_free_hash;
- psb->cipher_keysize = g->cipher_keysize;
- }
-
- mutex_unlock(&pohmelfs_config_lock);
-
- return 0;
-
-err_out_free_hash:
- kfree(psb->hash_key);
-err_out_free_cipher_string:
- kfree(psb->cipher_string);
-err_out_free_hash_string:
- kfree(psb->hash_string);
-err_out_exit:
- mutex_unlock(&pohmelfs_config_lock);
- return err;
-}
-
-static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl)
-{
- struct pohmelfs_cn_ack *ack;
-
- ack = kzalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL);
- if (!ack)
- return -ENOMEM;
-
- memcpy(&ack->msg, msg, sizeof(struct cn_msg));
-
- if (action == POHMELFS_CTLINFO_ACK)
- memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl));
-
- ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg);
- ack->msg.ack = msg->ack + 1;
- ack->error = err;
- ack->msg_num = msg_num;
-
- cn_netlink_send(&ack->msg, 0, GFP_KERNEL);
- kfree(ack);
- return 0;
-}
-
-static int pohmelfs_cn_disp(struct cn_msg *msg)
-{
- struct pohmelfs_config_group *g;
- struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
- struct pohmelfs_config *c, *tmp;
- int err = 0, i = 1;
-
- if (msg->len != sizeof(struct pohmelfs_ctl))
- return -EBADMSG;
-
- mutex_lock(&pohmelfs_config_lock);
-
- g = pohmelfs_find_config_group(ctl->idx);
- if (!g) {
- pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL);
- goto out_unlock;
- }
-
- list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
- struct pohmelfs_ctl *sc = &c->state.ctl;
- if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) {
- err = -ENOMEM;
- goto out_unlock;
- }
- i += 1;
- }
-
- out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
- return err;
-}
-
-static int pohmelfs_cn_dump(struct cn_msg *msg)
-{
- struct pohmelfs_config_group *g;
- struct pohmelfs_config *c, *tmp;
- int err = 0, i = 1;
- int total_msg = 0;
-
- if (msg->len != sizeof(struct pohmelfs_ctl))
- return -EBADMSG;
-
- mutex_lock(&pohmelfs_config_lock);
-
- list_for_each_entry(g, &pohmelfs_config_list, group_entry)
- total_msg += g->num_entry;
- if (total_msg == 0) {
- if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
- err = -ENOMEM;
- goto out_unlock;
- }
-
- list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
- list_for_each_entry_safe(c, tmp, &g->config_list,
- config_entry) {
- struct pohmelfs_ctl *sc = &c->state.ctl;
- if (pohmelfs_send_reply(err, total_msg - i,
- POHMELFS_CTLINFO_ACK, msg,
- sc)) {
- err = -ENOMEM;
- goto out_unlock;
- }
- i += 1;
- }
- }
-
-out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
- return err;
-}
-
-static int pohmelfs_cn_flush(struct cn_msg *msg)
-{
- struct pohmelfs_config_group *g;
- struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
- struct pohmelfs_config *c, *tmp;
- int err = 0;
-
- if (msg->len != sizeof(struct pohmelfs_ctl))
- return -EBADMSG;
-
- mutex_lock(&pohmelfs_config_lock);
-
- if (ctl->idx != POHMELFS_NULL_IDX) {
- g = pohmelfs_find_config_group(ctl->idx);
-
- if (!g)
- goto out_unlock;
-
- list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
- list_del(&c->config_entry);
- g->num_entry--;
- kfree(c);
- }
- } else {
- list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
- list_for_each_entry_safe(c, tmp, &g->config_list,
- config_entry) {
- list_del(&c->config_entry);
- g->num_entry--;
- kfree(c);
- }
- }
- }
-
-out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
- pohmelfs_cn_dump(msg);
-
- return err;
-}
-
-static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new)
-{
- old->perm = new->perm;
- old->prio = new->prio;
- return 0;
-}
-
-static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
-{
- struct pohmelfs_config_group *g;
- struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
- struct pohmelfs_config *c, *tmp;
- int err = 0;
-
- if (msg->len != sizeof(struct pohmelfs_ctl))
- return -EBADMSG;
-
- mutex_lock(&pohmelfs_config_lock);
-
- g = pohmelfs_find_create_config_group(ctl->idx);
- if (!g) {
- err = -ENOMEM;
- goto out_unlock;
- }
-
- list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
- struct pohmelfs_ctl *sc = &c->state.ctl;
-
- if (pohmelfs_config_eql(sc, ctl)) {
- if (action == POHMELFS_FLAGS_ADD) {
- err = -EEXIST;
- goto out_unlock;
- } else if (action == POHMELFS_FLAGS_DEL) {
- list_del(&c->config_entry);
- g->num_entry--;
- kfree(c);
- goto out_unlock;
- } else if (action == POHMELFS_FLAGS_MODIFY) {
- err = pohmelfs_modify_config(sc, ctl);
- goto out_unlock;
- } else {
- err = -EEXIST;
- goto out_unlock;
- }
- }
- }
- if (action == POHMELFS_FLAGS_DEL) {
- err = -EBADMSG;
- goto out_unlock;
- }
-
- c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
- if (!c) {
- err = -ENOMEM;
- goto out_unlock;
- }
- memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl));
- g->num_entry++;
-
- list_add_tail(&c->config_entry, &g->config_list);
-
- out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
- if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
- err = -ENOMEM;
-
- return err;
-}
-
-static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
- char *algo = (char *)c->data;
- u8 *key = (u8 *)(algo + c->strlen);
-
- if (g->hash_string)
- return -EEXIST;
-
- g->hash_string = kstrdup(algo, GFP_KERNEL);
- if (!g->hash_string)
- return -ENOMEM;
- g->hash_strlen = c->strlen;
- g->hash_keysize = c->keysize;
-
- g->hash_key = kmemdup(key, c->keysize, GFP_KERNEL);
- if (!g->hash_key) {
- kfree(g->hash_string);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
- char *algo = (char *)c->data;
- u8 *key = (u8 *)(algo + c->strlen);
-
- if (g->cipher_string)
- return -EEXIST;
-
- g->cipher_string = kstrdup(algo, GFP_KERNEL);
- if (!g->cipher_string)
- return -ENOMEM;
- g->cipher_strlen = c->strlen;
- g->cipher_keysize = c->keysize;
-
- g->cipher_key = kmemdup(key, c->keysize, GFP_KERNEL);
- if (!g->cipher_key) {
- kfree(g->cipher_string);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int pohmelfs_cn_crypto(struct cn_msg *msg)
-{
- struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data;
- struct pohmelfs_config_group *g;
- int err = 0;
-
- dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n",
- __func__, crypto->idx, crypto->strlen, crypto->type,
- crypto->keysize, (char *)crypto->data);
-
- mutex_lock(&pohmelfs_config_lock);
- g = pohmelfs_find_create_config_group(crypto->idx);
- if (!g) {
- err = -ENOMEM;
- goto out_unlock;
- }
-
- switch (crypto->type) {
- case POHMELFS_CRYPTO_HASH:
- err = pohmelfs_crypto_hash_init(g, crypto);
- break;
- case POHMELFS_CRYPTO_CIPHER:
- err = pohmelfs_crypto_cipher_init(g, crypto);
- break;
- default:
- err = -ENOTSUPP;
- break;
- }
-
-out_unlock:
- mutex_unlock(&pohmelfs_config_lock);
- if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
- err = -ENOMEM;
-
- return err;
-}
-
-static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
- int err;
-
- if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
- return;
-
- switch (msg->flags) {
- case POHMELFS_FLAGS_ADD:
- case POHMELFS_FLAGS_DEL:
- case POHMELFS_FLAGS_MODIFY:
- err = pohmelfs_cn_ctl(msg, msg->flags);
- break;
- case POHMELFS_FLAGS_FLUSH:
- err = pohmelfs_cn_flush(msg);
- break;
- case POHMELFS_FLAGS_SHOW:
- err = pohmelfs_cn_disp(msg);
- break;
- case POHMELFS_FLAGS_DUMP:
- err = pohmelfs_cn_dump(msg);
- break;
- case POHMELFS_FLAGS_CRYPTO:
- err = pohmelfs_cn_crypto(msg);
- break;
- default:
- err = -ENOSYS;
- break;
- }
-}
-
-int pohmelfs_config_check(struct pohmelfs_config *config, int idx)
-{
- struct pohmelfs_ctl *ctl = &config->state.ctl;
- struct pohmelfs_config *tmp;
- int err = -ENOENT;
- struct pohmelfs_ctl *sc;
- struct pohmelfs_config_group *g;
-
- mutex_lock(&pohmelfs_config_lock);
-
- g = pohmelfs_find_config_group(ctl->idx);
- if (g) {
- list_for_each_entry(tmp, &g->config_list, config_entry) {
- sc = &tmp->state.ctl;
-
- if (pohmelfs_config_eql(sc, ctl)) {
- err = 0;
- break;
- }
- }
- }
-
- mutex_unlock(&pohmelfs_config_lock);
-
- return err;
-}
-
-int __init pohmelfs_config_init(void)
-{
- /* XXX remove (void *) cast when vanilla connector got synced */
- return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", (void *)pohmelfs_cn_callback);
-}
-
-void pohmelfs_config_exit(void)
-{
- struct pohmelfs_config *c, *tmp;
- struct pohmelfs_config_group *g, *gtmp;
-
- cn_del_callback(&pohmelfs_cn_id);
-
- mutex_lock(&pohmelfs_config_lock);
- list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) {
- list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
- list_del(&c->config_entry);
- kfree(c);
- }
-
- list_del(&g->group_entry);
-
- kfree(g->hash_string);
-
- kfree(g->cipher_string);
-
- kfree(g);
- }
- mutex_unlock(&pohmelfs_config_lock);
-}
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
deleted file mode 100644
index ad92771dce57..000000000000
--- a/drivers/staging/pohmelfs/crypto.c
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/crypto.h>
-#include <linux/highmem.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb)
-{
- int err;
- struct crypto_hash *hash;
-
- hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(hash)) {
- err = PTR_ERR(hash);
- dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n",
- __func__, psb->idx, psb->hash_string, err);
- goto err_out_exit;
- }
-
- psb->crypto_attached_size = crypto_hash_digestsize(hash);
-
- if (!psb->hash_keysize)
- return hash;
-
- err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize);
- if (err) {
- dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n",
- __func__, psb->idx, psb->hash_string, err);
- goto err_out_free;
- }
-
- return hash;
-
-err_out_free:
- crypto_free_hash(hash);
-err_out_exit:
- return ERR_PTR(err);
-}
-
-static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb)
-{
- int err = -EINVAL;
- struct crypto_ablkcipher *cipher;
-
- if (!psb->cipher_keysize)
- goto err_out_exit;
-
- cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0);
- if (IS_ERR(cipher)) {
- err = PTR_ERR(cipher);
- dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n",
- __func__, psb->idx, psb->cipher_string, err);
- goto err_out_exit;
- }
-
- crypto_ablkcipher_clear_flags(cipher, ~0);
-
- err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize);
- if (err) {
- dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n",
- __func__, psb->idx, psb->cipher_string, err);
- goto err_out_free;
- }
-
- return cipher;
-
-err_out_free:
- crypto_free_ablkcipher(cipher);
-err_out_exit:
- return ERR_PTR(err);
-}
-
-int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
- int err;
-
- e->page_num = 0;
-
- e->size = PAGE_SIZE;
- e->data = kmalloc(e->size, GFP_KERNEL);
- if (!e->data) {
- err = -ENOMEM;
- goto err_out_exit;
- }
-
- if (psb->hash_string) {
- e->hash = pohmelfs_init_hash(psb);
- if (IS_ERR(e->hash)) {
- err = PTR_ERR(e->hash);
- e->hash = NULL;
- goto err_out_free;
- }
- }
-
- if (psb->cipher_string) {
- e->cipher = pohmelfs_init_cipher(psb);
- if (IS_ERR(e->cipher)) {
- err = PTR_ERR(e->cipher);
- e->cipher = NULL;
- goto err_out_free_hash;
- }
- }
-
- return 0;
-
-err_out_free_hash:
- crypto_free_hash(e->hash);
-err_out_free:
- kfree(e->data);
-err_out_exit:
- return err;
-}
-
-void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e)
-{
- crypto_free_hash(e->hash);
- crypto_free_ablkcipher(e->cipher);
- kfree(e->data);
-}
-
-static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err)
-{
- struct pohmelfs_crypto_completion *c = req->data;
-
- if (err == -EINPROGRESS)
- return;
-
- dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
- c->error = err;
- complete(&c->complete);
-}
-
-static int pohmelfs_crypto_process(struct ablkcipher_request *req,
- struct scatterlist *sg_dst, struct scatterlist *sg_src,
- void *iv, int enc, unsigned long timeout)
-{
- struct pohmelfs_crypto_completion complete;
- int err;
-
- init_completion(&complete.complete);
- complete.error = -EINPROGRESS;
-
- ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- pohmelfs_crypto_complete, &complete);
-
- ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
-
- if (enc)
- err = crypto_ablkcipher_encrypt(req);
- else
- err = crypto_ablkcipher_decrypt(req);
-
- switch (err) {
- case -EINPROGRESS:
- case -EBUSY:
- err = wait_for_completion_interruptible_timeout(&complete.complete,
- timeout);
- if (!err)
- err = -ETIMEDOUT;
- else if (err > 0)
- err = complete.error;
- break;
- default:
- break;
- }
-
- return err;
-}
-
-int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv,
- void *data, struct page *page, unsigned int size)
-{
- int err;
- struct scatterlist sg;
-
- if (!e->cipher && !e->hash)
- return 0;
-
- dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n",
- __func__, e, cmd_iv, data, page, (page) ? page->index : 0, size);
-
- if (data) {
- sg_init_one(&sg, data, size);
- } else {
- sg_init_table(&sg, 1);
- sg_set_page(&sg, page, size, 0);
- }
-
- if (e->cipher) {
- struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash);
- u8 iv[32];
-
- memset(iv, 0, sizeof(iv));
- memcpy(iv, &cmd_iv, sizeof(cmd_iv));
-
- ablkcipher_request_set_tfm(req, e->cipher);
-
- err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout);
- if (err)
- goto err_out_exit;
- }
-
- if (e->hash) {
- struct hash_desc desc;
- void *dst = e->data + e->size/2;
-
- desc.tfm = e->hash;
- desc.flags = 0;
-
- err = crypto_hash_init(&desc);
- if (err)
- goto err_out_exit;
-
- err = crypto_hash_update(&desc, &sg, size);
- if (err)
- goto err_out_exit;
-
- err = crypto_hash_final(&desc, dst);
- if (err)
- goto err_out_exit;
-
- err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash));
-
- if (err) {
-#ifdef CONFIG_POHMELFS_DEBUG
- unsigned int i;
- unsigned char *recv = e->data, *calc = dst;
-
- dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ",
- __func__, e, e->hash, e->cipher, cmd_iv);
- for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) {
-#if 0
- dprintka("%02x ", recv[i]);
- if (recv[i] != calc[i]) {
- dprintka("| calc byte: %02x.\n", calc[i]);
- break;
- }
-#else
- dprintka("%02x/%02x ", recv[i], calc[i]);
-#endif
- }
- dprintk("\n");
-#endif
- goto err_out_exit;
- } else {
- dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n",
- __func__, e, e->hash, e->cipher);
- }
- }
-
- dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n",
- __func__, e, e->size, e->hash, e->cipher);
-
- return 0;
-
-err_out_exit:
- dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n",
- __func__, e, e->hash, e->cipher, err);
- return err;
-}
-
-static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e,
- int (*iterator) (struct pohmelfs_crypto_engine *e,
- struct scatterlist *dst,
- struct scatterlist *src))
-{
- void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size;
- unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size;
- struct netfs_cmd *cmd = data;
- unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx;
- struct scatterlist sg_src, sg_dst;
- int err;
-
- while (size) {
- cmd = data;
- cmd_cmd = __be16_to_cpu(cmd->cmd);
- csize = __be32_to_cpu(cmd->size);
- cmd->iv = __cpu_to_be64(e->iv);
-
- if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE)
- csize = __be16_to_cpu(cmd->ext);
-
- sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd);
-
- dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n",
- __func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad));
-
- data += sz;
- size -= sz;
-
- sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd));
- sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd));
-
- err = iterator(e, &sg_dst, &sg_src);
- if (err)
- return err;
- }
-
- if (!pages)
- return 0;
-
- dpage_idx = 0;
- for (i = 0; i < t->page_num; ++i) {
- struct page *page = t->pages[i];
- struct page *dpage = e->pages[dpage_idx];
-
- if (!page)
- continue;
-
- sg_init_table(&sg_src, 1);
- sg_init_table(&sg_dst, 1);
- sg_set_page(&sg_src, page, page_private(page), 0);
- sg_set_page(&sg_dst, dpage, page_private(page), 0);
-
- err = iterator(e, &sg_dst, &sg_src);
- if (err)
- return err;
-
- pages--;
- if (!pages)
- break;
- dpage_idx++;
- }
-
- return 0;
-}
-
-static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e,
- struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
- struct ablkcipher_request *req = e->data;
- u8 iv[32];
-
- memset(iv, 0, sizeof(iv));
-
- memcpy(iv, &e->iv, sizeof(e->iv));
-
- return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout);
-}
-
-static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc)
-{
- struct netfs_trans *t = tc->trans;
- struct pohmelfs_crypto_engine *e = &tc->eng;
- struct ablkcipher_request *req = e->data;
-
- memset(req, 0, sizeof(struct ablkcipher_request));
- ablkcipher_request_set_tfm(req, e->cipher);
-
- e->iv = pohmelfs_gen_iv(t);
-
- return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator);
-}
-
-static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e,
- struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
- return crypto_hash_update(e->data, sg_src, sg_src->length);
-}
-
-static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc)
-{
- struct pohmelfs_crypto_engine *e = &tc->eng;
- struct hash_desc *desc = e->data;
- unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd);
- int err;
-
- desc->tfm = e->hash;
- desc->flags = 0;
-
- err = crypto_hash_init(desc);
- if (err)
- return err;
-
- err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator);
- if (err)
- return err;
-
- err = crypto_hash_final(desc, dst);
- if (err)
- return err;
-
- {
- unsigned int i;
- dprintk("%s: ", __func__);
- for (i = 0; i < tc->psb->crypto_attached_size; ++i)
- dprintka("%02x ", dst[i]);
- dprintka("\n");
- }
-
- return 0;
-}
-
-static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e)
-{
- unsigned int i;
-
- for (i = 0; i < e->page_num; ++i)
- __free_page(e->pages[i]);
- kfree(e->pages);
-}
-
-static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
- unsigned int i;
-
- e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL);
- if (!e->pages)
- return -ENOMEM;
-
- for (i = 0; i < psb->trans_max_pages; ++i) {
- e->pages[i] = alloc_page(GFP_KERNEL);
- if (!e->pages[i])
- break;
- }
-
- e->page_num = i;
- if (!e->page_num)
- goto err_out_free;
-
- return 0;
-
-err_out_free:
- kfree(e->pages);
- return -ENOMEM;
-}
-
-static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t)
-{
- struct pohmelfs_sb *psb = t->psb;
-
- if (t->thread)
- kthread_stop(t->thread);
-
- mutex_lock(&psb->crypto_thread_lock);
- list_del(&t->thread_entry);
- psb->crypto_thread_num--;
- mutex_unlock(&psb->crypto_thread_lock);
-
- pohmelfs_crypto_engine_exit(&t->eng);
- pohmelfs_crypto_pages_free(&t->eng);
- kfree(t);
-}
-
-static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err)
-{
- struct netfs_cmd *cmd = t->iovec.iov_base;
- netfs_convert_cmd(cmd);
-
- if (likely(!err))
- err = netfs_trans_finish_send(t, psb);
-
- t->result = err;
- netfs_trans_put(t);
-
- return err;
-}
-
-void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th)
-{
- struct pohmelfs_sb *psb = th->psb;
-
- th->page = NULL;
- th->trans = NULL;
-
- mutex_lock(&psb->crypto_thread_lock);
- list_move_tail(&th->thread_entry, &psb->crypto_ready_list);
- mutex_unlock(&psb->crypto_thread_lock);
- wake_up(&psb->wait);
-}
-
-static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t)
-{
- struct netfs_trans *trans;
- int err = 0;
-
- trans = t->trans;
- trans->eng = NULL;
-
- if (t->eng.hash) {
- err = pohmelfs_hash(t);
- if (err)
- goto out_complete;
- }
-
- if (t->eng.cipher) {
- err = pohmelfs_encrypt(t);
- if (err)
- goto out_complete;
- trans->eng = &t->eng;
- }
-
-out_complete:
- t->page = NULL;
- t->trans = NULL;
-
- if (!trans->eng)
- pohmelfs_crypto_thread_make_ready(t);
-
- pohmelfs_crypto_finish(trans, t->psb, err);
- return err;
-}
-
-static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t)
-{
- struct pohmelfs_crypto_engine *e = &t->eng;
- struct page *page = t->page;
- int err;
-
- WARN_ON(!PageChecked(page));
-
- err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size);
- if (!err)
- SetPageUptodate(page);
- else
- SetPageError(page);
- unlock_page(page);
- page_cache_release(page);
-
- pohmelfs_crypto_thread_make_ready(t);
-
- return err;
-}
-
-static int pohmelfs_crypto_thread_func(void *data)
-{
- struct pohmelfs_crypto_thread *t = data;
-
- while (!kthread_should_stop()) {
- wait_event_interruptible(t->wait, kthread_should_stop() ||
- t->trans || t->page);
-
- if (kthread_should_stop())
- break;
-
- if (!t->trans && !t->page)
- continue;
-
- dprintk("%s: thread: %p, trans: %p, page: %p.\n",
- __func__, t, t->trans, t->page);
-
- if (t->trans)
- pohmelfs_crypto_thread_trans(t);
- else if (t->page)
- pohmelfs_crypto_thread_page(t);
- }
-
- return 0;
-}
-
-static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head)
-{
- while (!list_empty(head)) {
- struct pohmelfs_crypto_thread *t = NULL;
-
- mutex_lock(&psb->crypto_thread_lock);
- if (!list_empty(head)) {
- t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry);
- list_del_init(&t->thread_entry);
- }
- mutex_unlock(&psb->crypto_thread_lock);
-
- if (t)
- pohmelfs_sys_crypto_exit_one(t);
- }
-}
-
-static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb)
-{
- while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) {
- dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num);
- pohmelfs_crypto_flush(psb, &psb->crypto_active_list);
- pohmelfs_crypto_flush(psb, &psb->crypto_ready_list);
- }
-}
-
-static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb)
-{
- unsigned int i;
- struct pohmelfs_crypto_thread *t;
- struct pohmelfs_config *c;
- struct netfs_state *st;
- int err;
-
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
-
- err = pohmelfs_crypto_engine_init(&st->eng, psb);
- if (err)
- goto err_out_exit;
-
- dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n",
- __func__, st, &st->eng, &st->eng.hash, &st->eng.cipher);
- }
-
- for (i = 0; i < psb->crypto_thread_num; ++i) {
- err = -ENOMEM;
- t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL);
- if (!t)
- goto err_out_free_state_engines;
-
- init_waitqueue_head(&t->wait);
-
- t->psb = psb;
- t->trans = NULL;
- t->eng.thread = t;
-
- err = pohmelfs_crypto_engine_init(&t->eng, psb);
- if (err)
- goto err_out_free_state_engines;
-
- err = pohmelfs_crypto_pages_alloc(&t->eng, psb);
- if (err)
- goto err_out_free;
-
- t->thread = kthread_run(pohmelfs_crypto_thread_func, t,
- "pohmelfs-crypto-%d-%d", psb->idx, i);
- if (IS_ERR(t->thread)) {
- err = PTR_ERR(t->thread);
- t->thread = NULL;
- goto err_out_free;
- }
-
- if (t->eng.cipher)
- psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher);
-
- mutex_lock(&psb->crypto_thread_lock);
- list_add_tail(&t->thread_entry, &psb->crypto_ready_list);
- mutex_unlock(&psb->crypto_thread_lock);
- }
-
- psb->crypto_thread_num = i;
- return 0;
-
-err_out_free:
- pohmelfs_sys_crypto_exit_one(t);
-err_out_free_state_engines:
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
- pohmelfs_crypto_engine_exit(&st->eng);
- }
-err_out_exit:
- pohmelfs_sys_crypto_exit(psb);
- return err;
-}
-
-void pohmelfs_crypto_exit(struct pohmelfs_sb *psb)
-{
- pohmelfs_sys_crypto_exit(psb);
-
- kfree(psb->hash_string);
- kfree(psb->cipher_string);
-}
-
-static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num,
- void *private, int err)
-{
- struct pohmelfs_sb *psb = private;
-
- psb->flags = -err;
- dprintk("%s: err: %d.\n", __func__, err);
-
- wake_up(&psb->wait);
-
- return err;
-}
-
-static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb)
-{
- struct netfs_trans *t;
- struct netfs_crypto_capabilities *cap;
- struct netfs_cmd *cmd;
- char *str;
- int err = -ENOMEM, size;
-
- size = sizeof(struct netfs_crypto_capabilities) +
- psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */
-
- t = netfs_trans_alloc(psb, size, 0, 0);
- if (!t)
- goto err_out_exit;
-
- t->complete = pohmelfs_crypt_init_complete;
- t->private = psb;
-
- cmd = netfs_trans_current(t);
- cap = (struct netfs_crypto_capabilities *)(cmd + 1);
- str = (char *)(cap + 1);
-
- cmd->cmd = NETFS_CAPABILITIES;
- cmd->id = POHMELFS_CRYPTO_CAPABILITIES;
- cmd->size = size;
- cmd->start = 0;
- cmd->ext = 0;
- cmd->csize = 0;
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, size);
-
- cap->hash_strlen = psb->hash_strlen;
- if (cap->hash_strlen) {
- sprintf(str, "%s", psb->hash_string);
- str += cap->hash_strlen;
- }
-
- cap->cipher_strlen = psb->cipher_strlen;
- cap->cipher_keysize = psb->cipher_keysize;
- if (cap->cipher_strlen)
- sprintf(str, "%s", psb->cipher_string);
-
- netfs_convert_crypto_capabilities(cap);
-
- psb->flags = ~0;
- err = netfs_trans_finish(t, psb);
- if (err)
- goto err_out_exit;
-
- err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0),
- psb->wait_on_page_timeout);
- if (!err)
- err = -ETIMEDOUT;
- else if (err > 0)
- err = -psb->flags;
-
- if (!err)
- psb->perform_crypto = 1;
- psb->flags = 0;
-
- /*
- * At this point NETFS_CAPABILITIES response command
- * should setup superblock in a way, which is acceptable
- * for both client and server, so if server refuses connection,
- * it will send error in transaction response.
- */
-
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_exit:
- return err;
-}
-
-int pohmelfs_crypto_init(struct pohmelfs_sb *psb)
-{
- int err;
-
- if (!psb->cipher_string && !psb->hash_string)
- return 0;
-
- err = pohmelfs_crypto_init_handshake(psb);
- if (err)
- return err;
-
- err = pohmelfs_sys_crypto_init(psb);
- if (err)
- return err;
-
- return 0;
-}
-
-static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb,
- int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data)
-{
- struct pohmelfs_crypto_thread *t = NULL;
- int err;
-
- while (!t) {
- err = wait_event_interruptible_timeout(psb->wait,
- !list_empty(&psb->crypto_ready_list),
- psb->wait_on_page_timeout);
-
- t = NULL;
- err = 0;
- mutex_lock(&psb->crypto_thread_lock);
- if (!list_empty(&psb->crypto_ready_list)) {
- t = list_entry(psb->crypto_ready_list.prev,
- struct pohmelfs_crypto_thread,
- thread_entry);
-
- list_move_tail(&t->thread_entry,
- &psb->crypto_active_list);
-
- action(t, data);
- wake_up(&t->wait);
-
- }
- mutex_unlock(&psb->crypto_thread_lock);
- }
-
- return err;
-}
-
-static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data)
-{
- struct netfs_trans *trans = data;
-
- netfs_trans_get(trans);
- t->trans = trans;
-
- dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t);
- return 0;
-}
-
-int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
-{
- if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) {
- netfs_trans_get(trans);
- return pohmelfs_crypto_finish(trans, psb, 0);
- }
-
- return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
-}
-
-struct pohmelfs_crypto_input_action_data {
- struct page *page;
- struct pohmelfs_crypto_engine *e;
- u64 iv;
- unsigned int size;
-};
-
-static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data)
-{
- struct pohmelfs_crypto_input_action_data *act = data;
-
- memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size);
-
- t->size = act->size;
- t->eng.iv = act->iv;
-
- t->page = act->page;
- return 0;
-}
-
-int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
- struct page *page, unsigned int size, u64 iv)
-{
- struct inode *inode = page->mapping->host;
- struct pohmelfs_crypto_input_action_data act;
- int err = -ENOENT;
-
- act.page = page;
- act.e = e;
- act.size = size;
- act.iv = iv;
-
- err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb),
- pohmelfs_crypt_input_page_action, &act);
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_exit:
- SetPageUptodate(page);
- page_cache_release(page);
-
- return err;
-}
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
deleted file mode 100644
index 2ee4491b7136..000000000000
--- a/drivers/staging/pohmelfs/dir.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/kernel.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-
-#include "netfs.h"
-
-static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash)
-{
- if (n->hash > hash)
- return -1;
- if (n->hash < hash)
- return 1;
-
- return 0;
-}
-
-static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash)
-{
- struct rb_node *n = pi->hash_root.rb_node;
- struct pohmelfs_name *tmp = NULL;
- int cmp;
-
- while (n) {
- tmp = rb_entry(n, struct pohmelfs_name, hash_node);
-
- cmp = pohmelfs_cmp_hash(tmp, hash);
- if (cmp < 0)
- n = n->rb_left;
- else if (cmp > 0)
- n = n->rb_right;
- else
- break;
-
- }
-
- return tmp;
-}
-
-struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash)
-{
- struct pohmelfs_name *tmp;
-
- tmp = pohmelfs_search_hash_unprecise(pi, hash);
- if (tmp && (tmp->hash == hash))
- return tmp;
-
- return NULL;
-}
-
-static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
- rb_erase(&node->hash_node, &parent->hash_root);
-}
-
-/*
- * Remove name cache entry from its caches and free it.
- */
-static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
- __pohmelfs_name_del(parent, node);
- list_del(&node->sync_create_entry);
- kfree(node);
-}
-
-static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi,
- struct pohmelfs_name *new)
-{
- struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL;
- struct pohmelfs_name *ret = NULL, *tmp;
- int cmp;
-
- while (*n) {
- parent = *n;
-
- tmp = rb_entry(parent, struct pohmelfs_name, hash_node);
-
- cmp = pohmelfs_cmp_hash(tmp, new->hash);
- if (cmp < 0)
- n = &parent->rb_left;
- else if (cmp > 0)
- n = &parent->rb_right;
- else {
- ret = tmp;
- break;
- }
- }
-
- if (ret) {
- printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
- "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
- __func__, pi->ino,
- ret->ino, ret->hash, ret->len, ret->data,
- new->ino, new->hash, new->len, new->data);
- ret->ino = new->ino;
- return ret;
- }
-
- rb_link_node(&new->hash_node, parent, n);
- rb_insert_color(&new->hash_node, &pi->hash_root);
-
- return NULL;
-}
-
-/*
- * Free name cache for given inode.
- */
-void pohmelfs_free_names(struct pohmelfs_inode *parent)
-{
- struct rb_node *rb_node;
- struct pohmelfs_name *n;
-
- for (rb_node = rb_first(&parent->hash_root); rb_node;) {
- n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
- rb_node = rb_next(rb_node);
-
- pohmelfs_name_free(parent, n);
- }
-}
-
-static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
- parent->total_len -= node->len;
-}
-
-/*
- * Free name cache entry helper.
- */
-void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
- pohmelfs_fix_offset(parent, node);
- pohmelfs_name_free(parent, node);
-}
-
-/*
- * Insert new name cache entry into all hash cache.
- */
-static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n)
-{
- struct pohmelfs_name *name;
-
- name = pohmelfs_insert_hash(parent, n);
- if (name)
- return -EEXIST;
-
- parent->total_len += n->len;
- list_add_tail(&n->sync_create_entry, &parent->sync_create_list);
-
- return 0;
-}
-
-/*
- * Allocate new name cache entry.
- */
-static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len)
-{
- struct pohmelfs_name *n;
-
- n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL);
- if (!n)
- return NULL;
-
- INIT_LIST_HEAD(&n->sync_create_entry);
-
- n->data = (char *)(n+1);
-
- return n;
-}
-
-/*
- * Add new name entry into directory's cache.
- */
-static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent,
- struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link)
-{
- int err = -ENOMEM;
- struct pohmelfs_name *n;
-
- n = pohmelfs_name_alloc(str->len + 1);
- if (!n)
- goto err_out_exit;
-
- n->ino = npi->ino;
- n->mode = mode;
- n->len = str->len;
- n->hash = str->hash;
- sprintf(n->data, "%s", str->name);
-
- mutex_lock(&parent->offset_lock);
- err = pohmelfs_insert_name(parent, n);
- mutex_unlock(&parent->offset_lock);
-
- if (err) {
- if (err != -EEXIST)
- goto err_out_free;
- kfree(n);
- }
-
- return 0;
-
-err_out_free:
- kfree(n);
-err_out_exit:
- return err;
-}
-
-/*
- * Create new inode for given parameters (name, inode info, parent).
- * This does not create object on the server, it will be synced there during writeback.
- */
-struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
- struct pohmelfs_inode *parent, struct qstr *str,
- struct netfs_inode_info *info, int link)
-{
- struct inode *new = NULL;
- struct pohmelfs_inode *npi;
- int err = -EEXIST;
-
- dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
- __func__, (parent) ? parent->ino : 0, info->ino, str);
-
- err = -ENOMEM;
- new = iget_locked(psb->sb, info->ino);
- if (!new)
- goto err_out_exit;
-
- npi = POHMELFS_I(new);
- npi->ino = info->ino;
- err = 0;
-
- if (new->i_state & I_NEW) {
- dprintk("%s: filling VFS inode: %lu/%llu.\n",
- __func__, new->i_ino, info->ino);
- pohmelfs_fill_inode(new, info);
-
- if (S_ISDIR(info->mode)) {
- struct qstr s;
-
- s.name = ".";
- s.len = 1;
- s.hash = jhash(s.name, s.len, 0);
-
- err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0);
- if (err)
- goto err_out_put;
-
- s.name = "..";
- s.len = 2;
- s.hash = jhash(s.name, s.len, 0);
-
- err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s,
- (parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0);
- if (err)
- goto err_out_put;
- }
- }
-
- if (str) {
- if (parent) {
- err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link);
-
- dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
- __func__, (err) ? "unsuccessfully" : "successfully",
- str->name, parent->total_len, info->ino, parent->ino);
-
- if (err && err != -EEXIST)
- goto err_out_put;
- }
- }
-
- if (new->i_state & I_NEW) {
- if (parent)
- mark_inode_dirty(&parent->vfs_inode);
- mark_inode_dirty(new);
- }
-
- set_bit(NETFS_INODE_OWNED, &npi->state);
- npi->lock_type = POHMELFS_WRITE_LOCK;
- unlock_new_inode(new);
-
- return npi;
-
-err_out_put:
- printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err);
- iput(new);
-err_out_exit:
- return ERR_PTR(err);
-}
-
-static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num,
- void *private, int err)
-{
- struct pohmelfs_inode *pi = private;
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
- dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
- if (err)
- pi->error = err;
- wake_up(&psb->wait);
- pohmelfs_put_inode(pi);
-
- return err;
-}
-
-/*
- * Receive directory content from the server.
- * This should be only done for objects, which were not created locally,
- * and which were not synced previously.
- */
-static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
-{
- struct inode *inode = &pi->vfs_inode;
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- long ret = psb->wait_on_page_timeout;
- int err;
-
- dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
- __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state));
-
- if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state))
- return 0;
-
- if (!igrab(inode)) {
- err = -ENOENT;
- goto err_out_exit;
- }
-
- err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST,
- pohmelfs_remote_sync_complete, pi, 0);
- if (err)
- goto err_out_exit;
-
- pi->error = 0;
- ret = wait_event_interruptible_timeout(psb->wait,
- test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret);
- dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error);
- if (ret <= 0) {
- err = ret;
- if (!err)
- err = -ETIMEDOUT;
- goto err_out_exit;
- }
-
- if (pi->error)
- return pi->error;
-
- return 0;
-
-err_out_exit:
- clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
- return err;
-}
-
-static int pohmelfs_dir_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return 0;
-}
-
-/*
- * VFS readdir callback. Syncs directory content from server if needed,
- * and provides direntry info to the userspace.
- */
-static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct pohmelfs_name *n;
- struct rb_node *rb_node;
- int err = 0, mode;
- u64 len;
-
- dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
- __func__, pi->ino, (u64)file->f_pos,
- (unsigned long)file->private_data);
-#if 0
- err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
- if (err)
- return err;
-#endif
- err = pohmelfs_sync_remote_dir(pi);
- if (err)
- return err;
-
- if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos))
- return 0;
-
- mutex_lock(&pi->offset_lock);
- n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data);
-
- while (n) {
- mode = (n->mode >> 12) & 15;
-
- dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
- "mode: %o/%o, fpos: %llu, hash: %08x.\n",
- __func__, file->f_pos, pi->ino, n->data, n->len,
- n->ino, n->mode, mode, file->f_pos, n->hash);
-
- file->private_data = (void *)(unsigned long)n->hash;
-
- len = n->len;
- err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode);
-
- if (err < 0) {
- dprintk("%s: err: %d.\n", __func__, err);
- err = 0;
- break;
- }
-
- file->f_pos += len;
-
- rb_node = rb_next(&n->hash_node);
-
- if (!rb_node || (rb_node == &n->hash_node)) {
- file->private_data = (void *)(unsigned long)file->f_pos;
- break;
- }
-
- n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
- }
- mutex_unlock(&pi->offset_lock);
-
- return err;
-}
-
-static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin)
-{
- file->f_pos = offset;
- file->private_data = NULL;
- return offset;
-}
-
-const struct file_operations pohmelfs_dir_fops = {
- .open = pohmelfs_dir_open,
- .read = generic_read_dir,
- .llseek = pohmelfs_dir_lseek,
- .readdir = pohmelfs_readdir,
-};
-
-/*
- * Lookup single object on server.
- */
-static int pohmelfs_lookup_single(struct pohmelfs_inode *parent,
- struct qstr *str, u64 ino)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb);
- long ret = msecs_to_jiffies(5000);
- int err;
-
- set_bit(NETFS_COMMAND_PENDING, &parent->state);
- err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP,
- (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino);
- if (err)
- goto err_out_exit;
-
- err = 0;
- ret = wait_event_interruptible_timeout(psb->wait,
- !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret);
- if (ret <= 0) {
- err = ret;
- if (!err)
- err = -ETIMEDOUT;
- }
-
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_exit:
- clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-
- printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
- __func__, parent->ino, ino, str->name, err);
-
- return err;
-}
-
-/*
- * VFS lookup callback.
- * We first try to get inode number from local name cache, if we have one,
- * then inode can be found in inode cache. If there is no inode or no object in
- * local cache, try to lookup it on server. This only should be done for directories,
- * which were not created locally, otherwise remote server does not know about dir at all,
- * so no need to try to know that.
- */
-struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct pohmelfs_inode *parent = POHMELFS_I(dir);
- struct pohmelfs_name *n;
- struct inode *inode = NULL;
- unsigned long ino = 0;
- int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
- struct qstr str = dentry->d_name;
-
- if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
- lock_type = POHMELFS_WRITE_LOCK;
-
- if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
- if (lock_type == parent->lock_type)
- need_lock = 0;
- if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK))
- need_lock = 0;
- }
-
- if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state))
- need_lock = 1;
-
- str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
- mutex_lock(&parent->offset_lock);
- n = pohmelfs_search_hash(parent, str.hash);
- if (n)
- ino = n->ino;
- mutex_unlock(&parent->offset_lock);
-
- dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
- __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
-
- if (ino) {
- inode = ilookup(dir->i_sb, ino);
- if (inode)
- goto out;
- }
-
- dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
- __func__, dir, parent->ino,
- str.name, str.len, parent->state, ino);
-
- if (!ino) {
- if (!need_lock)
- goto out;
- }
-
- err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
- if (err)
- goto out;
-
- err = pohmelfs_lookup_single(parent, &str, ino);
- if (err)
- goto out;
-
- if (!ino) {
- mutex_lock(&parent->offset_lock);
- n = pohmelfs_search_hash(parent, str.hash);
- if (n)
- ino = n->ino;
- mutex_unlock(&parent->offset_lock);
- }
-
- if (ino) {
- inode = ilookup(dir->i_sb, ino);
- dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
- __func__, ino, inode, str.name, str.hash);
- if (!inode) {
- dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
- __func__, ino, str.name, str.hash);
- /* return NULL; */
- return ERR_PTR(-EACCES);
- }
- } else {
- printk("%s: No inode number : name: '%s', hash: %x.\n",
- __func__, str.name, str.hash);
- }
-out:
- return d_splice_alias(inode, dentry);
-}
-
-/*
- * Create new object in local cache. Object will be synced to server
- * during writeback for given inode.
- */
-struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
- struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode)
-{
- struct pohmelfs_inode *npi;
- int err = -ENOMEM;
- struct netfs_inode_info info;
-
- dprintk("%s: name: '%s', mode: %ho, start: %llu.\n",
- __func__, str->name, mode, start);
-
- info.mode = mode;
- info.ino = start;
-
- if (!start)
- info.ino = pohmelfs_new_ino(psb);
-
- info.nlink = S_ISDIR(mode) ? 2 : 1;
- info.uid = current_fsuid();
- info.gid = current_fsgid();
- info.size = 0;
- info.blocksize = 512;
- info.blocks = 0;
- info.rdev = 0;
- info.version = 0;
-
- npi = pohmelfs_new_inode(psb, parent, str, &info, !!start);
- if (IS_ERR(npi)) {
- err = PTR_ERR(npi);
- goto err_out_unlock;
- }
-
- return npi;
-
-err_out_unlock:
- dprintk("%s: err: %d.\n", __func__, err);
- return ERR_PTR(err);
-}
-
-/*
- * Create local object and bind it to dentry.
- */
-static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry,
- u64 start, umode_t mode)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
- struct pohmelfs_inode *npi, *parent;
- struct qstr str = dentry->d_name;
- int err;
-
- parent = POHMELFS_I(dir);
-
- err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
- if (err)
- return err;
-
- str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
- npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode);
- if (IS_ERR(npi))
- return PTR_ERR(npi);
-
- d_instantiate(dentry, &npi->vfs_inode);
-
- dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
- __func__, parent->ino, npi->ino, dentry->d_name.name,
- (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink);
-
- return 0;
-}
-
-/*
- * VFS create and mkdir callbacks.
- */
-static int pohmelfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
- struct nameidata *nd)
-{
- return pohmelfs_create_entry(dir, dentry, 0, mode);
-}
-
-static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
- int err;
-
- inode_inc_link_count(dir);
- err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR);
- if (err)
- inode_dec_link_count(dir);
-
- return err;
-}
-
-static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
- struct inode *inode = dentry->d_inode;
- struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode);
- struct pohmelfs_name *n;
- int err = -ENOENT;
- struct qstr str = dentry->d_name;
-
- err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
- if (err)
- return err;
-
- str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
- dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
- __func__, parent->ino, pi->ino,
- str.name, (signed)inode->i_nlink);
-
- BUG_ON(!inode);
-
- mutex_lock(&parent->offset_lock);
- n = pohmelfs_search_hash(parent, str.hash);
- if (n) {
- pohmelfs_fix_offset(parent, n);
- if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
- pohmelfs_remove_child(pi, n);
-
- pohmelfs_name_free(parent, n);
- err = 0;
- }
- mutex_unlock(&parent->offset_lock);
-
- if (!err) {
- psb->avail_size += inode->i_size;
-
- pohmelfs_inode_del_inode(psb, pi);
-
- mark_inode_dirty(dir);
-
- inode->i_ctime = dir->i_ctime;
- if (inode->i_nlink)
- inode_dec_link_count(inode);
- }
-
- return err;
-}
-
-/*
- * Unlink and rmdir VFS callbacks.
- */
-static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry)
-{
- return pohmelfs_remove_entry(dir, dentry);
-}
-
-static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- int err;
- struct inode *inode = dentry->d_inode;
-
- dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
- __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino,
- dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink);
-
- err = pohmelfs_remove_entry(dir, dentry);
- if (!err) {
- inode_dec_link_count(dir);
- inode_dec_link_count(inode);
- }
-
- return err;
-}
-
-/*
- * Link creation is synchronous.
- * I'm lazy.
- * Earth is somewhat round.
- */
-static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj,
- struct pohmelfs_inode *target, struct qstr *tstr)
-{
- struct super_block *sb = parent->vfs_inode.i_sb;
- struct pohmelfs_sb *psb = POHMELFS_SB(sb);
- struct netfs_cmd *cmd;
- struct netfs_trans *t;
- void *data;
- int err, parent_len, target_len = 0, cur_len, path_size = 0;
-
- err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
- if (err)
- return err;
-
- err = sb->s_op->write_inode(&parent->vfs_inode, 0);
- if (err)
- goto err_out_exit;
-
- if (tstr)
- target_len = tstr->len;
-
- parent_len = pohmelfs_path_length(parent);
- if (target)
- target_len += pohmelfs_path_length(target);
-
- if (parent_len < 0) {
- err = parent_len;
- goto err_out_exit;
- }
-
- if (target_len < 0) {
- err = target_len;
- goto err_out_exit;
- }
-
- t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
- cur_len = netfs_trans_cur_len(t);
-
- cmd = netfs_trans_current(t);
- if (IS_ERR(cmd)) {
- err = PTR_ERR(cmd);
- goto err_out_free;
- }
-
- data = (void *)(cmd + 1);
- cur_len -= sizeof(struct netfs_cmd);
-
- err = pohmelfs_construct_path_string(parent, data, parent_len);
- if (err > 0) {
- /* Do not place null-byte before the slash */
- path_size = err - 1;
- cur_len -= path_size;
-
- err = snprintf(data + path_size, cur_len, "/%s|", obj->name);
-
- path_size += err;
- cur_len -= err;
-
- cmd->ext = path_size - 1; /* No | symbol */
-
- if (target) {
- err = pohmelfs_construct_path_string(target, data + path_size, target_len);
- if (err > 0) {
- path_size += err;
- cur_len -= err;
- }
- }
- }
-
- if (err < 0)
- goto err_out_free;
-
- cmd->start = 0;
-
- if (!target && tstr) {
- if (tstr->len > cur_len - 1) {
- err = -ENAMETOOLONG;
- goto err_out_free;
- }
-
- err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */
- path_size += err;
- cur_len -= err;
- cmd->start = 1;
- }
-
- dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
- __func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL,
- (char *)data);
-
- cmd->cmd = NETFS_LINK;
- cmd->size = path_size;
- cmd->id = parent->ino;
-
- netfs_convert_cmd(cmd);
-
- netfs_trans_update(cmd, t, path_size);
-
- err = netfs_trans_finish(t, psb);
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_free:
- t->result = err;
- netfs_trans_put(t);
-err_out_exit:
- return err;
-}
-
-/*
- * VFS hard and soft link callbacks.
- */
-static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
-{
- struct inode *inode = old_dentry->d_inode;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- int err;
- struct qstr str = dentry->d_name;
-
- str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
- err = inode->i_sb->s_op->write_inode(inode, 0);
- if (err)
- return err;
-
- err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL);
- if (err)
- return err;
-
- return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode);
-}
-
-static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
- struct qstr sym_str;
- struct qstr str = dentry->d_name;
- struct inode *inode;
- int err;
-
- str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
- sym_str.name = symname;
- sym_str.len = strlen(symname);
-
- err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str);
- if (err)
- goto err_out_exit;
-
- err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
- if (err)
- goto err_out_exit;
-
- inode = dentry->d_inode;
-
- err = page_symlink(inode, symname, sym_str.len + 1);
- if (err)
- goto err_out_put;
-
- return 0;
-
-err_out_put:
- iput(inode);
-err_out_exit:
- return err;
-}
-
-static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent,
- struct qstr *str)
-{
- int path_len, err, total_len = 0, inode_len, parent_len;
- char *path;
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
- parent_len = pohmelfs_path_length(parent);
- inode_len = pohmelfs_path_length(pi);
-
- if (parent_len < 0 || inode_len < 0)
- return -EINVAL;
-
- path_len = parent_len + inode_len + str->len + 3;
-
- t = netfs_trans_alloc(psb, path_len, 0, 0);
- if (!t)
- return -ENOMEM;
-
- cmd = netfs_trans_current(t);
- path = (char *)(cmd + 1);
-
- err = pohmelfs_construct_path_string(pi, path, inode_len);
- if (err < 0)
- goto err_out_unlock;
-
- cmd->ext = err;
-
- path += err;
- total_len += err;
- path_len -= err;
-
- *path = '|';
- path++;
- total_len++;
- path_len--;
-
- err = pohmelfs_construct_path_string(parent, path, parent_len);
- if (err < 0)
- goto err_out_unlock;
-
- /*
- * Do not place a null-byte before the final slash and the name.
- */
- err--;
- path += err;
- total_len += err;
- path_len -= err;
-
- err = snprintf(path, path_len - 1, "/%s", str->name);
-
- total_len += err + 1; /* 0 symbol */
- path_len -= err + 1;
-
- cmd->cmd = NETFS_RENAME;
- cmd->id = pi->ino;
- cmd->start = parent->ino;
- cmd->size = total_len;
-
- netfs_convert_cmd(cmd);
-
- netfs_trans_update(cmd, t, total_len);
-
- return netfs_trans_finish(t, psb);
-
-err_out_unlock:
- netfs_trans_free(t);
- return err;
-}
-
-static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
-{
- struct inode *inode = old_dentry->d_inode;
- struct pohmelfs_inode *old_parent, *pi, *new_parent;
- struct qstr str = new_dentry->d_name;
- struct pohmelfs_name *n;
- unsigned int old_hash;
- int err = -ENOENT;
-
- pi = POHMELFS_I(inode);
- old_parent = POHMELFS_I(old_dir);
-
- if (new_dir)
- new_dir->i_sb->s_op->write_inode(new_dir, 0);
-
- old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
- str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
- str.len = new_dentry->d_name.len;
- str.name = new_dentry->d_name.name;
- str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
- if (new_dir) {
- new_parent = POHMELFS_I(new_dir);
- err = -ENOTEMPTY;
-
- if (S_ISDIR(inode->i_mode) &&
- new_parent->total_len <= 3)
- goto err_out_exit;
- } else {
- new_parent = old_parent;
- }
-
- dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
- __func__, pi->ino, old_parent->ino, old_dentry->d_name.name,
- new_parent->ino, new_dentry->d_name.name, inode->i_size);
-
- if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) &&
- test_bit(NETFS_INODE_OWNED, &pi->state)) {
- err = pohmelfs_send_rename(pi, new_parent, &str);
- if (err)
- goto err_out_exit;
- }
-
- n = pohmelfs_name_alloc(str.len + 1);
- if (!n)
- goto err_out_exit;
-
- mutex_lock(&new_parent->offset_lock);
- n->ino = pi->ino;
- n->mode = inode->i_mode;
- n->len = str.len;
- n->hash = str.hash;
- sprintf(n->data, "%s", str.name);
-
- err = pohmelfs_insert_name(new_parent, n);
- mutex_unlock(&new_parent->offset_lock);
-
- if (err)
- goto err_out_exit;
-
- mutex_lock(&old_parent->offset_lock);
- n = pohmelfs_search_hash(old_parent, old_hash);
- if (n)
- pohmelfs_name_del(old_parent, n);
- mutex_unlock(&old_parent->offset_lock);
-
- mark_inode_dirty(inode);
- mark_inode_dirty(&new_parent->vfs_inode);
-
- WARN_ON_ONCE(list_empty(&inode->i_dentry));
-
- return 0;
-
-err_out_exit:
-
- clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
- return err;
-}
-
-/*
- * POHMELFS directory inode operations.
- */
-const struct inode_operations pohmelfs_dir_inode_ops = {
- .link = pohmelfs_link,
- .symlink = pohmelfs_symlink,
- .unlink = pohmelfs_unlink,
- .mkdir = pohmelfs_mkdir,
- .rmdir = pohmelfs_rmdir,
- .create = pohmelfs_create,
- .lookup = pohmelfs_lookup,
- .setattr = pohmelfs_setattr,
- .rename = pohmelfs_rename,
-};
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
deleted file mode 100644
index 807e3f324113..000000000000
--- a/drivers/staging/pohmelfs/inode.c
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/backing-dev.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/pagevec.h>
-#include <linux/parser.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-#include <linux/prefetch.h>
-
-#include "netfs.h"
-
-#define POHMELFS_MAGIC_NUM 0x504f482e
-
-static struct kmem_cache *pohmelfs_inode_cache;
-static atomic_t psb_bdi_num = ATOMIC_INIT(0);
-
-/*
- * Removes inode from all trees, drops local name cache and removes all queued
- * requests for object removal.
- */
-void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi)
-{
- mutex_lock(&pi->offset_lock);
- pohmelfs_free_names(pi);
- mutex_unlock(&pi->offset_lock);
-
- dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino);
-}
-
-/*
- * Sync inode to server.
- * Returns zero in success and negative error value otherwise.
- * It will gather path to root directory into structures containing
- * creation mode, permissions and names, so that the whole path
- * to given inode could be created using only single network command.
- */
-int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans)
-{
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- int err = -ENOMEM, size;
- struct netfs_cmd *cmd;
- void *data;
- int cur_len = netfs_trans_cur_len(trans);
-
- if (unlikely(cur_len < 0))
- return -ETOOSMALL;
-
- cmd = netfs_trans_current(trans);
- cur_len -= sizeof(struct netfs_cmd);
-
- data = (void *)(cmd + 1);
-
- err = pohmelfs_construct_path_string(pi, data, cur_len);
- if (err < 0)
- goto err_out_exit;
-
- size = err;
-
- cmd->start = i_size_read(inode);
- cmd->cmd = NETFS_CREATE;
- cmd->size = size;
- cmd->id = pi->ino;
- cmd->ext = inode->i_mode;
-
- netfs_convert_cmd(cmd);
-
- netfs_trans_update(cmd, trans, size);
-
- return 0;
-
-err_out_exit:
- printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err);
- return err;
-}
-
-static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num,
- void *private, int err)
-{
- unsigned i;
-
- dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n",
- __func__, pages[0]->index, pages[page_num-1]->index,
- page_num, err);
-
- for (i = 0; i < page_num; i++) {
- struct page *page = pages[i];
-
- if (!page)
- continue;
-
- end_page_writeback(page);
-
- if (err < 0) {
- SetPageError(page);
- set_page_dirty(page);
- }
-
- unlock_page(page);
- page_cache_release(page);
-
- /* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */
- }
- return err;
-}
-
-static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index)
-{
- int ret;
- struct page *page;
-
- rcu_read_lock();
- ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
- (void **)&page, index, 1, PAGECACHE_TAG_DIRTY);
- rcu_read_unlock();
- return ret;
-}
-
-static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
-{
- struct inode *inode = mapping->host;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- int err = 0;
- int done = 0;
- int nr_pages;
- pgoff_t index;
- pgoff_t end; /* Inclusive */
- int scanned = 0;
- int range_whole = 0;
-
- if (wbc->range_cyclic) {
- index = mapping->writeback_index; /* Start from prev offset */
- end = -1;
- } else {
- index = wbc->range_start >> PAGE_CACHE_SHIFT;
- end = wbc->range_end >> PAGE_CACHE_SHIFT;
- if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
- range_whole = 1;
- scanned = 1;
- }
-retry:
- while (!done && (index <= end)) {
- unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages);
- int path_len;
- struct netfs_trans *trans;
-
- err = pohmelfs_inode_has_dirty_pages(mapping, index);
- if (!err)
- break;
-
- err = pohmelfs_path_length(pi);
- if (err < 0)
- break;
-
- path_len = err;
-
- if (path_len <= 2) {
- err = -ENOENT;
- break;
- }
-
- trans = netfs_trans_alloc(psb, path_len, 0, i);
- if (!trans) {
- err = -ENOMEM;
- break;
- }
- trans->complete = &pohmelfs_write_trans_complete;
-
- trans->page_num = nr_pages = find_get_pages_tag(mapping, &index,
- PAGECACHE_TAG_DIRTY, trans->page_num,
- trans->pages);
-
- dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n",
- __func__, trans, nr_pages, end, index, trans->page_num);
-
- if (!nr_pages)
- goto err_out_reset;
-
- err = pohmelfs_write_inode_create(inode, trans);
- if (err)
- goto err_out_reset;
-
- err = 0;
- scanned = 1;
-
- for (i = 0; i < trans->page_num; i++) {
- struct page *page = trans->pages[i];
-
- lock_page(page);
-
- if (unlikely(page->mapping != mapping))
- goto out_continue;
-
- if (!wbc->range_cyclic && page->index > end) {
- done = 1;
- goto out_continue;
- }
-
- if (wbc->sync_mode != WB_SYNC_NONE)
- wait_on_page_writeback(page);
-
- if (PageWriteback(page) ||
- !clear_page_dirty_for_io(page)) {
- dprintk("%s: not clear for io page: %p, writeback: %d.\n",
- __func__, page, PageWriteback(page));
- goto out_continue;
- }
-
- set_page_writeback(page);
-
- trans->attached_size += page_private(page);
- trans->attached_pages++;
-#if 0
- dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n",
- __func__, i, trans->page_num, trans, trans->gen, page,
- !!PageHighMem(page), page_private(page), page->index);
-#endif
- wbc->nr_to_write--;
-
- if (wbc->nr_to_write <= 0)
- done = 1;
-
- continue;
-out_continue:
- unlock_page(page);
- trans->pages[i] = NULL;
- }
-
- err = netfs_trans_finish(trans, psb);
- if (err)
- break;
-
- continue;
-
-err_out_reset:
- trans->result = err;
- netfs_trans_reset(trans);
- netfs_trans_put(trans);
- break;
- }
-
- if (!scanned && !done) {
- /*
- * We hit the last page and there is more work to be done: wrap
- * back to the start of the file
- */
- scanned = 1;
- index = 0;
- goto retry;
- }
-
- if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
- mapping->writeback_index = index;
-
- return err;
-}
-
-/*
- * Inode writeback creation completion callback.
- * Only invoked for just created inodes, which do not have pages attached,
- * like dirs and empty files.
- */
-static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num,
- void *private, int err)
-{
- struct inode *inode = private;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
- if (inode) {
- if (err) {
- mark_inode_dirty(inode);
- clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
- } else {
- set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
- }
-
- pohmelfs_put_inode(pi);
- }
-
- return err;
-}
-
-int pohmelfs_write_create_inode(struct pohmelfs_inode *pi)
-{
- struct netfs_trans *t;
- struct inode *inode = &pi->vfs_inode;
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- int err;
-
- if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
- return 0;
-
- dprintk("%s: started ino: %llu.\n", __func__, pi->ino);
-
- err = pohmelfs_path_length(pi);
- if (err < 0)
- goto err_out_exit;
-
- t = netfs_trans_alloc(psb, err + 1, 0, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
- t->complete = pohmelfs_write_inode_complete;
- t->private = igrab(inode);
- if (!t->private) {
- err = -ENOENT;
- goto err_out_put;
- }
-
- err = pohmelfs_write_inode_create(inode, t);
- if (err)
- goto err_out_put;
-
- netfs_trans_finish(t, POHMELFS_SB(inode->i_sb));
-
- return 0;
-
-err_out_put:
- t->result = err;
- netfs_trans_put(t);
-err_out_exit:
- return err;
-}
-
-/*
- * Sync all not-yet-created children in given directory to the server.
- */
-static int pohmelfs_write_inode_create_children(struct inode *inode)
-{
- struct pohmelfs_inode *parent = POHMELFS_I(inode);
- struct super_block *sb = inode->i_sb;
- struct pohmelfs_name *n;
-
- while (!list_empty(&parent->sync_create_list)) {
- n = NULL;
- mutex_lock(&parent->offset_lock);
- if (!list_empty(&parent->sync_create_list)) {
- n = list_first_entry(&parent->sync_create_list,
- struct pohmelfs_name, sync_create_entry);
- list_del_init(&n->sync_create_entry);
- }
- mutex_unlock(&parent->offset_lock);
-
- if (!n)
- break;
-
- inode = ilookup(sb, n->ino);
-
- dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n",
- __func__, parent->ino, n->ino, inode);
-
- if (inode && (inode->i_state & I_DIRTY)) {
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- pohmelfs_write_create_inode(pi);
- /* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */
- iput(inode);
- }
- }
-
- return 0;
-}
-
-/*
- * Removes given child from given inode on server.
- */
-int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n)
-{
- return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0);
-}
-
-/*
- * Writeback for given inode.
- */
-static int pohmelfs_write_inode(struct inode *inode,
- struct writeback_control *wbc)
-{
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
- pohmelfs_write_create_inode(pi);
- pohmelfs_write_inode_create_children(inode);
-
- return 0;
-}
-
-/*
- * It is not exported, sorry...
- */
-static inline wait_queue_head_t *page_waitqueue(struct page *page)
-{
- const struct zone *zone = page_zone(page);
-
- return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
-}
-
-static int pohmelfs_wait_on_page_locked(struct page *page)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb);
- long ret = psb->wait_on_page_timeout;
- DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
- int err = 0;
-
- if (!PageLocked(page))
- return 0;
-
- for (;;) {
- prepare_to_wait(page_waitqueue(page),
- &wait.wait, TASK_INTERRUPTIBLE);
-
- dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n",
- __func__, page, PageLocked(page), PageUptodate(page),
- PageError(page), page->flags);
-
- if (!PageLocked(page))
- break;
-
- if (!signal_pending(current)) {
- ret = schedule_timeout(ret);
- if (!ret)
- break;
- continue;
- }
- ret = -ERESTARTSYS;
- break;
- }
- finish_wait(page_waitqueue(page), &wait.wait);
-
- if (!ret)
- err = -ETIMEDOUT;
-
-
- if (!err)
- SetPageUptodate(page);
-
- if (err)
- printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n",
- __func__, page, PageUptodate(page), PageLocked(page), err);
-
- return err;
-}
-
-static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num,
- void *private, int err)
-{
- struct page *page = private;
-
- if (PageChecked(page))
- return err;
-
- if (err < 0) {
- dprintk("%s: page: %p, err: %d.\n", __func__, page, err);
- SetPageError(page);
- }
-
- unlock_page(page);
-
- return err;
-}
-
-/*
- * Read a page from remote server.
- * Function will wait until page is unlocked.
- */
-static int pohmelfs_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- int err, path_len;
- void *data;
- u64 isize;
-
- err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT,
- PAGE_SIZE, POHMELFS_READ_LOCK);
- if (err)
- goto err_out_exit;
-
- isize = i_size_read(inode);
- if (isize <= page->index << PAGE_CACHE_SHIFT) {
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
- }
-
- path_len = pohmelfs_path_length(pi);
- if (path_len < 0) {
- err = path_len;
- goto err_out_exit;
- }
-
- t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
-
- t->complete = pohmelfs_read_page_complete;
- t->private = page;
-
- cmd = netfs_trans_current(t);
- data = (void *)(cmd + 1);
-
- err = pohmelfs_construct_path_string(pi, data, path_len);
- if (err < 0)
- goto err_out_free;
-
- path_len = err;
-
- cmd->id = pi->ino;
- cmd->start = page->index;
- cmd->start <<= PAGE_CACHE_SHIFT;
- cmd->size = PAGE_CACHE_SIZE + path_len;
- cmd->cmd = NETFS_READ_PAGE;
- cmd->ext = path_len;
-
- dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n",
- __func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE);
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, path_len);
-
- err = netfs_trans_finish(t, psb);
- if (err)
- goto err_out_return;
-
- return pohmelfs_wait_on_page_locked(page);
-
-err_out_free:
- t->result = err;
- netfs_trans_put(t);
-err_out_exit:
- SetPageError(page);
- if (PageLocked(page))
- unlock_page(page);
-err_out_return:
- printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n",
- __func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err);
-
- return err;
-}
-
-/*
- * Write begin/end magic.
- * Allocates a page and writes inode if it was not synced to server before.
- */
-static int pohmelfs_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
-{
- struct inode *inode = mapping->host;
- struct page *page;
- pgoff_t index;
- unsigned start, end;
- int err;
-
- *pagep = NULL;
-
- index = pos >> PAGE_CACHE_SHIFT;
- start = pos & (PAGE_CACHE_SIZE - 1);
- end = start + len;
-
- page = grab_cache_page(mapping, index);
-#if 0
- dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n",
- __func__, page, pos, len, index, start, end, PageUptodate(page));
-#endif
- if (!page) {
- err = -ENOMEM;
- goto err_out_exit;
- }
-
- while (!PageUptodate(page)) {
- if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) {
- err = pohmelfs_readpage(file, page);
- if (err)
- goto err_out_exit;
-
- lock_page(page);
- continue;
- }
-
- if (len != PAGE_CACHE_SIZE) {
- void *kaddr = kmap_atomic(page, KM_USER0);
-
- memset(kaddr + start, 0, PAGE_CACHE_SIZE - start);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
- }
- SetPageUptodate(page);
- }
-
- set_page_private(page, end);
-
- *pagep = page;
-
- return 0;
-
-err_out_exit:
- page_cache_release(page);
- *pagep = NULL;
-
- return err;
-}
-
-static int pohmelfs_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
-{
- struct inode *inode = mapping->host;
-
- if (copied != len) {
- unsigned from = pos & (PAGE_CACHE_SIZE - 1);
- void *kaddr = kmap_atomic(page, KM_USER0);
-
- memset(kaddr + from + copied, 0, len - copied);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
- }
-
- SetPageUptodate(page);
- set_page_dirty(page);
-#if 0
- dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n",
- __func__, page,
- PageUptodate(page), PageDirty(page), PageLocked(page),
- pos, len, copied);
-#endif
- flush_dcache_page(page);
-
- unlock_page(page);
- page_cache_release(page);
-
- if (pos + copied > inode->i_size) {
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
- psb->avail_size -= pos + copied - inode->i_size;
-
- i_size_write(inode, pos + copied);
- }
-
- return copied;
-}
-
-static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num,
- void *private, int err)
-{
- struct pohmelfs_inode *pi = private;
- unsigned int i, num;
- struct page **pages, *page = (struct page *)__pages;
- loff_t index = page->index;
-
- pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO);
- if (!pages)
- return -ENOMEM;
-
- num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages);
- if (num <= 0) {
- err = num;
- goto err_out_free;
- }
-
- for (i = 0; i < num; ++i) {
- page = pages[i];
-
- if (err)
- printk("%s: %u/%u: page: %p, index: %lu, uptodate: %d, locked: %d, err: %d.\n",
- __func__, i, num, page, page->index,
- PageUptodate(page), PageLocked(page), err);
-
- if (!PageChecked(page)) {
- if (err < 0)
- SetPageError(page);
- unlock_page(page);
- }
- page_cache_release(page);
- page_cache_release(page);
- }
-
-err_out_free:
- kfree(pages);
- return err;
-}
-
-static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num)
-{
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
- int err, path_len;
- void *data;
-
- err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT,
- num * PAGE_SIZE, POHMELFS_READ_LOCK);
- if (err)
- goto err_out_exit;
-
- path_len = pohmelfs_path_length(pi);
- if (path_len < 0) {
- err = path_len;
- goto err_out_exit;
- }
-
- t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
-
- cmd = netfs_trans_current(t);
- data = (void *)(cmd + 1);
-
- t->complete = pohmelfs_readpages_trans_complete;
- t->private = pi;
- t->page_num = num;
- t->pages = (struct page **)first;
-
- err = pohmelfs_construct_path_string(pi, data, path_len);
- if (err < 0)
- goto err_out_put;
-
- path_len = err;
-
- cmd->cmd = NETFS_READ_PAGES;
- cmd->start = first->index;
- cmd->start <<= PAGE_CACHE_SHIFT;
- cmd->size = (num << 8 | PAGE_CACHE_SHIFT);
- cmd->id = pi->ino;
- cmd->ext = path_len;
-
- dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, "
- "start: %lu, num: %u.\n",
- __func__, t, t->gen, (char *)data, path_len,
- first->index, num);
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, path_len);
-
- return netfs_trans_finish(t, psb);
-
-err_out_put:
- netfs_trans_free(t);
-err_out_exit:
- pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err);
- return err;
-}
-
-#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
-
-static int pohmelfs_readpages(struct file *file, struct address_space *mapping,
- struct list_head *pages, unsigned nr_pages)
-{
- unsigned int page_idx, num = 0;
- struct page *page = NULL, *first = NULL;
-
- for (page_idx = 0; page_idx < nr_pages; page_idx++) {
- page = list_to_page(pages);
-
- prefetchw(&page->flags);
- list_del(&page->lru);
-
- if (!add_to_page_cache_lru(page, mapping,
- page->index, GFP_KERNEL)) {
-
- if (!num) {
- num = 1;
- first = page;
- continue;
- }
-
- dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n",
- __func__, page, page->index, first->index);
-
- if (unlikely(first->index + num != page->index) || (num > 500)) {
- pohmelfs_send_readpages(POHMELFS_I(mapping->host),
- first, num);
- first = page;
- num = 0;
- }
-
- num++;
- }
- }
- pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num);
-
- /*
- * This will be sync read, so when last page is processed,
- * all previous are alerady unlocked and ready to be used.
- */
- return 0;
-}
-
-/*
- * Small address space operations for POHMELFS.
- */
-const struct address_space_operations pohmelfs_aops = {
- .readpage = pohmelfs_readpage,
- .readpages = pohmelfs_readpages,
- .writepages = pohmelfs_writepages,
- .write_begin = pohmelfs_write_begin,
- .write_end = pohmelfs_write_end,
- .set_page_dirty = __set_page_dirty_nobuffers,
-};
-
-static void pohmelfs_i_callback(struct rcu_head *head)
-{
- struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode));
-}
-
-/*
- * ->destroy_inode() callback. Deletes inode from the caches
- * and frees private data.
- */
-static void pohmelfs_destroy_inode(struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
- struct pohmelfs_sb *psb = POHMELFS_SB(sb);
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
- /* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */
-
- pohmelfs_inode_del_inode(psb, pi);
-
- dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
- __func__, pi, &pi->vfs_inode, pi->ino);
- atomic_long_dec(&psb->total_inodes);
- call_rcu(&inode->i_rcu, pohmelfs_i_callback);
-}
-
-/*
- * ->alloc_inode() callback. Allocates inode and initializes private data.
- */
-static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
-{
- struct pohmelfs_inode *pi;
-
- pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO);
- if (!pi)
- return NULL;
-
- pi->hash_root = RB_ROOT;
- mutex_init(&pi->offset_lock);
-
- INIT_LIST_HEAD(&pi->sync_create_list);
-
- INIT_LIST_HEAD(&pi->inode_entry);
-
- pi->lock_type = 0;
- pi->state = 0;
- pi->total_len = 0;
- pi->drop_count = 0;
-
- dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode);
-
- atomic_long_inc(&POHMELFS_SB(sb)->total_inodes);
-
- return &pi->vfs_inode;
-}
-
-/*
- * We want fsync() to work on POHMELFS.
- */
-static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
- struct inode *inode = file->f_mapping->host;
- int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
- if (!err) {
- mutex_lock(&inode->i_mutex);
- err = sync_inode_metadata(inode, 1);
- mutex_unlock(&inode->i_mutex);
- }
- return err;
-}
-
-ssize_t pohmelfs_write(struct file *file, const char __user *buf,
- size_t len, loff_t *ppos)
-{
- struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
- struct kiocb kiocb;
- ssize_t ret;
- loff_t pos = *ppos;
-
- init_sync_kiocb(&kiocb, file);
- kiocb.ki_pos = pos;
- kiocb.ki_left = len;
-
- dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos);
-
- mutex_lock(&inode->i_mutex);
- ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK);
- if (ret)
- goto err_out_unlock;
-
- ret = __generic_file_aio_write(&kiocb, &iov, 1, &kiocb.ki_pos);
- *ppos = kiocb.ki_pos;
-
- mutex_unlock(&inode->i_mutex);
- WARN_ON(ret < 0);
-
- if (ret > 0) {
- ssize_t err;
-
- err = generic_write_sync(file, pos, ret);
- if (err < 0)
- ret = err;
- WARN_ON(ret < 0);
- }
-
- return ret;
-
-err_out_unlock:
- mutex_unlock(&inode->i_mutex);
- return ret;
-}
-
-static const struct file_operations pohmelfs_file_ops = {
- .open = generic_file_open,
- .fsync = pohmelfs_fsync,
-
- .llseek = generic_file_llseek,
-
- .read = do_sync_read,
- .aio_read = generic_file_aio_read,
-
- .mmap = generic_file_mmap,
-
- .splice_read = generic_file_splice_read,
- .splice_write = generic_file_splice_write,
-
- .write = pohmelfs_write,
- .aio_write = generic_file_aio_write,
-};
-
-const struct inode_operations pohmelfs_symlink_inode_operations = {
- .readlink = generic_readlink,
- .follow_link = page_follow_link_light,
- .put_link = page_put_link,
-};
-
-int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr)
-{
- int err;
-
- err = inode_change_ok(inode, attr);
- if (err) {
- dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino);
- goto err_out_exit;
- }
-
- if ((attr->ia_valid & ATTR_SIZE) &&
- attr->ia_size != i_size_read(inode)) {
- err = vmtruncate(inode, attr->ia_size);
- if (err) {
- dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
- goto err_out_exit;
- }
- }
-
- setattr_copy(inode, attr);
- mark_inode_dirty(inode);
-
- dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n",
- __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode,
- inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size);
-
- return 0;
-
-err_out_exit:
- return err;
-}
-
-int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
- struct inode *inode = dentry->d_inode;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- int err;
-
- err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
- if (err)
- goto err_out_exit;
-
- err = security_inode_setattr(dentry, attr);
- if (err)
- goto err_out_exit;
-
- err = pohmelfs_setattr_raw(inode, attr);
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_exit:
- return err;
-}
-
-static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start,
- const char *name, const void *value, size_t attrsize, int command)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
- int err, path_len, namelen = strlen(name) + 1; /* 0-byte */
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- void *data;
-
- dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n",
- __func__, id, start, name, attrsize, command);
-
- path_len = pohmelfs_path_length(pi);
- if (path_len < 0) {
- err = path_len;
- goto err_out_exit;
- }
-
- t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
-
- cmd = netfs_trans_current(t);
- data = cmd + 1;
-
- path_len = pohmelfs_construct_path_string(pi, data, path_len);
- if (path_len < 0) {
- err = path_len;
- goto err_out_put;
- }
- data += path_len;
-
- /*
- * 'name' is a NUL-terminated string already and
- * 'namelen' includes 0-byte.
- */
- memcpy(data, name, namelen);
- data += namelen;
-
- memcpy(data, value, attrsize);
-
- cmd->cmd = command;
- cmd->id = id;
- cmd->start = start;
- cmd->size = attrsize + namelen + path_len;
- cmd->ext = path_len;
- cmd->csize = 0;
- cmd->cpad = 0;
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, namelen + path_len + attrsize);
-
- return netfs_trans_finish(t, psb);
-
-err_out_put:
- t->result = err;
- netfs_trans_put(t);
-err_out_exit:
- return err;
-}
-
-static int pohmelfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t attrsize, int flags)
-{
- struct inode *inode = dentry->d_inode;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
- if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
- return -EOPNOTSUPP;
-
- return pohmelfs_send_xattr_req(pi, flags, attrsize, name,
- value, attrsize, NETFS_XATTR_SET);
-}
-
-static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t attrsize)
-{
- struct inode *inode = dentry->d_inode;
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- struct pohmelfs_mcache *m;
- int err;
- long timeout = psb->mcache_timeout;
-
- if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
- return -EOPNOTSUPP;
-
- m = pohmelfs_mcache_alloc(psb, 0, attrsize, value);
- if (IS_ERR(m))
- return PTR_ERR(m);
-
- dprintk("%s: ino: %llu, name: '%s', size: %zu.\n",
- __func__, pi->ino, name, attrsize);
-
- err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET);
- if (err)
- goto err_out_put;
-
- do {
- err = wait_for_completion_timeout(&m->complete, timeout);
- if (err) {
- err = m->err;
- break;
- }
-
- /*
- * This loop is a bit ugly, since it waits until reference counter
- * hits 1 and then puts the object here. Main goal is to prevent race with
- * the network thread, when it can start processing the given request, i.e.
- * increase its reference counter but yet not complete it, while
- * we will exit from ->getxattr() with timeout, and although request
- * will not be freed (its reference counter was increased by network
- * thread), data pointer provided by user may be released, so we will
- * overwrite an already freed area in the network thread.
- *
- * Now after timeout we remove request from the cache, so it can not be
- * found by network thread, and wait for its reference counter to hit 1,
- * i.e. if network thread already started to process this request, we wait
- * for it to finish, and then free object locally. If reference counter is
- * already 1, i.e. request is not used by anyone else, we can free it without
- * problem.
- */
- err = -ETIMEDOUT;
- timeout = HZ;
-
- pohmelfs_mcache_remove_locked(psb, m);
- } while (atomic_read(&m->refcnt) != 1);
-
- pohmelfs_mcache_put(psb, m);
-
- dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
- return err;
-
-err_out_put:
- pohmelfs_mcache_put(psb, m);
- return err;
-}
-
-static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
- struct inode *inode = dentry->d_inode;
-#if 0
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
- int err;
-
- err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
- if (err)
- return err;
- dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n",
- __func__, pi->ino, inode->i_mode, inode->i_uid,
- inode->i_gid, inode->i_size);
-#endif
-
- generic_fillattr(inode, stat);
- return 0;
-}
-
-const struct inode_operations pohmelfs_file_inode_operations = {
- .setattr = pohmelfs_setattr,
- .getattr = pohmelfs_getattr,
- .setxattr = pohmelfs_setxattr,
- .getxattr = pohmelfs_getxattr,
-};
-
-/*
- * Fill inode data: mode, size, operation callbacks and so on...
- */
-void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
-{
- inode->i_mode = info->mode;
- set_nlink(inode, info->nlink);
- inode->i_uid = info->uid;
- inode->i_gid = info->gid;
- inode->i_blocks = info->blocks;
- inode->i_rdev = info->rdev;
- inode->i_size = info->size;
- inode->i_version = info->version;
- inode->i_blkbits = ffs(info->blocksize);
-
- dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n",
- __func__, inode, inode->i_ino, info->ino,
- S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode),
- S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size);
-
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-
- /*
- * i_mapping is a pointer to i_data during inode initialization.
- */
- inode->i_data.a_ops = &pohmelfs_aops;
-
- if (S_ISREG(inode->i_mode)) {
- inode->i_fop = &pohmelfs_file_ops;
- inode->i_op = &pohmelfs_file_inode_operations;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_fop = &pohmelfs_dir_fops;
- inode->i_op = &pohmelfs_dir_inode_ops;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &pohmelfs_symlink_inode_operations;
- inode->i_fop = &pohmelfs_file_ops;
- } else {
- inode->i_fop = &generic_ro_fops;
- }
-}
-
-static int pohmelfs_drop_inode(struct inode *inode)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
- spin_lock(&psb->ino_lock);
- list_del_init(&pi->inode_entry);
- spin_unlock(&psb->ino_lock);
-
- return generic_drop_inode(inode);
-}
-
-static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
- struct list_head *head, unsigned int *count)
-{
- struct pohmelfs_inode *pi = NULL;
-
- spin_lock(&psb->ino_lock);
- if (!list_empty(head)) {
- pi = list_entry(head->next, struct pohmelfs_inode,
- inode_entry);
- list_del_init(&pi->inode_entry);
- *count = pi->drop_count;
- pi->drop_count = 0;
- }
- spin_unlock(&psb->ino_lock);
-
- return pi;
-}
-
-static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config *c;
-
- mutex_lock(&psb->state_lock);
- list_for_each_entry(c, &psb->state_list, config_entry) {
- pohmelfs_state_flush_transactions(&c->state);
- }
- mutex_unlock(&psb->state_lock);
-}
-
-/*
- * ->put_super() callback. Invoked before superblock is destroyed,
- * so it has to clean all private data.
- */
-static void pohmelfs_put_super(struct super_block *sb)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(sb);
- struct pohmelfs_inode *pi;
- unsigned int count = 0;
- unsigned int in_drop_list = 0;
- struct inode *inode, *tmp;
-
- dprintk("%s.\n", __func__);
-
- /*
- * Kill pending transactions, which could affect inodes in-flight.
- */
- pohmelfs_flush_transactions(psb);
-
- while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) {
- inode = &pi->vfs_inode;
-
- dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
- __func__, pi->ino, pi, inode, count);
-
- if (atomic_read(&inode->i_count) != count) {
- printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n",
- __func__, pi->ino, pi, inode, count,
- atomic_read(&inode->i_count));
- count = atomic_read(&inode->i_count);
- in_drop_list++;
- }
-
- while (count--)
- iput(&pi->vfs_inode);
- }
-
- list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) {
- pi = POHMELFS_I(inode);
-
- dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n",
- __func__, pi->ino, pi, inode, atomic_read(&inode->i_count));
-
- /*
- * These are special inodes, they were created during
- * directory reading or lookup, and were not bound to dentry,
- * so they live here with reference counter being 1 and prevent
- * umount from succeed since it believes that they are busy.
- */
- count = atomic_read(&inode->i_count);
- if (count) {
- list_del_init(&inode->i_sb_list);
- while (count--)
- iput(&pi->vfs_inode);
- }
- }
-
- psb->trans_scan_timeout = psb->drop_scan_timeout = 0;
- cancel_delayed_work_sync(&psb->dwork);
- cancel_delayed_work_sync(&psb->drop_dwork);
- flush_scheduled_work();
-
- dprintk("%s: stopped workqueues.\n", __func__);
-
- pohmelfs_crypto_exit(psb);
- pohmelfs_state_exit(psb);
-
- bdi_destroy(&psb->bdi);
-
- kfree(psb);
- sb->s_fs_info = NULL;
-}
-
-static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
- struct super_block *sb = dentry->d_sb;
- struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-
- /*
- * There are no filesystem size limits yet.
- */
- memset(buf, 0, sizeof(struct kstatfs));
-
- buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */
- buf->f_bsize = sb->s_blocksize;
- buf->f_files = psb->ino;
- buf->f_namelen = 255;
- buf->f_files = atomic_long_read(&psb->total_inodes);
- buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT;
- buf->f_blocks = psb->total_size >> PAGE_SHIFT;
-
- dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n",
- __func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize);
-
- return 0;
-}
-
-static int pohmelfs_show_options(struct seq_file *seq, struct dentry *root)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
-
- seq_printf(seq, ",idx=%u", psb->idx);
- seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout));
- seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout));
- seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout));
- seq_printf(seq, ",trans_retries=%u", psb->trans_retries);
- seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num);
- seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages);
- seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout));
- if (psb->crypto_fail_unsupported)
- seq_printf(seq, ",crypto_fail_unsupported");
-
- return 0;
-}
-
-enum {
- pohmelfs_opt_idx,
- pohmelfs_opt_crypto_thread_num,
- pohmelfs_opt_trans_max_pages,
- pohmelfs_opt_crypto_fail_unsupported,
-
- /* Remountable options */
- pohmelfs_opt_trans_scan_timeout,
- pohmelfs_opt_drop_scan_timeout,
- pohmelfs_opt_wait_on_page_timeout,
- pohmelfs_opt_trans_retries,
- pohmelfs_opt_mcache_timeout,
-};
-
-static struct match_token pohmelfs_tokens[] = {
- {pohmelfs_opt_idx, "idx=%u"},
- {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
- {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
- {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
- {pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"},
- {pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"},
- {pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"},
- {pohmelfs_opt_trans_retries, "trans_retries=%u"},
- {pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"},
-};
-
-static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option, err;
-
- if (!options)
- return 0;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token;
- if (!*p)
- continue;
-
- token = match_token(p, pohmelfs_tokens, args);
-
- err = match_int(&args[0], &option);
- if (err)
- return err;
-
- if (remount && token <= pohmelfs_opt_crypto_fail_unsupported)
- continue;
-
- switch (token) {
- case pohmelfs_opt_idx:
- psb->idx = option;
- break;
- case pohmelfs_opt_trans_scan_timeout:
- psb->trans_scan_timeout = msecs_to_jiffies(option);
- break;
- case pohmelfs_opt_drop_scan_timeout:
- psb->drop_scan_timeout = msecs_to_jiffies(option);
- break;
- case pohmelfs_opt_wait_on_page_timeout:
- psb->wait_on_page_timeout = msecs_to_jiffies(option);
- break;
- case pohmelfs_opt_mcache_timeout:
- psb->mcache_timeout = msecs_to_jiffies(option);
- break;
- case pohmelfs_opt_trans_retries:
- psb->trans_retries = option;
- break;
- case pohmelfs_opt_crypto_thread_num:
- psb->crypto_thread_num = option;
- break;
- case pohmelfs_opt_trans_max_pages:
- psb->trans_max_pages = option;
- break;
- case pohmelfs_opt_crypto_fail_unsupported:
- psb->crypto_fail_unsupported = 1;
- break;
- default:
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
-{
- int err;
- struct pohmelfs_sb *psb = POHMELFS_SB(sb);
- unsigned long old_sb_flags = sb->s_flags;
-
- err = pohmelfs_parse_options(data, psb, 1);
- if (err)
- goto err_out_restore;
-
- if (!(*flags & MS_RDONLY))
- sb->s_flags &= ~MS_RDONLY;
- return 0;
-
-err_out_restore:
- sb->s_flags = old_sb_flags;
- return err;
-}
-
-static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count)
-{
- struct inode *inode = &pi->vfs_inode;
-
- dprintk("%s: %p: ino: %llu, owned: %d.\n",
- __func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state));
-
- mutex_lock(&inode->i_mutex);
- if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) {
- filemap_fdatawrite(inode->i_mapping);
- inode->i_sb->s_op->write_inode(inode, 0);
- }
-
-#ifdef POHMELFS_TRUNCATE_ON_INODE_FLUSH
- truncate_inode_pages(inode->i_mapping, 0);
-#endif
-
- pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
- mutex_unlock(&inode->i_mutex);
-}
-
-static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count)
-{
- dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
- __func__, pi->ino, pi, &pi->vfs_inode, count);
-
- if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state))
- pohmelfs_flush_inode(pi, count);
-
- while (count--)
- iput(&pi->vfs_inode);
-}
-
-static void pohmelfs_drop_scan(struct work_struct *work)
-{
- struct pohmelfs_sb *psb =
- container_of(work, struct pohmelfs_sb, drop_dwork.work);
- struct pohmelfs_inode *pi;
- unsigned int count = 0;
-
- while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count)))
- pohmelfs_put_inode_count(pi, count);
-
- pohmelfs_check_states(psb);
-
- if (psb->drop_scan_timeout)
- schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-}
-
-/*
- * Run through all transactions starting from the oldest,
- * drop transaction from current state and try to send it
- * to all remote nodes, which are currently installed.
- */
-static void pohmelfs_trans_scan_state(struct netfs_state *st)
-{
- struct rb_node *rb_node;
- struct netfs_trans_dst *dst;
- struct pohmelfs_sb *psb = st->psb;
- unsigned int timeout = psb->trans_scan_timeout;
- struct netfs_trans *t;
- int err;
-
- mutex_lock(&st->trans_lock);
- for (rb_node = rb_first(&st->trans_root); rb_node; ) {
- dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
- t = dst->trans;
-
- if (timeout && time_after(dst->send_time + timeout, jiffies)
- && dst->retries == 0)
- break;
-
- dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n",
- __func__, t, t->gen, st, dst->retries, psb->trans_retries);
- netfs_trans_get(t);
-
- rb_node = rb_next(rb_node);
-
- err = -ETIMEDOUT;
- if (timeout && (++dst->retries < psb->trans_retries))
- err = netfs_trans_resend(t, psb);
-
- if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) {
- if (netfs_trans_remove_nolock(dst, st))
- netfs_trans_drop_dst_nostate(dst);
- }
-
- t->result = err;
- netfs_trans_put(t);
- }
- mutex_unlock(&st->trans_lock);
-}
-
-/*
- * Walk through all installed network states and resend all
- * transactions, which are old enough.
- */
-static void pohmelfs_trans_scan(struct work_struct *work)
-{
- struct pohmelfs_sb *psb =
- container_of(work, struct pohmelfs_sb, dwork.work);
- struct netfs_state *st;
- struct pohmelfs_config *c;
-
- mutex_lock(&psb->state_lock);
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
-
- pohmelfs_trans_scan_state(st);
- }
- mutex_unlock(&psb->state_lock);
-
- /*
- * If no timeout specified then system is in the middle of umount process,
- * so no need to reschedule scanning process again.
- */
- if (psb->trans_scan_timeout)
- schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-}
-
-int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
- unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start)
-{
- struct inode *inode = &pi->vfs_inode;
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- int err = 0, sz;
- struct netfs_trans *t;
- int path_len, addon_len = 0;
- void *data;
- struct netfs_inode_info *info;
- struct netfs_cmd *cmd;
-
- dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon);
-
- path_len = pohmelfs_path_length(pi);
- if (path_len < 0) {
- err = path_len;
- goto err_out_exit;
- }
-
- if (addon)
- addon_len = strlen(addon) + 1; /* 0-byte */
- sz = addon_len;
-
- if (cmd_op == NETFS_INODE_INFO)
- sz += sizeof(struct netfs_inode_info);
-
- t = netfs_trans_alloc(psb, sz + path_len, flags, 0);
- if (!t) {
- err = -ENOMEM;
- goto err_out_exit;
- }
- t->complete = complete;
- t->private = priv;
-
- cmd = netfs_trans_current(t);
- data = (void *)(cmd + 1);
-
- if (cmd_op == NETFS_INODE_INFO) {
- info = (struct netfs_inode_info *)(cmd + 1);
- data = (void *)(info + 1);
-
- /*
- * We are under i_mutex, can read and change whatever we want...
- */
- info->mode = inode->i_mode;
- info->nlink = inode->i_nlink;
- info->uid = inode->i_uid;
- info->gid = inode->i_gid;
- info->blocks = inode->i_blocks;
- info->rdev = inode->i_rdev;
- info->size = inode->i_size;
- info->version = inode->i_version;
-
- netfs_convert_inode_info(info);
- }
-
- path_len = pohmelfs_construct_path_string(pi, data, path_len);
- if (path_len < 0)
- goto err_out_free;
-
- dprintk("%s: path_len: %d.\n", __func__, path_len);
-
- if (addon) {
- path_len--; /* Do not place null-byte before the addon */
- path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */
- }
-
- sz += path_len;
-
- cmd->cmd = cmd_op;
- cmd->ext = path_len;
- cmd->size = sz;
- cmd->id = id;
- cmd->start = start;
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, sz);
-
- /*
- * Note, that it is possible to leak error here: transaction callback will not
- * be invoked for allocation path failure.
- */
- return netfs_trans_finish(t, psb);
-
-err_out_free:
- netfs_trans_free(t);
-err_out_exit:
- if (complete)
- complete(NULL, 0, priv, err);
- return err;
-}
-
-int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
- netfs_trans_complete_t complete, void *priv, u64 start)
-{
- return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start);
-}
-
-/*
- * Send request and wait for POHMELFS root capabilities response,
- * which will update server's informaion about size of the export,
- * permissions, number of objects, available size and so on.
- */
-static int pohmelfs_root_handshake(struct pohmelfs_sb *psb)
-{
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- int err = -ENOMEM;
-
- t = netfs_trans_alloc(psb, 0, 0, 0);
- if (!t)
- goto err_out_exit;
-
- cmd = netfs_trans_current(t);
-
- cmd->cmd = NETFS_CAPABILITIES;
- cmd->id = POHMELFS_ROOT_CAPABILITIES;
- cmd->size = 0;
- cmd->start = 0;
- cmd->ext = 0;
- cmd->csize = 0;
-
- netfs_convert_cmd(cmd);
- netfs_trans_update(cmd, t, 0);
-
- err = netfs_trans_finish(t, psb);
- if (err)
- goto err_out_exit;
-
- psb->flags = ~0;
- err = wait_event_interruptible_timeout(psb->wait,
- (psb->flags != ~0),
- psb->wait_on_page_timeout);
- if (!err)
- err = -ETIMEDOUT;
- else if (err > 0)
- err = -psb->flags;
-
- if (err)
- goto err_out_exit;
-
- return 0;
-
-err_out_exit:
- return err;
-}
-
-static int pohmelfs_show_stats(struct seq_file *m, struct dentry *root)
-{
- struct netfs_state *st;
- struct pohmelfs_ctl *ctl;
- struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
- struct pohmelfs_config *c;
-
- mutex_lock(&psb->state_lock);
-
- seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n");
-
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
- ctl = &st->ctl;
-
- seq_printf(m, "%u ", ctl->idx);
- if (ctl->addr.sa_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
- seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
- } else if (ctl->addr.sa_family == AF_INET6) {
- struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
- seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
- } else {
- unsigned int i;
- for (i = 0; i < ctl->addrlen; ++i)
- seq_printf(m, "%02x.", ctl->addr.addr[i]);
- }
-
- seq_printf(m, " %u %u %d %u %x\n",
- ctl->type, ctl->proto,
- st->socket != NULL,
- ctl->prio, ctl->perm);
- }
- mutex_unlock(&psb->state_lock);
-
- return 0;
-}
-
-static const struct super_operations pohmelfs_sb_ops = {
- .alloc_inode = pohmelfs_alloc_inode,
- .destroy_inode = pohmelfs_destroy_inode,
- .drop_inode = pohmelfs_drop_inode,
- .write_inode = pohmelfs_write_inode,
- .put_super = pohmelfs_put_super,
- .remount_fs = pohmelfs_remount,
- .statfs = pohmelfs_statfs,
- .show_options = pohmelfs_show_options,
- .show_stats = pohmelfs_show_stats,
-};
-
-/*
- * Allocate private superblock and create root dir.
- */
-static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct pohmelfs_sb *psb;
- int err = -ENOMEM;
- struct inode *root;
- struct pohmelfs_inode *npi;
- struct qstr str;
-
- psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL);
- if (!psb)
- goto err_out_exit;
-
- err = bdi_init(&psb->bdi);
- if (err)
- goto err_out_free_sb;
-
- err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
- if (err) {
- bdi_destroy(&psb->bdi);
- goto err_out_free_sb;
- }
-
- sb->s_fs_info = psb;
- sb->s_op = &pohmelfs_sb_ops;
- sb->s_magic = POHMELFS_MAGIC_NUM;
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_blocksize = PAGE_SIZE;
- sb->s_bdi = &psb->bdi;
-
- psb->sb = sb;
-
- psb->ino = 2;
- psb->idx = 0;
- psb->active_state = NULL;
- psb->trans_retries = 5;
- psb->trans_data_size = PAGE_SIZE;
- psb->drop_scan_timeout = msecs_to_jiffies(1000);
- psb->trans_scan_timeout = msecs_to_jiffies(5000);
- psb->wait_on_page_timeout = msecs_to_jiffies(5000);
- init_waitqueue_head(&psb->wait);
-
- spin_lock_init(&psb->ino_lock);
-
- INIT_LIST_HEAD(&psb->drop_list);
-
- mutex_init(&psb->mcache_lock);
- psb->mcache_root = RB_ROOT;
- psb->mcache_timeout = msecs_to_jiffies(5000);
- atomic_long_set(&psb->mcache_gen, 0);
-
- psb->trans_max_pages = 100;
-
- psb->crypto_align_size = 16;
- psb->crypto_attached_size = 0;
- psb->hash_strlen = 0;
- psb->cipher_strlen = 0;
- psb->perform_crypto = 0;
- psb->crypto_thread_num = 2;
- psb->crypto_fail_unsupported = 0;
- mutex_init(&psb->crypto_thread_lock);
- INIT_LIST_HEAD(&psb->crypto_ready_list);
- INIT_LIST_HEAD(&psb->crypto_active_list);
-
- atomic_set(&psb->trans_gen, 1);
- atomic_long_set(&psb->total_inodes, 0);
-
- mutex_init(&psb->state_lock);
- INIT_LIST_HEAD(&psb->state_list);
-
- err = pohmelfs_parse_options((char *) data, psb, 0);
- if (err)
- goto err_out_free_bdi;
-
- err = pohmelfs_copy_crypto(psb);
- if (err)
- goto err_out_free_bdi;
-
- err = pohmelfs_state_init(psb);
- if (err)
- goto err_out_free_strings;
-
- err = pohmelfs_crypto_init(psb);
- if (err)
- goto err_out_state_exit;
-
- err = pohmelfs_root_handshake(psb);
- if (err)
- goto err_out_crypto_exit;
-
- str.name = "/";
- str.hash = jhash("/", 1, 0);
- str.len = 1;
-
- npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR);
- if (IS_ERR(npi)) {
- err = PTR_ERR(npi);
- goto err_out_crypto_exit;
- }
- set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
- clear_bit(NETFS_INODE_OWNED, &npi->state);
-
- root = &npi->vfs_inode;
-
- sb->s_root = d_alloc_root(root);
- if (!sb->s_root)
- goto err_out_put_root;
-
- INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan);
- schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-
- INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan);
- schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-
- return 0;
-
-err_out_put_root:
- iput(root);
-err_out_crypto_exit:
- pohmelfs_crypto_exit(psb);
-err_out_state_exit:
- pohmelfs_state_exit(psb);
-err_out_free_strings:
- kfree(psb->cipher_string);
- kfree(psb->hash_string);
-err_out_free_bdi:
- bdi_destroy(&psb->bdi);
-err_out_free_sb:
- kfree(psb);
-err_out_exit:
-
- dprintk("%s: err: %d.\n", __func__, err);
- return err;
-}
-
-/*
- * Some VFS magic here...
- */
-static struct dentry *pohmelfs_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return mount_nodev(fs_type, flags, data, pohmelfs_fill_super);
-}
-
-/*
- * We need this to sync all inodes earlier, since when writeback
- * is invoked from the umount/mntput path dcache is already shrunk,
- * see generic_shutdown_super(), and no inodes can access the path.
- */
-static void pohmelfs_kill_super(struct super_block *sb)
-{
- sync_inodes_sb(sb);
- kill_anon_super(sb);
-}
-
-static struct file_system_type pohmel_fs_type = {
- .owner = THIS_MODULE,
- .name = "pohmel",
- .mount = pohmelfs_mount,
- .kill_sb = pohmelfs_kill_super,
-};
-
-/*
- * Cache and module initializations and freeing routings.
- */
-static void pohmelfs_init_once(void *data)
-{
- struct pohmelfs_inode *pi = data;
-
- inode_init_once(&pi->vfs_inode);
-}
-
-static int __init pohmelfs_init_inodecache(void)
-{
- pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache",
- sizeof(struct pohmelfs_inode),
- 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
- pohmelfs_init_once);
- if (!pohmelfs_inode_cache)
- return -ENOMEM;
-
- return 0;
-}
-
-static void pohmelfs_destroy_inodecache(void)
-{
- kmem_cache_destroy(pohmelfs_inode_cache);
-}
-
-static int __init init_pohmel_fs(void)
-{
- int err;
-
- err = pohmelfs_config_init();
- if (err)
- goto err_out_exit;
-
- err = pohmelfs_init_inodecache();
- if (err)
- goto err_out_config_exit;
-
- err = pohmelfs_mcache_init();
- if (err)
- goto err_out_destroy;
-
- err = netfs_trans_init();
- if (err)
- goto err_out_mcache_exit;
-
- err = register_filesystem(&pohmel_fs_type);
- if (err)
- goto err_out_trans;
-
- return 0;
-
-err_out_trans:
- netfs_trans_exit();
-err_out_mcache_exit:
- pohmelfs_mcache_exit();
-err_out_destroy:
- pohmelfs_destroy_inodecache();
-err_out_config_exit:
- pohmelfs_config_exit();
-err_out_exit:
- return err;
-}
-
-static void __exit exit_pohmel_fs(void)
-{
- unregister_filesystem(&pohmel_fs_type);
- pohmelfs_destroy_inodecache();
- pohmelfs_mcache_exit();
- pohmelfs_config_exit();
- netfs_trans_exit();
-}
-
-module_init(init_pohmel_fs);
-module_exit(exit_pohmel_fs);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_DESCRIPTION("Pohmel filesystem");
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c
deleted file mode 100644
index 6710114cd425..000000000000
--- a/drivers/staging/pohmelfs/lock.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/backing-dev.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
- u64 id, u64 start, u32 size, int type)
-{
- struct inode *inode = &pi->vfs_inode;
- struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
- struct netfs_trans *t;
- struct netfs_cmd *cmd;
- int path_len, err;
- void *data;
- struct netfs_lock *l;
- int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info);
-
- err = pohmelfs_path_length(pi);
- if (err < 0)
- goto err_out_exit;
-
- path_len = err;
-
- err = -ENOMEM;
- t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
- NETFS_TRANS_SINGLE_DST, 0);
- if (!t)
- goto err_out_exit;
-
- cmd = netfs_trans_current(t);
- data = cmd + 1;
-
- err = pohmelfs_construct_path_string(pi, data, path_len);
- if (err < 0)
- goto err_out_free;
- path_len = err;
-
- l = data + path_len;
-
- l->start = start;
- l->size = size;
- l->type = type;
- l->ino = pi->ino;
-
- cmd->cmd = NETFS_LOCK;
- cmd->start = 0;
- cmd->id = id;
- cmd->size = sizeof(struct netfs_lock) + path_len + isize;
- cmd->ext = path_len;
- cmd->csize = 0;
-
- netfs_convert_cmd(cmd);
- netfs_convert_lock(l);
-
- if (isize) {
- struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1);
-
- info->mode = inode->i_mode;
- info->nlink = inode->i_nlink;
- info->uid = inode->i_uid;
- info->gid = inode->i_gid;
- info->blocks = inode->i_blocks;
- info->rdev = inode->i_rdev;
- info->size = inode->i_size;
- info->version = inode->i_version;
-
- netfs_convert_inode_info(info);
- }
-
- netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize);
-
- return netfs_trans_finish(t, psb);
-
-err_out_free:
- netfs_trans_free(t);
-err_out_exit:
- printk("%s: err: %d.\n", __func__, err);
- return err;
-}
-
-int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
- struct pohmelfs_mcache *m;
- int err = -ENOMEM;
- struct iattr iattr;
- struct inode *inode = &pi->vfs_inode;
-
- dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
- "type: %d, locked as: %d, owned: %d.\n",
- __func__, &pi->vfs_inode, pi->ino,
- start, size, type, pi->lock_type,
- !!test_bit(NETFS_INODE_OWNED, &pi->state));
-
- if (!pohmelfs_need_lock(pi, type))
- return 0;
-
- m = pohmelfs_mcache_alloc(psb, start, size, NULL);
- if (IS_ERR(m))
- return PTR_ERR(m);
-
- err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
- type | POHMELFS_LOCK_GRAB);
- if (err)
- goto err_out_put;
-
- err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
- if (err)
- err = m->err;
- else
- err = -ETIMEDOUT;
-
- if (err) {
- printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
- __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
- }
-
- if (err && (err != -ENOENT))
- goto err_out_put;
-
- if (!err) {
- netfs_convert_inode_info(&m->info);
-
- iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
- iattr.ia_mode = m->info.mode;
- iattr.ia_uid = m->info.uid;
- iattr.ia_gid = m->info.gid;
- iattr.ia_size = m->info.size;
- iattr.ia_atime = CURRENT_TIME;
-
- dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
- __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);
-
- err = pohmelfs_setattr_raw(inode, &iattr);
- if (!err) {
- struct dentry *dentry = d_find_alias(inode);
- if (dentry) {
- fsnotify_change(dentry, iattr.ia_valid);
- dput(dentry);
- }
- }
- }
-
- pi->lock_type = type;
- set_bit(NETFS_INODE_OWNED, &pi->state);
-
- pohmelfs_mcache_put(psb, m);
-
- return 0;
-
-err_out_put:
- pohmelfs_mcache_put(psb, m);
- return err;
-}
-
-int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
- dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
- __func__, &pi->vfs_inode, pi->ino, start, size, type);
- pi->lock_type = 0;
- clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state);
- clear_bit(NETFS_INODE_OWNED, &pi->state);
- return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type);
-}
diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c
deleted file mode 100644
index e22665cdd16c..000000000000
--- a/drivers/staging/pohmelfs/mcache.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *pohmelfs_mcache_cache;
-static mempool_t *pohmelfs_mcache_pool;
-
-static inline int pohmelfs_mcache_cmp(u64 gen, u64 new)
-{
- if (gen < new)
- return 1;
- if (gen > new)
- return -1;
- return 0;
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen)
-{
- struct rb_root *root = &psb->mcache_root;
- struct rb_node *n = root->rb_node;
- struct pohmelfs_mcache *tmp, *ret = NULL;
- int cmp;
-
- while (n) {
- tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry);
-
- cmp = pohmelfs_mcache_cmp(tmp->gen, gen);
- if (cmp < 0)
- n = n->rb_left;
- else if (cmp > 0)
- n = n->rb_right;
- else {
- ret = tmp;
- pohmelfs_mcache_get(ret);
- break;
- }
- }
-
- return ret;
-}
-
-static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
- struct rb_root *root = &psb->mcache_root;
- struct rb_node **n = &root->rb_node, *parent = NULL;
- struct pohmelfs_mcache *ret = NULL, *tmp;
- int cmp;
-
- while (*n) {
- parent = *n;
-
- tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry);
-
- cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen);
- if (cmp < 0)
- n = &parent->rb_left;
- else if (cmp > 0)
- n = &parent->rb_right;
- else {
- ret = tmp;
- break;
- }
- }
-
- if (ret)
- return -EEXIST;
-
- rb_link_node(&m->mcache_entry, parent, n);
- rb_insert_color(&m->mcache_entry, root);
-
- return 0;
-}
-
-static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
- if (m && m->mcache_entry.rb_parent_color) {
- rb_erase(&m->mcache_entry, &psb->mcache_root);
- m->mcache_entry.rb_parent_color = 0;
- return 1;
- }
- return 0;
-}
-
-void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
- mutex_lock(&psb->mcache_lock);
- pohmelfs_mcache_remove(psb, m);
- mutex_unlock(&psb->mcache_lock);
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
- unsigned int size, void *data)
-{
- struct pohmelfs_mcache *m;
- int err = -ENOMEM;
-
- m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL);
- if (!m)
- goto err_out_exit;
-
- init_completion(&m->complete);
- m->err = 0;
- atomic_set(&m->refcnt, 1);
- m->data = data;
- m->start = start;
- m->size = size;
- m->gen = atomic_long_inc_return(&psb->mcache_gen);
-
- mutex_lock(&psb->mcache_lock);
- err = pohmelfs_mcache_insert(psb, m);
- mutex_unlock(&psb->mcache_lock);
- if (err)
- goto err_out_free;
-
- return m;
-
-err_out_free:
- mempool_free(m, pohmelfs_mcache_pool);
-err_out_exit:
- return ERR_PTR(err);
-}
-
-void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
- pohmelfs_mcache_remove_locked(psb, m);
-
- mempool_free(m, pohmelfs_mcache_pool);
-}
-
-int __init pohmelfs_mcache_init(void)
-{
- pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache",
- sizeof(struct pohmelfs_mcache),
- 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL);
- if (!pohmelfs_mcache_cache)
- goto err_out_exit;
-
- pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache);
- if (!pohmelfs_mcache_pool)
- goto err_out_free;
-
- return 0;
-
-err_out_free:
- kmem_cache_destroy(pohmelfs_mcache_cache);
-err_out_exit:
- return -ENOMEM;
-}
-
-void pohmelfs_mcache_exit(void)
-{
- mempool_destroy(pohmelfs_mcache_pool);
- kmem_cache_destroy(pohmelfs_mcache_cache);
-}
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
deleted file mode 100644
index b2e918622088..000000000000
--- a/drivers/staging/pohmelfs/net.c
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/fsnotify.h>
-#include <linux/jhash.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/syscalls.h>
-#include <linux/vmalloc.h>
-
-#include "netfs.h"
-
-/*
- * Async machinery lives here.
- * All commands being sent to server do _not_ require sync reply,
- * instead, if it is really needed, like readdir or readpage, caller
- * sleeps waiting for data, which will be placed into provided buffer
- * and caller will be awakened.
- *
- * Every command response can come without some listener. For example
- * readdir response will add new objects into cache without appropriate
- * request from userspace. This is used in cache coherency.
- *
- * If object is not found for given data, it is discarded.
- *
- * All requests are received by dedicated kernel thread.
- */
-
-/*
- * Basic network sending/receiving functions.
- * Blocked mode is used.
- */
-static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size)
-{
- struct msghdr msg;
- struct kvec iov;
- int err;
-
- BUG_ON(!size);
-
- iov.iov_base = buf;
- iov.iov_len = size;
-
- msg.msg_iov = (struct iovec *)&iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = MSG_DONTWAIT;
-
- err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
- msg.msg_flags);
- if (err <= 0) {
- printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err);
- if (err == 0)
- err = -ECONNRESET;
- }
-
- return err;
-}
-
-static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size)
-{
- unsigned int revents = 0;
- unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
- unsigned int mask = err_mask | POLLIN;
- int err = 0;
-
- while (size && !err) {
- revents = netfs_state_poll(st);
-
- if (!(revents & mask)) {
- DEFINE_WAIT(wait);
-
- for (;;) {
- prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE);
- if (kthread_should_stop())
- break;
-
- revents = netfs_state_poll(st);
-
- if (revents & mask)
- break;
-
- if (signal_pending(current))
- break;
-
- schedule();
- continue;
- }
- finish_wait(&st->thread_wait, &wait);
- }
-
- err = 0;
- netfs_state_lock(st);
- if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) {
- err = netfs_data_recv(st, data, size);
- if (err > 0) {
- data += err;
- size -= err;
- err = 0;
- } else if (err == 0)
- err = -ECONNRESET;
- }
-
- if (revents & err_mask) {
- printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
- __func__, revents, st->socket, size, err);
- err = -ECONNRESET;
- }
- netfs_state_unlock(st);
-
- if (err < 0) {
- if (netfs_state_trylock_send(st)) {
- netfs_state_exit(st);
- err = netfs_state_init(st);
- if (!err)
- err = -EAGAIN;
- netfs_state_unlock_send(st);
- } else {
- st->need_reset = 1;
- }
- }
-
- if (kthread_should_stop())
- err = -ENODEV;
-
- if (err)
- printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
- "should_stop: %d, size: %u, err: %d.\n",
- __func__, st->socket, st->read_socket,
- revents, revents & err_mask, kthread_should_stop(), size, err);
- }
-
- return err;
-}
-
-int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size)
-{
- struct netfs_cmd *cmd = &st->cmd;
- int err;
-
- err = pohmelfs_data_recv(st, data, size);
- if (err)
- return err;
-
- return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size);
-}
-
-/*
- * Polling machinery.
- */
-
-struct netfs_poll_helper {
- poll_table pt;
- struct netfs_state *st;
-};
-
-static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
- struct netfs_state *st = container_of(wait, struct netfs_state, wait);
-
- wake_up(&st->thread_wait);
- return 1;
-}
-
-static void netfs_queue_func(struct file *file, wait_queue_head_t *whead,
- poll_table *pt)
-{
- struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st;
-
- st->whead = whead;
- init_waitqueue_func_entry(&st->wait, netfs_queue_wake);
- add_wait_queue(whead, &st->wait);
-}
-
-static void netfs_poll_exit(struct netfs_state *st)
-{
- if (st->whead) {
- remove_wait_queue(st->whead, &st->wait);
- st->whead = NULL;
- }
-}
-
-static int netfs_poll_init(struct netfs_state *st)
-{
- struct netfs_poll_helper ph;
-
- ph.st = st;
- init_poll_funcptr(&ph.pt, &netfs_queue_func);
-
- st->socket->ops->poll(NULL, st->socket, &ph.pt);
- return 0;
-}
-
-/*
- * Get response for readpage command. We search inode and page in its mapping
- * and copy data into. If it was async request, then we queue page into shared
- * data and wakeup listener, who will copy it to userspace.
- *
- * There is a work in progress of allowing to call copy_to_user() directly from
- * async receiving kernel thread.
- */
-static int pohmelfs_read_page_response(struct netfs_state *st)
-{
- struct pohmelfs_sb *psb = st->psb;
- struct netfs_cmd *cmd = &st->cmd;
- struct inode *inode;
- struct page *page;
- int err = 0;
-
- if (cmd->size > PAGE_CACHE_SIZE) {
- err = -EINVAL;
- goto err_out_exit;
- }
-
- inode = ilookup(st->psb->sb, cmd->id);
- if (!inode) {
- printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
- err = -ENOENT;
- goto err_out_exit;
- }
-
- page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT);
- if (!page || !PageLocked(page)) {
- printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
- __func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT);
-
- while (cmd->size) {
- unsigned int sz = min(cmd->size, st->size);
-
- err = pohmelfs_data_recv(st, st->data, sz);
- if (err)
- break;
-
- cmd->size -= sz;
- }
-
- err = -ENODEV;
- if (page)
- goto err_out_page_put;
- goto err_out_put;
- }
-
- if (cmd->size) {
- void *addr;
-
- addr = kmap(page);
- err = pohmelfs_data_recv(st, addr, cmd->size);
- kunmap(page);
-
- if (err)
- goto err_out_page_unlock;
- }
-
- dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
- __func__, page, cmd->start, cmd->size, PageLocked(page));
-
- SetPageChecked(page);
- if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) {
- err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv);
- if (err < 0)
- goto err_out_page_unlock;
- } else {
- SetPageUptodate(page);
- unlock_page(page);
- page_cache_release(page);
- }
-
- pohmelfs_put_inode(POHMELFS_I(inode));
- wake_up(&st->psb->wait);
-
- return 0;
-
-err_out_page_unlock:
- SetPageError(page);
- unlock_page(page);
-err_out_page_put:
- page_cache_release(page);
-err_out_put:
- pohmelfs_put_inode(POHMELFS_I(inode));
-err_out_exit:
- wake_up(&st->psb->wait);
- return err;
-}
-
-static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str,
- struct netfs_inode_info *info)
-{
- struct inode *inode;
- struct pohmelfs_name *n;
- int err = 0;
- u64 ino = 0;
-
- mutex_lock(&parent->offset_lock);
- n = pohmelfs_search_hash(parent, str->hash);
- if (n)
- ino = n->ino;
- mutex_unlock(&parent->offset_lock);
-
- if (!ino)
- goto out;
-
- inode = ilookup(parent->vfs_inode.i_sb, ino);
- if (!inode)
- goto out;
-
- dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino);
-
- pohmelfs_fill_inode(inode, info);
- pohmelfs_put_inode(POHMELFS_I(inode));
- err = -EEXIST;
-out:
- return err;
-}
-
-/*
- * Readdir response from server. If special field is set, we wakeup
- * listener (readdir() call), which will copy data to userspace.
- */
-static int pohmelfs_readdir_response(struct netfs_state *st)
-{
- struct inode *inode;
- struct netfs_cmd *cmd = &st->cmd;
- struct netfs_inode_info *info;
- struct pohmelfs_inode *parent = NULL, *npi;
- int err = 0, last = cmd->ext;
- struct qstr str;
-
- if (cmd->size > st->size)
- return -EINVAL;
-
- inode = ilookup(st->psb->sb, cmd->id);
- if (!inode) {
- printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
- return -ENOENT;
- }
- parent = POHMELFS_I(inode);
-
- if (!cmd->size && cmd->start) {
- err = -cmd->start;
- goto out;
- }
-
- if (cmd->size) {
- char *name;
-
- err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
- if (err)
- goto err_out_put;
-
- info = (struct netfs_inode_info *)(st->data);
-
- name = (char *)(info + 1);
- str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
- name[str.len] = 0;
- str.name = name;
- str.hash = jhash(str.name, str.len, 0);
-
- netfs_convert_inode_info(info);
-
- if (parent) {
- err = pohmelfs_check_name(parent, &str, info);
- if (err) {
- if (err == -EEXIST)
- err = 0;
- goto out;
- }
- }
-
- info->ino = cmd->start;
- if (!info->ino)
- info->ino = pohmelfs_new_ino(st->psb);
-
- dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
- __func__, parent->ino, info->ino, str.name, str.hash, str.len,
- info->mode);
-
- npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
- if (IS_ERR(npi)) {
- err = PTR_ERR(npi);
-
- if (err != -EEXIST)
- goto err_out_put;
- } else {
- struct dentry *dentry, *alias, *pd;
-
- set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
- clear_bit(NETFS_INODE_OWNED, &npi->state);
-
- pd = d_find_alias(&parent->vfs_inode);
- if (pd) {
- str.hash = full_name_hash(str.name, str.len);
- dentry = d_alloc(pd, &str);
- if (dentry) {
- alias = d_materialise_unique(dentry, &npi->vfs_inode);
- if (alias)
- dput(alias);
- }
-
- dput(dentry);
- dput(pd);
- }
- }
- }
-out:
- if (last) {
- set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
- set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state);
- wake_up(&st->psb->wait);
- }
- pohmelfs_put_inode(parent);
-
- return err;
-
-err_out_put:
- clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
- printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id);
- pohmelfs_put_inode(parent);
- wake_up(&st->psb->wait);
- return err;
-}
-
-/*
- * Lookup command response.
- * It searches for inode to be looked at (if it exists) and substitutes
- * its inode information (size, permission, mode and so on), if inode does
- * not exist, new one will be created and inserted into caches.
- */
-static int pohmelfs_lookup_response(struct netfs_state *st)
-{
- struct inode *inode = NULL;
- struct netfs_cmd *cmd = &st->cmd;
- struct netfs_inode_info *info;
- struct pohmelfs_inode *parent = NULL, *npi;
- int err = -EINVAL;
- char *name;
-
- inode = ilookup(st->psb->sb, cmd->id);
- if (!inode) {
- printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
- __func__, cmd->id, cmd->start, cmd->size);
- err = -ENOENT;
- goto err_out_exit;
- }
- parent = POHMELFS_I(inode);
-
- if (!cmd->size) {
- err = -cmd->start;
- goto err_out_put;
- }
-
- if (cmd->size < sizeof(struct netfs_inode_info)) {
- printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
- __func__, cmd->id, cmd->start, cmd->size);
- err = -EINVAL;
- goto err_out_put;
- }
-
- err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
- if (err)
- goto err_out_put;
-
- info = (struct netfs_inode_info *)(st->data);
- name = (char *)(info + 1);
-
- netfs_convert_inode_info(info);
-
- info->ino = cmd->start;
- if (!info->ino)
- info->ino = pohmelfs_new_ino(st->psb);
-
- dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
- __func__, parent->ino, info->ino, name, cmd->start);
-
- if (cmd->start)
- npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0);
- else {
- struct qstr str;
-
- str.name = name;
- str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
- str.hash = jhash(name, str.len, 0);
-
- npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
- }
- if (IS_ERR(npi)) {
- err = PTR_ERR(npi);
-
- if (err != -EEXIST)
- goto err_out_put;
- } else {
- set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
- clear_bit(NETFS_INODE_OWNED, &npi->state);
- }
-
- clear_bit(NETFS_COMMAND_PENDING, &parent->state);
- pohmelfs_put_inode(parent);
-
- wake_up(&st->psb->wait);
-
- return 0;
-
-err_out_put:
- pohmelfs_put_inode(parent);
-err_out_exit:
- clear_bit(NETFS_COMMAND_PENDING, &parent->state);
- wake_up(&st->psb->wait);
- printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
- __func__, inode, cmd->id, cmd->start, cmd->size, err);
- return err;
-}
-
-/*
- * Create response, just marks local inode as 'created', so that writeback
- * for any of its children (or own) would not try to sync it again.
- */
-static int pohmelfs_create_response(struct netfs_state *st)
-{
- struct inode *inode;
- struct netfs_cmd *cmd = &st->cmd;
- struct pohmelfs_inode *pi;
-
- inode = ilookup(st->psb->sb, cmd->id);
- if (!inode) {
- printk("%s: failed to find inode: id: %llu, start: %llu.\n",
- __func__, cmd->id, cmd->start);
- goto err_out_exit;
- }
-
- pi = POHMELFS_I(inode);
-
- /*
- * To lock or not to lock?
- * We actually do not care if it races...
- */
- if (cmd->start)
- make_bad_inode(inode);
- set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
- pohmelfs_put_inode(pi);
-
- wake_up(&st->psb->wait);
- return 0;
-
-err_out_exit:
- wake_up(&st->psb->wait);
- return -ENOENT;
-}
-
-/*
- * Object remove response. Just says that remove request has been received.
- * Used in cache coherency protocol.
- */
-static int pohmelfs_remove_response(struct netfs_state *st)
-{
- struct netfs_cmd *cmd = &st->cmd;
- int err;
-
- err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
- if (err)
- return err;
-
- dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data);
-
- return 0;
-}
-
-/*
- * Transaction reply processing.
- *
- * Find transaction based on its generation number, bump its reference counter,
- * so that none could free it under us, drop from the trees and lists and
- * drop reference counter. When it hits zero (when all destinations replied
- * and all timeout handled by async scanning code), completion will be called
- * and transaction will be freed.
- */
-static int pohmelfs_transaction_response(struct netfs_state *st)
-{
- struct netfs_trans_dst *dst;
- struct netfs_trans *t = NULL;
- struct netfs_cmd *cmd = &st->cmd;
- short err = (signed)cmd->ext;
-
- mutex_lock(&st->trans_lock);
- dst = netfs_trans_search(st, cmd->start);
- if (dst) {
- netfs_trans_remove_nolock(dst, st);
- t = dst->trans;
- }
- mutex_unlock(&st->trans_lock);
-
- if (!t) {
- printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
- __func__, cmd->start, cmd->id, cmd->size, cmd->ext);
- err = -EINVAL;
- goto out;
- }
-
- t->result = err;
- netfs_trans_drop_dst_nostate(dst);
-
-out:
- wake_up(&st->psb->wait);
- return err;
-}
-
-/*
- * Inode metadata cache coherency message.
- */
-static int pohmelfs_page_cache_response(struct netfs_state *st)
-{
- struct netfs_cmd *cmd = &st->cmd;
- struct inode *inode;
-
- dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size);
-
- inode = ilookup(st->psb->sb, cmd->id);
- if (!inode) {
- printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
- return -ENOENT;
- }
-
- set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state);
- pohmelfs_put_inode(POHMELFS_I(inode));
-
- return 0;
-}
-
-/*
- * Root capabilities response: export statistics
- * like used and available size, number of files and dirs,
- * permissions.
- */
-static int pohmelfs_root_cap_response(struct netfs_state *st)
-{
- struct netfs_cmd *cmd = &st->cmd;
- struct netfs_root_capabilities *cap;
- struct pohmelfs_sb *psb = st->psb;
-
- if (cmd->size != sizeof(struct netfs_root_capabilities)) {
- psb->flags = EPROTO;
- wake_up(&psb->wait);
- return -EPROTO;
- }
-
- cap = st->data;
-
- netfs_convert_root_capabilities(cap);
-
- if (psb->total_size < cap->used + cap->avail)
- psb->total_size = cap->used + cap->avail;
- if (cap->avail)
- psb->avail_size = cap->avail;
- psb->state_flags = cap->flags;
-
- if (psb->state_flags & POHMELFS_FLAGS_RO) {
- psb->sb->s_flags |= MS_RDONLY;
- printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx);
- }
-
- if (psb->state_flags & POHMELFS_FLAGS_XATTR)
- printk(KERN_INFO "Mounting POHMELFS (%d) "
- "with extended attributes support.\n", psb->idx);
-
- if (atomic_long_read(&psb->total_inodes) <= 1)
- atomic_long_set(&psb->total_inodes, cap->nr_files);
-
- dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
- __func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files);
-
- psb->flags = 0;
- wake_up(&psb->wait);
- return 0;
-}
-
-/*
- * Crypto capabilities of the server, where it says that
- * it supports or does not requested hash/cipher algorithms.
- */
-static int pohmelfs_crypto_cap_response(struct netfs_state *st)
-{
- struct netfs_cmd *cmd = &st->cmd;
- struct netfs_crypto_capabilities *cap;
- struct pohmelfs_sb *psb = st->psb;
- int err = 0;
-
- if (cmd->size != sizeof(struct netfs_crypto_capabilities)) {
- psb->flags = EPROTO;
- wake_up(&psb->wait);
- return -EPROTO;
- }
-
- cap = st->data;
-
- dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
- __func__,
- psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED",
- psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED");
-
- if (!cap->hash_strlen) {
- if (psb->hash_strlen && psb->crypto_fail_unsupported)
- err = -ENOTSUPP;
- psb->hash_strlen = 0;
- kfree(psb->hash_string);
- psb->hash_string = NULL;
- }
-
- if (!cap->cipher_strlen) {
- if (psb->cipher_strlen && psb->crypto_fail_unsupported)
- err = -ENOTSUPP;
- psb->cipher_strlen = 0;
- kfree(psb->cipher_string);
- psb->cipher_string = NULL;
- }
-
- return err;
-}
-
-/*
- * Capabilities handshake response.
- */
-static int pohmelfs_capabilities_response(struct netfs_state *st)
-{
- struct netfs_cmd *cmd = &st->cmd;
- int err = 0;
-
- err = pohmelfs_data_recv(st, st->data, cmd->size);
- if (err)
- return err;
-
- switch (cmd->id) {
- case POHMELFS_CRYPTO_CAPABILITIES:
- return pohmelfs_crypto_cap_response(st);
- case POHMELFS_ROOT_CAPABILITIES:
- return pohmelfs_root_cap_response(st);
- default:
- break;
- }
- return -EINVAL;
-}
-
-/*
- * Receiving extended attribute.
- * Does not work properly if received size is more than requested one,
- * it should not happen with current request/reply model though.
- */
-static int pohmelfs_getxattr_response(struct netfs_state *st)
-{
- struct pohmelfs_sb *psb = st->psb;
- struct netfs_cmd *cmd = &st->cmd;
- struct pohmelfs_mcache *m;
- short error = (signed short)cmd->ext, err;
- unsigned int sz, total_size;
-
- m = pohmelfs_mcache_search(psb, cmd->id);
-
- dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
- __func__, cmd->id, (m) ? m->gen : 0, error);
-
- if (!m) {
- printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id);
- return -ENOENT;
- }
-
- if (cmd->size) {
- sz = min_t(unsigned int, cmd->size, m->size);
- err = pohmelfs_data_recv_and_check(st, m->data, sz);
- if (err) {
- error = err;
- goto out;
- }
-
- m->size = sz;
- total_size = cmd->size - sz;
-
- while (total_size) {
- sz = min(total_size, st->size);
-
- err = pohmelfs_data_recv_and_check(st, st->data, sz);
- if (err) {
- error = err;
- break;
- }
-
- total_size -= sz;
- }
- }
-
-out:
- m->err = error;
- complete(&m->complete);
- pohmelfs_mcache_put(psb, m);
-
- return error;
-}
-
-int pohmelfs_data_lock_response(struct netfs_state *st)
-{
- struct pohmelfs_sb *psb = st->psb;
- struct netfs_cmd *cmd = &st->cmd;
- struct pohmelfs_mcache *m;
- short err = (signed short)cmd->ext;
- u64 id = cmd->id;
-
- m = pohmelfs_mcache_search(psb, id);
-
- dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
- __func__, cmd->id, (m) ? m->gen : 0, err);
-
- if (!m) {
- pohmelfs_data_recv(st, st->data, cmd->size);
- printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id);
- return -ENOENT;
- }
-
- if (cmd->size)
- err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size);
-
- m->err = err;
- complete(&m->complete);
- pohmelfs_mcache_put(psb, m);
-
- return err;
-}
-
-static void __inline__ netfs_state_reset(struct netfs_state *st)
-{
- netfs_state_lock_send(st);
- netfs_state_exit(st);
- netfs_state_init(st);
- netfs_state_unlock_send(st);
-}
-
-/*
- * Main receiving function, called from dedicated kernel thread.
- */
-static int pohmelfs_recv(void *data)
-{
- int err = -EINTR;
- struct netfs_state *st = data;
- struct netfs_cmd *cmd = &st->cmd;
-
- while (!kthread_should_stop()) {
- /*
- * If socket will be reset after this statement, then
- * pohmelfs_data_recv() will just fail and loop will
- * start again, so it can be done without any locks.
- *
- * st->read_socket is needed to prevents state machine
- * breaking between this data reading and subsequent one
- * in protocol specific functions during connection reset.
- * In case of reset we have to read next command and do
- * not expect data for old command to magically appear in
- * new connection.
- */
- st->read_socket = st->socket;
- err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd));
- if (err) {
- msleep(1000);
- continue;
- }
-
- netfs_convert_cmd(cmd);
-
- dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
- "ext: %u, csize: %u, cpad: %u.\n",
- __func__, cmd->cmd, cmd->id, cmd->start,
- cmd->size, cmd->ext, cmd->csize, cmd->cpad);
-
- if (cmd->csize) {
- struct pohmelfs_crypto_engine *e = &st->eng;
-
- if (unlikely(cmd->csize > e->size/2)) {
- netfs_state_reset(st);
- continue;
- }
-
- if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) {
- dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
- "csize: %u != digest size %u.\n",
- __func__, cmd->cmd, cmd->id, cmd->start, cmd->size,
- cmd->csize, st->psb->crypto_attached_size);
- netfs_state_reset(st);
- continue;
- }
-
- err = pohmelfs_data_recv(st, e->data, cmd->csize);
- if (err) {
- netfs_state_reset(st);
- continue;
- }
-
-#ifdef CONFIG_POHMELFS_DEBUG
- {
- unsigned int i;
- unsigned char *hash = e->data;
-
- dprintk("%s: received hash: ", __func__);
- for (i = 0; i < cmd->csize; ++i)
- printk("%02x ", hash[i]);
-
- printk("\n");
- }
-#endif
- cmd->size -= cmd->csize;
- }
-
- /*
- * This should catch protocol breakage and random garbage instead of commands.
- */
- if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) {
- netfs_state_reset(st);
- continue;
- }
-
- switch (cmd->cmd) {
- case NETFS_READ_PAGE:
- err = pohmelfs_read_page_response(st);
- break;
- case NETFS_READDIR:
- err = pohmelfs_readdir_response(st);
- break;
- case NETFS_LOOKUP:
- err = pohmelfs_lookup_response(st);
- break;
- case NETFS_CREATE:
- err = pohmelfs_create_response(st);
- break;
- case NETFS_REMOVE:
- err = pohmelfs_remove_response(st);
- break;
- case NETFS_TRANS:
- err = pohmelfs_transaction_response(st);
- break;
- case NETFS_PAGE_CACHE:
- err = pohmelfs_page_cache_response(st);
- break;
- case NETFS_CAPABILITIES:
- err = pohmelfs_capabilities_response(st);
- break;
- case NETFS_LOCK:
- err = pohmelfs_data_lock_response(st);
- break;
- case NETFS_XATTR_GET:
- err = pohmelfs_getxattr_response(st);
- break;
- default:
- printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
- __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext);
- netfs_state_reset(st);
- break;
- }
- }
-
- while (!kthread_should_stop())
- schedule_timeout_uninterruptible(msecs_to_jiffies(10));
-
- return err;
-}
-
-int netfs_state_init(struct netfs_state *st)
-{
- int err;
- struct pohmelfs_ctl *ctl = &st->ctl;
-
- err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket);
- if (err) {
- printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
- __func__, ctl->addr.sa_family, ctl->type, ctl->proto, err);
- goto err_out_exit;
- }
-
- st->socket->sk->sk_allocation = GFP_NOIO;
- st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
- err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0);
- if (err) {
- printk("%s: failed to connect to server: idx: %u, err: %d.\n",
- __func__, st->psb->idx, err);
- goto err_out_release;
- }
- st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
- err = netfs_poll_init(st);
- if (err)
- goto err_out_release;
-
- if (st->socket->ops->family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr;
- printk(KERN_INFO "%s: (re)connected to peer %pi4:%d.\n", __func__,
- &sin->sin_addr.s_addr, ntohs(sin->sin_port));
- } else if (st->socket->ops->family == AF_INET6) {
- struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr;
- printk(KERN_INFO "%s: (re)connected to peer %pi6:%d", __func__,
- &sin->sin6_addr, ntohs(sin->sin6_port));
- }
-
- return 0;
-
-err_out_release:
- sock_release(st->socket);
-err_out_exit:
- st->socket = NULL;
- return err;
-}
-
-void netfs_state_exit(struct netfs_state *st)
-{
- if (st->socket) {
- netfs_poll_exit(st);
- st->socket->ops->shutdown(st->socket, 2);
-
- if (st->socket->ops->family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
- printk(KERN_INFO "%s: disconnected from peer %pi4:%d.\n", __func__,
- &sin->sin_addr.s_addr, ntohs(sin->sin_port));
- } else if (st->socket->ops->family == AF_INET6) {
- struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
- printk(KERN_INFO "%s: disconnected from peer %pi6:%d", __func__,
- &sin->sin6_addr, ntohs(sin->sin6_port));
- }
-
- sock_release(st->socket);
- st->socket = NULL;
- st->read_socket = NULL;
- st->need_reset = 0;
- }
-}
-
-int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf)
-{
- struct netfs_state *st = &conf->state;
- int err = -ENOMEM;
-
- mutex_init(&st->__state_lock);
- mutex_init(&st->__state_send_lock);
- init_waitqueue_head(&st->thread_wait);
-
- st->psb = psb;
- st->trans_root = RB_ROOT;
- mutex_init(&st->trans_lock);
-
- st->size = psb->trans_data_size;
- st->data = kmalloc(st->size, GFP_KERNEL);
- if (!st->data)
- goto err_out_exit;
-
- if (psb->perform_crypto) {
- err = pohmelfs_crypto_engine_init(&st->eng, psb);
- if (err)
- goto err_out_free_data;
- }
-
- err = netfs_state_init(st);
- if (err)
- goto err_out_free_engine;
-
- st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx);
- if (IS_ERR(st->thread)) {
- err = PTR_ERR(st->thread);
- goto err_out_netfs_exit;
- }
-
- if (!psb->active_state)
- psb->active_state = conf;
-
- dprintk("%s: conf: %p, st: %p, socket: %p.\n",
- __func__, conf, st, st->socket);
- return 0;
-
-err_out_netfs_exit:
- netfs_state_exit(st);
-err_out_free_engine:
- pohmelfs_crypto_engine_exit(&st->eng);
-err_out_free_data:
- kfree(st->data);
-err_out_exit:
- return err;
-
-}
-
-void pohmelfs_state_flush_transactions(struct netfs_state *st)
-{
- struct rb_node *rb_node;
- struct netfs_trans_dst *dst;
-
- mutex_lock(&st->trans_lock);
- for (rb_node = rb_first(&st->trans_root); rb_node; ) {
- dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
- rb_node = rb_next(rb_node);
-
- dst->trans->result = -EINVAL;
- netfs_trans_remove_nolock(dst, st);
- netfs_trans_drop_dst_nostate(dst);
- }
- mutex_unlock(&st->trans_lock);
-}
-
-static void pohmelfs_state_exit_one(struct pohmelfs_config *c)
-{
- struct netfs_state *st = &c->state;
-
- dprintk("%s: exiting, st: %p.\n", __func__, st);
- if (st->thread) {
- kthread_stop(st->thread);
- st->thread = NULL;
- }
-
- netfs_state_lock_send(st);
- netfs_state_exit(st);
- netfs_state_unlock_send(st);
-
- pohmelfs_state_flush_transactions(st);
-
- pohmelfs_crypto_engine_exit(&st->eng);
- kfree(st->data);
-
- kfree(c);
-}
-
-/*
- * Initialize network stack. It searches for given ID in global
- * configuration table, this contains information of the remote server
- * (address (any supported by socket interface) and port, protocol and so on).
- */
-int pohmelfs_state_init(struct pohmelfs_sb *psb)
-{
- int err = -ENOMEM;
-
- err = pohmelfs_copy_config(psb);
- if (err) {
- pohmelfs_state_exit(psb);
- return err;
- }
-
- return 0;
-}
-
-void pohmelfs_state_exit(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config *c, *tmp;
-
- list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
- list_del(&c->config_entry);
- pohmelfs_state_exit_one(c);
- }
-}
-
-void pohmelfs_switch_active(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config *c = psb->active_state;
-
- if (!list_empty(&psb->state_list)) {
- if (c->config_entry.next != &psb->state_list) {
- psb->active_state = list_entry(c->config_entry.next,
- struct pohmelfs_config, config_entry);
- } else {
- psb->active_state = list_entry(psb->state_list.next,
- struct pohmelfs_config, config_entry);
- }
-
- dprintk("%s: empty: %d, active %p -> %p.\n",
- __func__, list_empty(&psb->state_list), c,
- psb->active_state);
- } else
- psb->active_state = NULL;
-}
-
-void pohmelfs_check_states(struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config *c, *tmp;
- LIST_HEAD(delete_list);
-
- mutex_lock(&psb->state_lock);
- list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
- if (pohmelfs_config_check(c, psb->idx)) {
-
- if (psb->active_state == c)
- pohmelfs_switch_active(psb);
- list_move(&c->config_entry, &delete_list);
- }
- }
- pohmelfs_copy_config(psb);
- mutex_unlock(&psb->state_lock);
-
- list_for_each_entry_safe(c, tmp, &delete_list, config_entry) {
- list_del(&c->config_entry);
- pohmelfs_state_exit_one(c);
- }
-}
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
deleted file mode 100644
index f26894f2a57f..000000000000
--- a/drivers/staging/pohmelfs/netfs.h
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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.
- */
-
-#ifndef __NETFS_H
-#define __NETFS_H
-
-#include <linux/types.h>
-#include <linux/connector.h>
-#include <linux/backing-dev.h>
-
-#define POHMELFS_CN_IDX 5
-#define POHMELFS_CN_VAL 0
-
-#define POHMELFS_CTLINFO_ACK 1
-#define POHMELFS_NOINFO_ACK 2
-
-#define POHMELFS_NULL_IDX 65535
-
-/*
- * Network command structure.
- * Will be extended.
- */
-struct netfs_cmd {
- __u16 cmd; /* Command number */
- __u16 csize; /* Attached crypto information size */
- __u16 cpad; /* Attached padding size */
- __u16 ext; /* External flags */
- __u32 size; /* Size of the attached data */
- __u32 trans; /* Transaction id */
- __u64 id; /* Object ID to operate on. Used for feedback.*/
- __u64 start; /* Start of the object. */
- __u64 iv; /* IV sequence */
- __u8 data[0];
-};
-
-static inline void netfs_convert_cmd(struct netfs_cmd *cmd)
-{
- cmd->id = __be64_to_cpu(cmd->id);
- cmd->start = __be64_to_cpu(cmd->start);
- cmd->iv = __be64_to_cpu(cmd->iv);
- cmd->cmd = __be16_to_cpu(cmd->cmd);
- cmd->ext = __be16_to_cpu(cmd->ext);
- cmd->csize = __be16_to_cpu(cmd->csize);
- cmd->cpad = __be16_to_cpu(cmd->cpad);
- cmd->size = __be32_to_cpu(cmd->size);
-}
-
-#define NETFS_TRANS_SINGLE_DST (1<<0)
-
-enum {
- NETFS_READDIR = 1, /* Read directory for given inode number */
- NETFS_READ_PAGE, /* Read data page from the server */
- NETFS_WRITE_PAGE, /* Write data page to the server */
- NETFS_CREATE, /* Create directory entry */
- NETFS_REMOVE, /* Remove directory entry */
-
- NETFS_LOOKUP, /* Lookup single object */
- NETFS_LINK, /* Create a link */
- NETFS_TRANS, /* Transaction */
- NETFS_OPEN, /* Open intent */
- NETFS_INODE_INFO, /* Metadata cache coherency synchronization message */
-
- NETFS_PAGE_CACHE, /* Page cache invalidation message */
- NETFS_READ_PAGES, /* Read multiple contiguous pages in one go */
- NETFS_RENAME, /* Rename object */
- NETFS_CAPABILITIES, /* Capabilities of the client, for example supported crypto */
- NETFS_LOCK, /* Distributed lock message */
-
- NETFS_XATTR_SET, /* Set extended attribute */
- NETFS_XATTR_GET, /* Get extended attribute */
- NETFS_CMD_MAX
-};
-
-enum {
- POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */
- POHMELFS_FLAGS_DEL, /* Network state control message for DEL */
- POHMELFS_FLAGS_SHOW, /* Network state control message for SHOW */
- POHMELFS_FLAGS_CRYPTO, /* Crypto data control message */
- POHMELFS_FLAGS_MODIFY, /* Network state modification message */
- POHMELFS_FLAGS_DUMP, /* Network state control message for SHOW ALL */
- POHMELFS_FLAGS_FLUSH, /* Network state control message for FLUSH */
-};
-
-/*
- * Always wanted to copy it from socket headers into public one,
- * since they are __KERNEL__ protected there.
- */
-#define _K_SS_MAXSIZE 128
-
-struct saddr {
- unsigned short sa_family;
- char addr[_K_SS_MAXSIZE];
-};
-
-enum {
- POHMELFS_CRYPTO_HASH = 0,
- POHMELFS_CRYPTO_CIPHER,
-};
-
-struct pohmelfs_crypto {
- unsigned int idx; /* Config index */
- unsigned short strlen; /* Size of the attached crypto string including 0-byte
- * "cbc(aes)" for example */
- unsigned short type; /* HMAC, cipher, both */
- unsigned int keysize; /* Key size */
- unsigned char data[0]; /* Algorithm string, key and IV */
-};
-
-#define POHMELFS_IO_PERM_READ (1<<0)
-#define POHMELFS_IO_PERM_WRITE (1<<1)
-
-/*
- * Configuration command used to create table of different remote servers.
- */
-struct pohmelfs_ctl {
- __u32 idx; /* Config index */
- __u32 type; /* Socket type */
- __u32 proto; /* Socket protocol */
- __u16 addrlen; /* Size of the address */
- __u16 perm; /* IO permission */
- __u16 prio; /* IO priority */
- struct saddr addr; /* Remote server address */
-};
-
-/*
- * Ack for userspace about requested command.
- */
-struct pohmelfs_cn_ack {
- struct cn_msg msg;
- int error;
- int msg_num;
- int unused[3];
- struct pohmelfs_ctl ctl;
-};
-
-/*
- * Inode info structure used to sync with server.
- * Check what stat() returns.
- */
-struct netfs_inode_info {
- unsigned int mode;
- unsigned int nlink;
- unsigned int uid;
- unsigned int gid;
- unsigned int blocksize;
- unsigned int padding;
- __u64 ino;
- __u64 blocks;
- __u64 rdev;
- __u64 size;
- __u64 version;
-};
-
-static inline void netfs_convert_inode_info(struct netfs_inode_info *info)
-{
- info->mode = __cpu_to_be32(info->mode);
- info->nlink = __cpu_to_be32(info->nlink);
- info->uid = __cpu_to_be32(info->uid);
- info->gid = __cpu_to_be32(info->gid);
- info->blocksize = __cpu_to_be32(info->blocksize);
- info->blocks = __cpu_to_be64(info->blocks);
- info->rdev = __cpu_to_be64(info->rdev);
- info->size = __cpu_to_be64(info->size);
- info->version = __cpu_to_be64(info->version);
- info->ino = __cpu_to_be64(info->ino);
-}
-
-/*
- * Cache state machine.
- */
-enum {
- NETFS_COMMAND_PENDING = 0, /* Command is being executed */
- NETFS_INODE_REMOTE_SYNCED, /* Inode was synced to server */
- NETFS_INODE_REMOTE_DIR_SYNCED, /* Inode (directory) was synced from the server */
- NETFS_INODE_OWNED, /* Inode is owned by given host */
- NETFS_INODE_NEED_FLUSH, /* Inode has to be flushed to the server */
-};
-
-/*
- * POHMELFS capabilities: information about supported
- * crypto operations (hash/cipher, modes, key sizes and so on),
- * root information (used/available size, number of objects, permissions)
- */
-enum pohmelfs_capabilities {
- POHMELFS_CRYPTO_CAPABILITIES = 0,
- POHMELFS_ROOT_CAPABILITIES,
-};
-
-/* Read-only mount */
-#define POHMELFS_FLAGS_RO (1<<0)
-/* Extended attributes support on/off */
-#define POHMELFS_FLAGS_XATTR (1<<1)
-
-struct netfs_root_capabilities {
- __u64 nr_files;
- __u64 used, avail;
- __u64 flags;
-};
-
-static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap)
-{
- cap->nr_files = __cpu_to_be64(cap->nr_files);
- cap->used = __cpu_to_be64(cap->used);
- cap->avail = __cpu_to_be64(cap->avail);
- cap->flags = __cpu_to_be64(cap->flags);
-}
-
-struct netfs_crypto_capabilities {
- unsigned short hash_strlen; /* Hash string length, like "hmac(sha1) including 0 byte "*/
- unsigned short cipher_strlen; /* Cipher string length with the same format */
- unsigned int cipher_keysize; /* Cipher key size */
-};
-
-static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap)
-{
- cap->hash_strlen = __cpu_to_be16(cap->hash_strlen);
- cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen);
- cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize);
-}
-
-enum pohmelfs_lock_type {
- POHMELFS_LOCK_GRAB = (1<<15),
-
- POHMELFS_READ_LOCK = 0,
- POHMELFS_WRITE_LOCK,
-};
-
-struct netfs_lock {
- __u64 start;
- __u64 ino;
- __u32 size;
- __u32 type;
-};
-
-static inline void netfs_convert_lock(struct netfs_lock *lock)
-{
- lock->start = __cpu_to_be64(lock->start);
- lock->ino = __cpu_to_be64(lock->ino);
- lock->size = __cpu_to_be32(lock->size);
- lock->type = __cpu_to_be32(lock->type);
-}
-
-#ifdef __KERNEL__
-
-#include <linux/kernel.h>
-#include <linux/completion.h>
-#include <linux/rbtree.h>
-#include <linux/net.h>
-#include <linux/poll.h>
-
-/*
- * Private POHMELFS cache of objects in directory.
- */
-struct pohmelfs_name {
- struct rb_node hash_node;
-
- struct list_head sync_create_entry;
-
- u64 ino;
-
- u32 hash;
- u32 mode;
- u32 len;
-
- char *data;
-};
-
-/*
- * POHMELFS inode. Main object.
- */
-struct pohmelfs_inode {
- struct list_head inode_entry; /* Entry in superblock list.
- * Objects which are not bound to dentry require to be dropped
- * in ->put_super()
- */
- struct rb_root hash_root; /* The same, but indexed by name hash and len */
- struct mutex offset_lock; /* Protect both above trees */
-
- struct list_head sync_create_list; /* List of created but not yet synced to the server children */
-
- unsigned int drop_count;
-
- int lock_type; /* How this inode is locked: read or write */
-
- int error; /* Transaction error for given inode */
-
- long state; /* State machine above */
-
- u64 ino; /* Inode number */
- u64 total_len; /* Total length of all children names, used to create offsets */
-
- struct inode vfs_inode;
-};
-
-struct netfs_trans;
-typedef int (*netfs_trans_complete_t)(struct page **pages, unsigned int page_num,
- void *private, int err);
-
-struct netfs_state;
-struct pohmelfs_sb;
-
-struct netfs_trans {
- /*
- * Transaction header and attached contiguous data live here.
- */
- struct iovec iovec;
-
- /*
- * Pages attached to transaction.
- */
- struct page **pages;
-
- /*
- * List and protecting lock for transaction destination
- * network states.
- */
- spinlock_t dst_lock;
- struct list_head dst_list;
-
- /*
- * Number of users for given transaction.
- * For example each network state attached to transaction
- * via dst_list increases it.
- */
- atomic_t refcnt;
-
- /*
- * Number of pages attached to given transaction.
- * Some slots in above page array can be NULL, since
- * for example page can be under writeback already,
- * so we skip it in this transaction.
- */
- unsigned int page_num;
-
- /*
- * Transaction flags: single dst or broadcast and so on.
- */
- unsigned int flags;
-
- /*
- * Size of the data, which can be placed into
- * iovec.iov_base area.
- */
- unsigned int total_size;
-
- /*
- * Number of pages to be sent to remote server.
- * Usually equal to above page_num, but in case of partial
- * writeback it can accumulate only pages already completed
- * previous writeback.
- */
- unsigned int attached_pages;
-
- /*
- * Attached number of bytes in all above pages.
- */
- unsigned int attached_size;
-
- /*
- * Unique transacton generation number.
- * Used as identity in the network state tree of transactions.
- */
- unsigned int gen;
-
- /*
- * Transaction completion status.
- */
- int result;
-
- /*
- * Superblock this transaction belongs to
- */
- struct pohmelfs_sb *psb;
-
- /*
- * Crypto engine, which processed this transaction.
- * Can be not NULL only if crypto engine holds encrypted pages.
- */
- struct pohmelfs_crypto_engine *eng;
-
- /* Private data */
- void *private;
-
- /* Completion callback, invoked just before transaction is destroyed */
- netfs_trans_complete_t complete;
-};
-
-static inline int netfs_trans_cur_len(struct netfs_trans *t)
-{
- return (signed)(t->total_size - t->iovec.iov_len);
-}
-
-static inline void *netfs_trans_current(struct netfs_trans *t)
-{
- return t->iovec.iov_base + t->iovec.iov_len;
-}
-
-struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
- unsigned int flags, unsigned int nr);
-void netfs_trans_free(struct netfs_trans *t);
-int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb);
-int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb);
-
-static inline void netfs_trans_reset(struct netfs_trans *t)
-{
- t->complete = NULL;
-}
-
-struct netfs_trans_dst {
- struct list_head trans_entry;
- struct rb_node state_entry;
-
- unsigned long send_time;
-
- /*
- * Times this transaction was resent to its old or new,
- * depending on flags, destinations. When it reaches maximum
- * allowed number, specified in superblock->trans_retries,
- * transaction will be freed with ETIMEDOUT error.
- */
- unsigned int retries;
-
- struct netfs_trans *trans;
- struct netfs_state *state;
-};
-
-struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen);
-void netfs_trans_drop_dst(struct netfs_trans_dst *dst);
-void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst);
-void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st);
-void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st);
-int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb);
-int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st);
-
-int netfs_trans_init(void);
-void netfs_trans_exit(void);
-
-struct pohmelfs_crypto_engine {
- u64 iv; /* Crypto IV for current operation */
- unsigned long timeout; /* Crypto waiting timeout */
- unsigned int size; /* Size of crypto scratchpad */
- void *data; /* Temporal crypto scratchpad */
- /*
- * Crypto operations performed on objects.
- */
- struct crypto_hash *hash;
- struct crypto_ablkcipher *cipher;
-
- struct pohmelfs_crypto_thread *thread; /* Crypto thread which hosts this engine */
-
- struct page **pages;
- unsigned int page_num;
-};
-
-struct pohmelfs_crypto_thread {
- struct list_head thread_entry;
-
- struct task_struct *thread;
- struct pohmelfs_sb *psb;
-
- struct pohmelfs_crypto_engine eng;
-
- struct netfs_trans *trans;
-
- wait_queue_head_t wait;
- int error;
-
- unsigned int size;
- struct page *page;
-};
-
-void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th);
-
-/*
- * Network state, attached to one server.
- */
-struct netfs_state {
- struct mutex __state_lock; /* Can not allow to use the same socket simultaneously */
- struct mutex __state_send_lock;
- struct netfs_cmd cmd; /* Cached command */
- struct netfs_inode_info info; /* Cached inode info */
-
- void *data; /* Cached some data */
- unsigned int size; /* Size of that data */
-
- struct pohmelfs_sb *psb; /* Superblock */
-
- struct task_struct *thread; /* Async receiving thread */
-
- /* Waiting/polling machinery */
- wait_queue_t wait;
- wait_queue_head_t *whead;
- wait_queue_head_t thread_wait;
-
- struct mutex trans_lock;
- struct rb_root trans_root;
-
- struct pohmelfs_ctl ctl; /* Remote peer */
-
- struct socket *socket; /* Socket object */
- struct socket *read_socket; /* Cached pointer to socket object.
- * Used to determine if between lock drops socket was changed.
- * Never used to read data or any kind of access.
- */
- /*
- * Crypto engines to process incoming data.
- */
- struct pohmelfs_crypto_engine eng;
-
- int need_reset;
-};
-
-int netfs_state_init(struct netfs_state *st);
-void netfs_state_exit(struct netfs_state *st);
-
-static inline void netfs_state_lock_send(struct netfs_state *st)
-{
- mutex_lock(&st->__state_send_lock);
-}
-
-static inline int netfs_state_trylock_send(struct netfs_state *st)
-{
- return mutex_trylock(&st->__state_send_lock);
-}
-
-static inline void netfs_state_unlock_send(struct netfs_state *st)
-{
- BUG_ON(!mutex_is_locked(&st->__state_send_lock));
-
- mutex_unlock(&st->__state_send_lock);
-}
-
-static inline void netfs_state_lock(struct netfs_state *st)
-{
- mutex_lock(&st->__state_lock);
-}
-
-static inline void netfs_state_unlock(struct netfs_state *st)
-{
- BUG_ON(!mutex_is_locked(&st->__state_lock));
-
- mutex_unlock(&st->__state_lock);
-}
-
-static inline unsigned int netfs_state_poll(struct netfs_state *st)
-{
- unsigned int revents = POLLHUP | POLLERR;
-
- netfs_state_lock(st);
- if (st->socket)
- revents = st->socket->ops->poll(NULL, st->socket, NULL);
- netfs_state_unlock(st);
-
- return revents;
-}
-
-struct pohmelfs_config;
-
-struct pohmelfs_sb {
- struct rb_root mcache_root;
- struct mutex mcache_lock;
- atomic_long_t mcache_gen;
- unsigned long mcache_timeout;
-
- unsigned int idx;
-
- unsigned int trans_retries;
-
- atomic_t trans_gen;
-
- unsigned int crypto_attached_size;
- unsigned int crypto_align_size;
-
- unsigned int crypto_fail_unsupported;
-
- unsigned int crypto_thread_num;
- struct list_head crypto_active_list, crypto_ready_list;
- struct mutex crypto_thread_lock;
-
- unsigned int trans_max_pages;
- unsigned long trans_data_size;
- unsigned long trans_timeout;
-
- unsigned long drop_scan_timeout;
- unsigned long trans_scan_timeout;
-
- unsigned long wait_on_page_timeout;
-
- struct list_head flush_list;
- struct list_head drop_list;
- spinlock_t ino_lock;
- u64 ino;
-
- /*
- * Remote nodes POHMELFS connected to.
- */
- struct list_head state_list;
- struct mutex state_lock;
-
- /*
- * Currently active state to request data from.
- */
- struct pohmelfs_config *active_state;
-
-
- wait_queue_head_t wait;
-
- /*
- * Timed checks: stale transactions, inodes to be freed and so on.
- */
- struct delayed_work dwork;
- struct delayed_work drop_dwork;
-
- struct super_block *sb;
-
- struct backing_dev_info bdi;
-
- /*
- * Algorithm strings.
- */
- char *hash_string;
- char *cipher_string;
-
- u8 *hash_key;
- u8 *cipher_key;
-
- /*
- * Algorithm string lengths.
- */
- unsigned int hash_strlen;
- unsigned int cipher_strlen;
- unsigned int hash_keysize;
- unsigned int cipher_keysize;
-
- /*
- * Controls whether to perfrom crypto processing or not.
- */
- int perform_crypto;
-
- /*
- * POHMELFS statistics.
- */
- u64 total_size;
- u64 avail_size;
- atomic_long_t total_inodes;
-
- /*
- * Xattr support, read-only and so on.
- */
- u64 state_flags;
-
- /*
- * Temporary storage to detect changes in the wait queue.
- */
- long flags;
-};
-
-static inline void netfs_trans_update(struct netfs_cmd *cmd,
- struct netfs_trans *t, unsigned int size)
-{
- unsigned int sz = ALIGN(size, t->psb->crypto_align_size);
-
- t->iovec.iov_len += sizeof(struct netfs_cmd) + sz;
- cmd->cpad = __cpu_to_be16(sz - size);
-}
-
-static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode)
-{
- return container_of(inode, struct pohmelfs_inode, vfs_inode);
-}
-
-static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb)
-{
- u64 ino;
-
- spin_lock(&psb->ino_lock);
- ino = psb->ino++;
- spin_unlock(&psb->ino_lock);
-
- return ino;
-}
-
-static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi)
-{
- struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
- spin_lock(&psb->ino_lock);
- list_move_tail(&pi->inode_entry, &psb->drop_list);
- pi->drop_count++;
- spin_unlock(&psb->ino_lock);
-}
-
-struct pohmelfs_config {
- struct list_head config_entry;
-
- struct netfs_state state;
-};
-
-struct pohmelfs_config_group {
- /*
- * Entry in the global config group list.
- */
- struct list_head group_entry;
-
- /*
- * Index of the current group.
- */
- unsigned int idx;
- /*
- * Number of config_list entries in this group entry.
- */
- unsigned int num_entry;
- /*
- * Algorithm strings.
- */
- char *hash_string;
- char *cipher_string;
-
- /*
- * Algorithm string lengths.
- */
- unsigned int hash_strlen;
- unsigned int cipher_strlen;
-
- /*
- * Key and its size.
- */
- unsigned int hash_keysize;
- unsigned int cipher_keysize;
- u8 *hash_key;
- u8 *cipher_key;
-
- /*
- * List of config entries (network state info) for given idx.
- */
- struct list_head config_list;
-};
-
-int __init pohmelfs_config_init(void);
-void pohmelfs_config_exit(void);
-int pohmelfs_copy_config(struct pohmelfs_sb *psb);
-int pohmelfs_copy_crypto(struct pohmelfs_sb *psb);
-int pohmelfs_config_check(struct pohmelfs_config *config, int idx);
-int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf);
-
-extern const struct file_operations pohmelfs_dir_fops;
-extern const struct inode_operations pohmelfs_dir_inode_ops;
-
-int pohmelfs_state_init(struct pohmelfs_sb *psb);
-void pohmelfs_state_exit(struct pohmelfs_sb *psb);
-void pohmelfs_state_flush_transactions(struct netfs_state *st);
-
-void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info);
-
-void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
-void pohmelfs_free_names(struct pohmelfs_inode *parent);
-struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash);
-
-void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi);
-
-struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
- struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode);
-
-int pohmelfs_write_create_inode(struct pohmelfs_inode *pi);
-
-int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans);
-int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
-
-struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
- struct pohmelfs_inode *parent, struct qstr *str,
- struct netfs_inode_info *info, int link);
-
-int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr);
-int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr);
-
-int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
- netfs_trans_complete_t complete, void *priv, u64 start);
-int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
- unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start);
-
-void pohmelfs_check_states(struct pohmelfs_sb *psb);
-void pohmelfs_switch_active(struct pohmelfs_sb *psb);
-
-int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len);
-int pohmelfs_path_length(struct pohmelfs_inode *pi);
-
-struct pohmelfs_crypto_completion {
- struct completion complete;
- int error;
-};
-
-int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb);
-void pohmelfs_crypto_exit(struct pohmelfs_sb *psb);
-int pohmelfs_crypto_init(struct pohmelfs_sb *psb);
-
-int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb);
-void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e);
-
-int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv,
- void *data, struct page *page, unsigned int size);
-int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
- struct page *page, unsigned int size, u64 iv);
-
-static inline u64 pohmelfs_gen_iv(struct netfs_trans *t)
-{
- u64 iv = t->gen;
-
- iv <<= 32;
- iv |= ((unsigned long)t) & 0xffffffff;
-
- return iv;
-}
-
-int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
-int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
-int pohmelfs_data_lock_response(struct netfs_state *st);
-
-static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type)
-{
- if (test_bit(NETFS_INODE_OWNED, &pi->state)) {
- if (type == pi->lock_type)
- return 0;
- if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK))
- return 0;
- }
-
- if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
- return 0;
-
- return 1;
-}
-
-int __init pohmelfs_mcache_init(void);
-void pohmelfs_mcache_exit(void);
-
-/* #define CONFIG_POHMELFS_DEBUG */
-
-#ifdef CONFIG_POHMELFS_DEBUG
-#define dprintka(f, a...) printk(f, ##a)
-#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a)
-#else
-#define dprintka(f, a...) do {} while (0)
-#define dprintk(f, a...) do {} while (0)
-#endif
-
-static inline void netfs_trans_get(struct netfs_trans *t)
-{
- atomic_inc(&t->refcnt);
-}
-
-static inline void netfs_trans_put(struct netfs_trans *t)
-{
- if (atomic_dec_and_test(&t->refcnt)) {
- dprintk("%s: t: %p, gen: %u, err: %d.\n",
- __func__, t, t->gen, t->result);
- if (t->complete)
- t->complete(t->pages, t->page_num,
- t->private, t->result);
- netfs_trans_free(t);
- }
-}
-
-struct pohmelfs_mcache {
- struct rb_node mcache_entry;
- struct completion complete;
-
- atomic_t refcnt;
-
- u64 gen;
-
- void *data;
- u64 start;
- u32 size;
- int err;
-
- struct netfs_inode_info info;
-};
-
-struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
- unsigned int size, void *data);
-void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
-struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen);
-void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
-
-static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m)
-{
- atomic_inc(&m->refcnt);
-}
-
-static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb,
- struct pohmelfs_mcache *m)
-{
- if (atomic_dec_and_test(&m->refcnt))
- pohmelfs_mcache_free(psb, m);
-}
-
-/*#define POHMELFS_TRUNCATE_ON_INODE_FLUSH
- */
-
-#endif /* __KERNEL__*/
-
-#endif /* __NETFS_H */
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
deleted file mode 100644
index 400a9fc386ad..000000000000
--- a/drivers/staging/pohmelfs/path_entry.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/fs.h>
-#include <linux/ktime.h>
-#include <linux/fs_struct.h>
-#include <linux/pagemap.h>
-#include <linux/writeback.h>
-#include <linux/mount.h>
-#include <linux/mm.h>
-
-#include "netfs.h"
-
-#define UNHASHED_OBSCURE_STRING_SIZE sizeof(" (deleted)")
-
-/*
- * Create path from root for given inode.
- * Path is formed as set of stuctures, containing name of the object
- * and its inode data (mode, permissions and so on).
- */
-int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len)
-{
- struct path path;
- struct dentry *d;
- char *ptr;
- int err = 0, strlen, reduce = 0;
-
- d = d_find_alias(&pi->vfs_inode);
- if (!d) {
- printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry));
- return -ENOENT;
- }
-
- spin_lock(&current->fs->lock);
- path.mnt = mntget(current->fs->root.mnt);
- spin_unlock(&current->fs->lock);
-
- path.dentry = d;
-
- if (!IS_ROOT(d) && d_unhashed(d))
- reduce = 1;
-
- ptr = d_path(&path, data, len);
- if (IS_ERR(ptr)) {
- err = PTR_ERR(ptr);
- goto out;
- }
-
- if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) {
- char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE;
- *end = '\0';
- }
-
- strlen = len - (ptr - (char *)data);
- memmove(data, ptr, strlen);
- ptr = data;
-
- err = strlen;
-
- dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n",
- __func__, d->d_name.name, d->d_name.len, len, ptr, strlen);
-
-out:
- dput(d);
- mntput(path.mnt);
-
- return err;
-}
-
-int pohmelfs_path_length(struct pohmelfs_inode *pi)
-{
- struct dentry *d, *root, *first;
- int len;
- unsigned seq;
-
- first = d_find_alias(&pi->vfs_inode);
- if (!first) {
- dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
- return -ENOENT;
- }
-
- spin_lock(&current->fs->lock);
- root = dget(current->fs->root.dentry);
- spin_unlock(&current->fs->lock);
-
-rename_retry:
- len = 1; /* Root slash */
- d = first;
- seq = read_seqbegin(&rename_lock);
- rcu_read_lock();
-
- if (!IS_ROOT(d) && d_unhashed(d))
- len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
-
- while (d && d != root && !IS_ROOT(d)) {
- len += d->d_name.len + 1; /* Plus slash */
- d = d->d_parent;
- }
- rcu_read_unlock();
- if (read_seqretry(&rename_lock, seq))
- goto rename_retry;
-
- dput(root);
- dput(first);
-
- return len + 1; /* Including zero-byte */
-}
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
deleted file mode 100644
index 06c1a7451b1b..000000000000
--- a/drivers/staging/pohmelfs/trans.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mempool.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/parser.h>
-#include <linux/poll.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *netfs_trans_dst;
-static mempool_t *netfs_trans_dst_pool;
-
-static void netfs_trans_init_static(struct netfs_trans *t, int num, int size)
-{
- t->page_num = num;
- t->total_size = size;
- atomic_set(&t->refcnt, 1);
-
- spin_lock_init(&t->dst_lock);
- INIT_LIST_HEAD(&t->dst_list);
-}
-
-static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
-{
- int err = 0;
- unsigned int i, attached_pages = t->attached_pages, ci;
- struct msghdr msg;
- struct page **pages = (t->eng) ? t->eng->pages : t->pages;
- struct page *p;
- unsigned int size;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
- ci = 0;
- for (i = 0; i < t->page_num; ++i) {
- struct page *page = pages[ci];
- struct netfs_cmd cmd;
- struct iovec io;
-
- p = t->pages[i];
-
- if (!p)
- continue;
-
- size = page_private(p);
-
- io.iov_base = &cmd;
- io.iov_len = sizeof(struct netfs_cmd);
-
- cmd.cmd = NETFS_WRITE_PAGE;
- cmd.ext = 0;
- cmd.id = 0;
- cmd.size = size;
- cmd.start = p->index;
- cmd.start <<= PAGE_CACHE_SHIFT;
- cmd.csize = 0;
- cmd.cpad = 0;
- cmd.iv = pohmelfs_gen_iv(t);
-
- netfs_convert_cmd(&cmd);
-
- msg.msg_iov = &io;
- msg.msg_iovlen = 1;
- msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
- err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd));
- if (err <= 0) {
- printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n",
- __func__, i, t->page_num, t, t->gen, err);
- if (err == 0)
- err = -ECONNRESET;
- goto err_out;
- }
-
- msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 :
- MSG_MORE);
-
- err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags);
- if (err <= 0) {
- printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n",
- __func__, i, t->page_num, t, t->gen, size, err);
- if (err == 0)
- err = -ECONNRESET;
- goto err_out;
- }
-
- dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n",
- __func__, i, t->page_num, t, t->gen, page, p, size);
-
- err = 0;
- attached_pages--;
- if (!attached_pages)
- break;
- ci++;
-
- continue;
-
-err_out:
- printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err);
- netfs_state_exit(st);
- break;
- }
-
- return err;
-}
-
-int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
-{
- int err;
- struct msghdr msg;
-
- BUG_ON(!t->iovec.iov_len);
- BUG_ON(t->iovec.iov_len > 1024*1024*1024);
-
- netfs_state_lock_send(st);
- if (!st->socket) {
- err = netfs_state_init(st);
- if (err)
- goto err_out_unlock_return;
- }
-
- msg.msg_iov = &t->iovec;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = MSG_WAITALL;
-
- if (t->attached_pages)
- msg.msg_flags |= MSG_MORE;
-
- err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len);
- if (err <= 0) {
- printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n",
- __func__, t, t->gen, t->iovec.iov_len, err);
- if (err == 0)
- err = -ECONNRESET;
- goto err_out_unlock_return;
- }
-
- dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
- __func__, (t->page_num) ? "partial" : "full",
- t, t->gen, t->iovec.iov_len, t->page_num);
-
- err = 0;
- if (t->attached_pages)
- err = netfs_trans_send_pages(t, st);
-
-err_out_unlock_return:
-
- if (st->need_reset)
- netfs_state_exit(st);
-
- netfs_state_unlock_send(st);
-
- dprintk("%s: t: %p, gen: %u, err: %d.\n",
- __func__, t, t->gen, err);
-
- t->result = err;
- return err;
-}
-
-static inline int netfs_trans_cmp(unsigned int gen, unsigned int new)
-{
- if (gen < new)
- return 1;
- if (gen > new)
- return -1;
- return 0;
-}
-
-struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen)
-{
- struct rb_root *root = &st->trans_root;
- struct rb_node *n = root->rb_node;
- struct netfs_trans_dst *tmp, *ret = NULL;
- struct netfs_trans *t;
- int cmp;
-
- while (n) {
- tmp = rb_entry(n, struct netfs_trans_dst, state_entry);
- t = tmp->trans;
-
- cmp = netfs_trans_cmp(t->gen, gen);
- if (cmp < 0)
- n = n->rb_left;
- else if (cmp > 0)
- n = n->rb_right;
- else {
- ret = tmp;
- break;
- }
- }
-
- return ret;
-}
-
-static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st)
-{
- struct rb_root *root = &st->trans_root;
- struct rb_node **n = &root->rb_node, *parent = NULL;
- struct netfs_trans_dst *ret = NULL, *tmp;
- struct netfs_trans *t = NULL, *new = ndst->trans;
- int cmp;
-
- while (*n) {
- parent = *n;
-
- tmp = rb_entry(parent, struct netfs_trans_dst, state_entry);
- t = tmp->trans;
-
- cmp = netfs_trans_cmp(t->gen, new->gen);
- if (cmp < 0)
- n = &parent->rb_left;
- else if (cmp > 0)
- n = &parent->rb_right;
- else {
- ret = tmp;
- break;
- }
- }
-
- if (ret) {
- printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, "
- "new: gen: %u, flags: %x, send_time: %lu.\n",
- __func__, t->gen, t->flags, ret->send_time,
- new->gen, new->flags, ndst->send_time);
- return -EEXIST;
- }
-
- rb_link_node(&ndst->state_entry, parent, n);
- rb_insert_color(&ndst->state_entry, root);
- ndst->send_time = jiffies;
-
- return 0;
-}
-
-int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st)
-{
- if (dst && dst->state_entry.rb_parent_color) {
- rb_erase(&dst->state_entry, &st->trans_root);
- dst->state_entry.rb_parent_color = 0;
- return 1;
- }
- return 0;
-}
-
-static int netfs_trans_remove_state(struct netfs_trans_dst *dst)
-{
- int ret;
- struct netfs_state *st = dst->state;
-
- mutex_lock(&st->trans_lock);
- ret = netfs_trans_remove_nolock(dst, st);
- mutex_unlock(&st->trans_lock);
-
- return ret;
-}
-
-/*
- * Create new destination for given transaction associated with given network state.
- * Transaction's reference counter is bumped and will be dropped when either
- * reply is received or when async timeout detection task will fail resending
- * and drop transaction.
- */
-static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st)
-{
- struct netfs_trans_dst *dst;
- int err;
-
- dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL);
- if (!dst)
- return -ENOMEM;
-
- dst->retries = 0;
- dst->send_time = 0;
- dst->state = st;
- dst->trans = t;
- netfs_trans_get(t);
-
- mutex_lock(&st->trans_lock);
- err = netfs_trans_insert(dst, st);
- mutex_unlock(&st->trans_lock);
-
- if (err)
- goto err_out_free;
-
- spin_lock(&t->dst_lock);
- list_add_tail(&dst->trans_entry, &t->dst_list);
- spin_unlock(&t->dst_lock);
-
- return 0;
-
-err_out_free:
- t->result = err;
- netfs_trans_put(t);
- mempool_free(dst, netfs_trans_dst_pool);
- return err;
-}
-
-static void netfs_trans_free_dst(struct netfs_trans_dst *dst)
-{
- netfs_trans_put(dst->trans);
- mempool_free(dst, netfs_trans_dst_pool);
-}
-
-static void netfs_trans_remove_dst(struct netfs_trans_dst *dst)
-{
- if (netfs_trans_remove_state(dst))
- netfs_trans_free_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it.
- */
-void netfs_trans_drop_dst(struct netfs_trans_dst *dst)
-{
- struct netfs_trans *t = dst->trans;
-
- spin_lock(&t->dst_lock);
- list_del_init(&dst->trans_entry);
- spin_unlock(&t->dst_lock);
-
- netfs_trans_remove_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it and when we
- * already removed dst from state tree.
- */
-void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst)
-{
- struct netfs_trans *t = dst->trans;
-
- spin_lock(&t->dst_lock);
- list_del_init(&dst->trans_entry);
- spin_unlock(&t->dst_lock);
-
- netfs_trans_free_dst(dst);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st)
-{
- struct netfs_trans_dst *dst, *tmp, *ret = NULL;
-
- spin_lock(&t->dst_lock);
- list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
- if (dst->state == st) {
- ret = dst;
- list_del(&dst->trans_entry);
- break;
- }
- }
- spin_unlock(&t->dst_lock);
-
- if (ret)
- netfs_trans_remove_dst(ret);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st)
-{
- struct netfs_trans_dst *dst, *tmp, *ret;
-
- spin_lock(&t->dst_lock);
- ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry);
- if (ret->state != st) {
- ret = NULL;
- list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
- if (dst->state == st) {
- ret = dst;
- list_del_init(&dst->trans_entry);
- break;
- }
- }
- } else {
- list_del(&ret->trans_entry);
- }
- spin_unlock(&t->dst_lock);
-
- if (ret)
- netfs_trans_remove_dst(ret);
-}
-
-static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st)
-{
- int err;
-
- err = netfs_trans_push_dst(t, st);
- if (err)
- return err;
-
- err = netfs_trans_send(t, st);
- if (err)
- goto err_out_free;
-
- if (t->flags & NETFS_TRANS_SINGLE_DST)
- pohmelfs_switch_active(st->psb);
-
- return 0;
-
-err_out_free:
- t->result = err;
- netfs_trans_drop_last(t, st);
-
- return err;
-}
-
-int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
- struct pohmelfs_config *c;
- int err = -ENODEV;
- struct netfs_state *st;
-#if 0
- dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n",
- __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state);
-#endif
- mutex_lock(&psb->state_lock);
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
-
- if (t->flags & NETFS_TRANS_SINGLE_DST) {
- if (!(st->ctl.perm & POHMELFS_IO_PERM_READ))
- continue;
- } else {
- if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE))
- continue;
- }
-
- if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) &&
- (t->flags & NETFS_TRANS_SINGLE_DST))
- st = &psb->active_state->state;
-
- err = netfs_trans_push(t, st);
- if (!err && (t->flags & NETFS_TRANS_SINGLE_DST))
- break;
- }
-
- mutex_unlock(&psb->state_lock);
-#if 0
- dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n",
- __func__, t, t->gen, t->iovec.iov_len, t->page_num, err);
-#endif
- if (err)
- t->result = err;
- return err;
-}
-
-int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
- int err;
- struct netfs_cmd *cmd = t->iovec.iov_base;
-
- t->gen = atomic_inc_return(&psb->trans_gen);
-
- cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
- t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
- cmd->cmd = NETFS_TRANS;
- cmd->start = t->gen;
- cmd->id = 0;
-
- if (psb->perform_crypto) {
- cmd->ext = psb->crypto_attached_size;
- cmd->csize = psb->crypto_attached_size;
- }
-
- dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n",
- __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages);
- err = pohmelfs_trans_crypt(t, psb);
- if (err) {
- t->result = err;
- netfs_convert_cmd(cmd);
- dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n",
- __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err);
- }
- netfs_trans_put(t);
- return err;
-}
-
-/*
- * Resend transaction to remote server(s).
- * If new servers were added into superblock, we can try to send data
- * to them too.
- *
- * It is called under superblock's state_lock, so we can safely
- * dereference psb->state_list. Also, transaction's reference counter is
- * bumped, so it can not go away under us, thus we can safely access all
- * its members. State is locked.
- *
- * This function returns 0 if transaction was successfully sent to at
- * least one destination target.
- */
-int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
- struct netfs_trans_dst *dst;
- struct netfs_state *st;
- struct pohmelfs_config *c;
- int err, exist, error = -ENODEV;
-
- list_for_each_entry(c, &psb->state_list, config_entry) {
- st = &c->state;
-
- exist = 0;
- spin_lock(&t->dst_lock);
- list_for_each_entry(dst, &t->dst_list, trans_entry) {
- if (st == dst->state) {
- exist = 1;
- break;
- }
- }
- spin_unlock(&t->dst_lock);
-
- if (exist) {
- if (!(t->flags & NETFS_TRANS_SINGLE_DST) ||
- (c->config_entry.next == &psb->state_list)) {
- dprintk("%s: resending st: %p, t: %p, gen: %u.\n",
- __func__, st, t, t->gen);
- err = netfs_trans_send(t, st);
- if (!err)
- error = 0;
- }
- continue;
- }
-
- dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n",
- __func__, st, t, t->gen);
- err = netfs_trans_push(t, st);
- if (err)
- continue;
- error = 0;
- if (t->flags & NETFS_TRANS_SINGLE_DST)
- break;
- }
-
- t->result = error;
- return error;
-}
-
-void *netfs_trans_add(struct netfs_trans *t, unsigned int size)
-{
- struct iovec *io = &t->iovec;
- void *ptr;
-
- if (size > t->total_size) {
- ptr = ERR_PTR(-EINVAL);
- goto out;
- }
-
- if (io->iov_len + size > t->total_size) {
- dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n",
- __func__, t, t->gen, io->iov_len, size, t->total_size);
- ptr = ERR_PTR(-E2BIG);
- goto out;
- }
-
- ptr = io->iov_base + io->iov_len;
- io->iov_len += size;
-
-out:
- dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n",
- __func__, t, t->gen, size, io->iov_len);
- return ptr;
-}
-
-void netfs_trans_free(struct netfs_trans *t)
-{
- if (t->eng)
- pohmelfs_crypto_thread_make_ready(t->eng->thread);
- kfree(t);
-}
-
-struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
- unsigned int flags, unsigned int nr)
-{
- struct netfs_trans *t;
- unsigned int num, cont, pad, size_no_trans;
- unsigned int crypto_added = 0;
- struct netfs_cmd *cmd;
-
- if (psb->perform_crypto)
- crypto_added = psb->crypto_attached_size;
-
- /*
- * |sizeof(struct netfs_trans)|
- * |sizeof(struct netfs_cmd)| - transaction header
- * |size| - buffer with requested size
- * |padding| - crypto padding, zero bytes
- * |nr * sizeof(struct page *)| - array of page pointers
- *
- * Overall size should be less than PAGE_SIZE for guaranteed allocation.
- */
-
- cont = size;
- size = ALIGN(size, psb->crypto_align_size);
- pad = size - cont;
-
- size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added;
-
- cont = sizeof(struct netfs_trans) + size_no_trans;
-
- num = (PAGE_SIZE - cont)/sizeof(struct page *);
-
- if (nr > num)
- nr = num;
-
- t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO);
- if (!t)
- goto err_out_exit;
-
- t->iovec.iov_base = (void *)(t + 1);
- t->pages = (struct page **)(t->iovec.iov_base + size_no_trans);
-
- /*
- * Reserving space for transaction header.
- */
- t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added;
-
- netfs_trans_init_static(t, nr, size_no_trans);
-
- t->flags = flags;
- t->psb = psb;
-
- cmd = (struct netfs_cmd *)t->iovec.iov_base;
-
- cmd->size = size;
- cmd->cpad = pad;
- cmd->csize = crypto_added;
-
- dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, "
- "page_num: %u, base: %p, pages: %p.\n",
- __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr,
- t->iovec.iov_base, t->pages);
-
- return t;
-
-err_out_exit:
- return NULL;
-}
-
-int netfs_trans_init(void)
-{
- int err = -ENOMEM;
-
- netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst),
- 0, 0, NULL);
- if (!netfs_trans_dst)
- goto err_out_exit;
-
- netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst);
- if (!netfs_trans_dst_pool)
- goto err_out_free;
-
- return 0;
-
-err_out_free:
- kmem_cache_destroy(netfs_trans_dst);
-err_out_exit:
- return err;
-}
-
-void netfs_trans_exit(void)
-{
- mempool_destroy(netfs_trans_dst_pool);
- kmem_cache_destroy(netfs_trans_dst);
-}
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
index 9b5d771e650c..ed85b4415207 100644
--- a/drivers/staging/rtl8712/drv_types.h
+++ b/drivers/staging/rtl8712/drv_types.h
@@ -37,6 +37,8 @@ struct _adapter;
#include "wlan_bssdef.h"
#include "rtl8712_spec.h"
#include "rtl8712_hal.h"
+#include <linux/mutex.h>
+#include <linux/completion.h>
enum _NIC_VERSION {
RTL8711_NIC,
@@ -168,6 +170,7 @@ struct _adapter {
s32 bSurpriseRemoved;
u32 IsrContent;
u32 ImrContent;
+ bool fw_found;
u8 EepromAddressSize;
u8 hw_init_completed;
struct task_struct *cmdThread;
@@ -184,6 +187,10 @@ struct _adapter {
_workitem wkFilterRxFF0;
u8 blnEnableRxFF0Filter;
spinlock_t lockRxFF0Filter;
+ const struct firmware *fw;
+ struct usb_interface *pusb_intf;
+ struct mutex mutex_start;
+ struct completion rtl8712_fw_ready;
};
static inline u8 *myid(struct eeprom_priv *peepriv)
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index d0029aa4cd3c..cc893c0f5ad3 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -42,29 +42,56 @@
#define FWBUFF_ALIGN_SZ 512
#define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/
-static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
- const u8 **ppmappedfw)
+static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
{
+ struct _adapter *padapter = context;
+
+ complete(&padapter->rtl8712_fw_ready);
+ if (!firmware) {
+ struct usb_device *udev = padapter->dvobjpriv.pusbdev;
+ struct usb_interface *pusb_intf = padapter->pusb_intf;
+ printk(KERN_ERR "r8712u: Firmware request failed\n");
+ padapter->fw_found = false;
+ usb_put_dev(udev);
+ usb_set_intfdata(pusb_intf, NULL);
+ return;
+ }
+ padapter->fw = firmware;
+ padapter->fw_found = true;
+ /* firmware available - start netdev */
+ register_netdev(padapter->pnetdev);
+}
+
+static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+
+int rtl871x_load_fw(struct _adapter *padapter)
+{
+ struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
int rc;
- const char firmware_file[] = "rtlwifi/rtl8712u.bin";
- const struct firmware **praw = (const struct firmware **)
- (pphfwfile_hdl);
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
- (&padapter->dvobjpriv);
- struct usb_device *pusbdev = pdvobjpriv->pusbdev;
+ init_completion(&padapter->rtl8712_fw_ready);
printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
firmware_file);
- rc = request_firmware(praw, firmware_file, &pusbdev->dev);
- if (rc < 0) {
- printk(KERN_ERR "r8712u: Unable to load firmware\n");
- printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+ rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+ GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+ if (rc)
+ printk(KERN_ERR "r8712u: Firmware request error %d\n", rc);
+ return rc;
+}
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+
+static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
+{
+ const struct firmware **praw = &padapter->fw;
+
+ if (padapter->fw->size > 200000) {
+ printk(KERN_ERR "r8172u: Badfw->size of %d\n",
+ (int)padapter->fw->size);
return 0;
}
*ppmappedfw = (u8 *)((*praw)->data);
return (*praw)->size;
}
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
{
@@ -142,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
struct fw_hdr fwhdr;
u32 ulfilelength; /* FW file size */
- void *phfwfile_hdl = NULL;
const u8 *pmappedfw = NULL;
u8 *ptmpchar = NULL, *ppayload, *ptr;
struct tx_desc *ptx_desc;
u32 txdscp_sz = sizeof(struct tx_desc);
u8 ret = _FAIL;
- ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw);
+ ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);
if (pmappedfw && (ulfilelength > 0)) {
update_fwhdr(&fwhdr, pmappedfw);
if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
- goto firmware_rel;
+ return ret;
fill_fwpriv(padapter, &fwhdr.fwpriv);
/* firmware check ok */
maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
@@ -161,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
maxlen += txdscp_sz;
ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);
if (ptmpchar == NULL)
- goto firmware_rel;
+ return ret;
ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -
((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1)));
@@ -297,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)
exit_fail:
kfree(ptmpchar);
-firmware_rel:
- release_firmware((struct firmware *)phfwfile_hdl);
return ret;
}
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 9a75c6dbe505..98a3d684f9b2 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
+#include <linux/firmware.h>
#include "osdep_service.h"
#include "drv_types.h"
#include "xmit_osdep.h"
@@ -264,12 +265,12 @@ static void start_drv_timers(struct _adapter *padapter)
void r8712_stop_drv_timers(struct _adapter *padapter)
{
_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
- _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
- sitesurvey_ctrl_timer);
_cancel_timer_ex(&padapter->securitypriv.tkip_timer);
_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
_cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
_cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
+ _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
+ sitesurvey_ctrl_timer);
}
static u8 init_default_value(struct _adapter *padapter)
@@ -347,7 +348,8 @@ u8 r8712_free_drv_sw(struct _adapter *padapter)
r8712_free_mlme_priv(&padapter->mlmepriv);
r8712_free_io_queue(padapter);
_free_xmit_priv(&padapter->xmitpriv);
- _r8712_free_sta_priv(&padapter->stapriv);
+ if (padapter->fw_found)
+ _r8712_free_sta_priv(&padapter->stapriv);
_r8712_free_recv_priv(&padapter->recvpriv);
mp871xdeinit(padapter);
if (pnetdev)
@@ -388,6 +390,7 @@ static int netdev_open(struct net_device *pnetdev)
{
struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+ mutex_lock(&padapter->mutex_start);
if (padapter->bup == false) {
padapter->bDriverStopped = false;
padapter->bSurpriseRemoved = false;
@@ -435,11 +438,13 @@ static int netdev_open(struct net_device *pnetdev)
/* start driver mlme relation timer */
start_drv_timers(padapter);
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+ mutex_unlock(&padapter->mutex_start);
return 0;
netdev_open_error:
padapter->bup = false;
netif_carrier_off(pnetdev);
netif_stop_queue(pnetdev);
+ mutex_unlock(&padapter->mutex_start);
return -1;
}
@@ -473,6 +478,9 @@ static int netdev_close(struct net_device *pnetdev)
r8712_free_network_queue(padapter);
/* The interface is no longer Up: */
padapter->bup = false;
+ release_firmware(padapter->fw);
+ /* never exit with a firmware callback pending */
+ wait_for_completion(&padapter->rtl8712_fw_ready);
return 0;
}
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
index 665e71838172..d19865a5a50c 100644
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ b/drivers/staging/rtl8712/rtl8712_hal.h
@@ -145,5 +145,6 @@ struct hal_priv {
};
uint rtl8712_hal_init(struct _adapter *padapter);
+int rtl871x_load_fw(struct _adapter *padapter);
#endif
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 64f569618839..81bde803c59f 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -43,6 +43,7 @@ static void _init_stainfo(struct sta_info *psta)
_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
#ifdef CONFIG_R8712_AP
+ _init_listhead(&psta->asoc_list);
_init_listhead(&psta->auth_list);
#endif
}
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 5385da2e9cdb..9bade184883b 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -89,6 +89,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
{USB_DEVICE(0x0DF6, 0x0045)},
{USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
{USB_DEVICE(0x0DF6, 0x004B)},
+ {USB_DEVICE(0x0DF6, 0x005B)},
{USB_DEVICE(0x0DF6, 0x005D)},
{USB_DEVICE(0x0DF6, 0x0063)},
/* Sweex */
@@ -389,6 +390,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
pdvobjpriv = &padapter->dvobjpriv;
pdvobjpriv->padapter = padapter;
padapter->dvobjpriv.pusbdev = udev;
+ padapter->pusb_intf = pusb_intf;
usb_set_intfdata(pusb_intf, pnetdev);
SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
/* step 2. */
@@ -595,10 +597,11 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
"%pM\n", mac);
memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
}
- /* step 6. Tell the network stack we exist */
- if (register_netdev(pnetdev) != 0)
+ /* step 6. Load the firmware asynchronously */
+ if (rtl871x_load_fw(padapter))
goto error;
spin_lock_init(&padapter->lockRxFF0Filter);
+ mutex_init(&padapter->mutex_start);
return 0;
error:
usb_put_dev(udev);
@@ -629,7 +632,8 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
flush_scheduled_work();
udelay(1);
/*Stop driver mlme relation timer */
- r8712_stop_drv_timers(padapter);
+ if (padapter->fw_found)
+ r8712_stop_drv_timers(padapter);
r871x_dev_unload(padapter);
r8712_free_drv_sw(padapter);
}
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index e1c4492a7105..dde559d06c43 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -1046,8 +1046,6 @@ static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt)
/* Free the driver's device context: */
kfree(drv_datap->base_img);
- kfree(drv_datap);
- dev_set_drvdata(bridge, NULL);
kfree((void *)dev_ctxt);
return status;
}
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 76cfc6edecd9..385740bad0de 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -410,6 +410,9 @@ static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev)
DBC_ASSERT(ret == true);
}
+ kfree(drv_datap);
+ dev_set_drvdata(bridge, NULL);
+
func_cont:
mem_ext_phys_pool_release();
@@ -500,35 +503,42 @@ static int bridge_open(struct inode *ip, struct file *filp)
}
#endif
pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
- if (pr_ctxt) {
- pr_ctxt->res_state = PROC_RES_ALLOCATED;
- spin_lock_init(&pr_ctxt->dmm_map_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
- spin_lock_init(&pr_ctxt->dmm_rsv_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
-
- pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (pr_ctxt->node_id) {
- idr_init(pr_ctxt->node_id);
- } else {
- status = -ENOMEM;
- goto err;
- }
+ if (!pr_ctxt)
+ return -ENOMEM;
+
+ pr_ctxt->res_state = PROC_RES_ALLOCATED;
+ spin_lock_init(&pr_ctxt->dmm_map_lock);
+ INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
+ spin_lock_init(&pr_ctxt->dmm_rsv_lock);
+ INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
- pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (pr_ctxt->stream_id)
- idr_init(pr_ctxt->stream_id);
- else
- status = -ENOMEM;
- } else {
+ pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ if (!pr_ctxt->node_id) {
status = -ENOMEM;
+ goto err1;
}
-err:
+
+ idr_init(pr_ctxt->node_id);
+
+ pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ if (!pr_ctxt->stream_id) {
+ status = -ENOMEM;
+ goto err2;
+ }
+
+ idr_init(pr_ctxt->stream_id);
+
filp->private_data = pr_ctxt;
+
#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- if (!status)
- atomic_inc(&bridge_cref);
+ atomic_inc(&bridge_cref);
#endif
+ return 0;
+
+err2:
+ kfree(pr_ctxt->node_id);
+err1:
+ kfree(pr_ctxt);
return status;
}
@@ -550,6 +560,8 @@ static int bridge_release(struct inode *ip, struct file *filp)
flush_signals(current);
drv_remove_all_resources(pr_ctxt);
proc_detach(pr_ctxt);
+ kfree(pr_ctxt->node_id);
+ kfree(pr_ctxt->stream_id);
kfree(pr_ctxt);
filp->private_data = NULL;
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index 2d6317850064..705a9e530a19 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -246,8 +246,9 @@ static int __init usbip_host_init(void)
{
int ret;
- stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
+ init_busid_table();
+ stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
if (!stub_priv_cache) {
pr_err("kmem_cache_create failed\n");
return -ENOMEM;
@@ -266,7 +267,6 @@ static int __init usbip_host_init(void)
goto err_create_file;
}
- init_busid_table();
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
return ret;
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index 642840c612ac..ef7c52bb1df9 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -358,8 +358,8 @@ static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,
if (unlikely(zbpg == NULL))
goto out;
/* ok, have a page, now compress the data before taking locks */
- spin_lock(&zbpg->lock);
spin_lock(&zbud_budlists_spinlock);
+ spin_lock(&zbpg->lock);
list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);
zbud_unbuddied[nchunks].count++;
zh = &zbpg->buddy[0];
@@ -389,12 +389,11 @@ init_zh:
zh->oid = *oid;
zh->pool_id = pool_id;
zh->client_id = client_id;
- /* can wait to copy the data until the list locks are dropped */
- spin_unlock(&zbud_budlists_spinlock);
-
to = zbud_data(zh, size);
memcpy(to, cdata, size);
spin_unlock(&zbpg->lock);
+ spin_unlock(&zbud_budlists_spinlock);
+
zbud_cumul_chunk_counts[nchunks]++;
atomic_inc(&zcache_zbud_curr_zpages);
zcache_zbud_cumul_zpages++;
@@ -655,8 +654,8 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7;
*/
static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5;
-static unsigned long zv_curr_dist_counts[NCHUNKS];
-static unsigned long zv_cumul_dist_counts[NCHUNKS];
+static atomic_t zv_curr_dist_counts[NCHUNKS];
+static atomic_t zv_cumul_dist_counts[NCHUNKS];
static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
struct tmem_oid *oid, uint32_t index,
@@ -675,8 +674,8 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
&page, &offset, ZCACHE_GFP_MASK);
if (unlikely(ret))
goto out;
- zv_curr_dist_counts[chunks]++;
- zv_cumul_dist_counts[chunks]++;
+ atomic_inc(&zv_curr_dist_counts[chunks]);
+ atomic_inc(&zv_cumul_dist_counts[chunks]);
zv = kmap_atomic(page, KM_USER0) + offset;
zv->index = index;
zv->oid = *oid;
@@ -698,7 +697,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
ASSERT_SENTINEL(zv, ZVH);
BUG_ON(chunks >= NCHUNKS);
- zv_curr_dist_counts[chunks]--;
+ atomic_dec(&zv_curr_dist_counts[chunks]);
size -= sizeof(*zv);
BUG_ON(size == 0);
INVERT_SENTINEL(zv, ZVH);
@@ -738,7 +737,7 @@ static int zv_curr_dist_counts_show(char *buf)
char *p = buf;
for (i = 0; i < NCHUNKS; i++) {
- n = zv_curr_dist_counts[i];
+ n = atomic_read(&zv_curr_dist_counts[i]);
p += sprintf(p, "%lu ", n);
chunks += n;
sum_total_chunks += i * n;
@@ -754,7 +753,7 @@ static int zv_cumul_dist_counts_show(char *buf)
char *p = buf;
for (i = 0; i < NCHUNKS; i++) {
- n = zv_cumul_dist_counts[i];
+ n = atomic_read(&zv_cumul_dist_counts[i]);
p += sprintf(p, "%lu ", n);
chunks += n;
sum_total_chunks += i * n;
@@ -1782,9 +1781,9 @@ static int zcache_frontswap_poolid = -1;
* Swizzling increases objects per swaptype, increasing tmem concurrency
* for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS
* Setting SWIZ_BITS to 27 basically reconstructs the swap entry from
- * frontswap_get_page()
+ * frontswap_get_page(), but has side-effects. Hence using 8.
*/
-#define SWIZ_BITS 27
+#define SWIZ_BITS 8
#define SWIZ_MASK ((1 << SWIZ_BITS) - 1)
#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
#define iswiz(_ind) (_ind >> SWIZ_BITS)
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index ac44af165b27..44262908def5 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1061,7 +1061,7 @@ attach_cmd:
if (ret < 0)
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
- 1, 1, buf, cmd);
+ 1, 0, buf, cmd);
/*
* Check the CmdSN against ExpCmdSN/MaxCmdSN here if
* the Immediate Bit is not set, and no Immediate
@@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
return 0;
}
+static bool iscsit_check_inaddr_any(struct iscsi_np *np)
+{
+ bool ret = false;
+
+ if (np->np_sockaddr.ss_family == AF_INET6) {
+ const struct sockaddr_in6 sin6 = {
+ .sin6_addr = IN6ADDR_ANY_INIT };
+ struct sockaddr_in6 *sock_in6 =
+ (struct sockaddr_in6 *)&np->np_sockaddr;
+
+ if (!memcmp(sock_in6->sin6_addr.s6_addr,
+ sin6.sin6_addr.s6_addr, 16))
+ ret = true;
+ } else {
+ struct sockaddr_in * sock_in =
+ (struct sockaddr_in *)&np->np_sockaddr;
+
+ if (sock_in->sin_addr.s_addr == INADDR_ANY)
+ ret = true;
+ }
+
+ return ret;
+}
+
static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
{
char *payload = NULL;
@@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
spin_lock(&tpg->tpg_np_lock);
list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
tpg_np_list) {
+ struct iscsi_np *np = tpg_np->tpg_np;
+ bool inaddr_any = iscsit_check_inaddr_any(np);
+
len = sprintf(buf, "TargetAddress="
"%s%s%s:%hu,%hu",
- (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
- "[" : "", tpg_np->tpg_np->np_ip,
- (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
- "]" : "", tpg_np->tpg_np->np_port,
+ (np->np_sockaddr.ss_family == AF_INET6) ?
+ "[" : "", (inaddr_any == false) ?
+ np->np_ip : conn->local_ip,
+ (np->np_sockaddr.ss_family == AF_INET6) ?
+ "]" : "", (inaddr_any == false) ?
+ np->np_port : conn->local_port,
tpg->tpgt);
len += 1;
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 3468caab47a2..6b35b37988ed 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -21,6 +21,7 @@
#include <linux/configfs.h>
#include <linux/export.h>
+#include <linux/inet.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index f1a02dad05a0..0ec3b77a0c27 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -508,6 +508,7 @@ struct iscsi_conn {
u16 cid;
/* Remote TCP Port */
u16 login_port;
+ u16 local_port;
int net_size;
u32 auth_id;
#define CONNFLAG_SCTP_STRUCT_FILE 0x01
@@ -527,6 +528,7 @@ struct iscsi_conn {
unsigned char bad_hdr[ISCSI_HDR_LEN];
#define IPV6_ADDRESS_SPACE 48
unsigned char login_ip[IPV6_ADDRESS_SPACE];
+ unsigned char local_ip[IPV6_ADDRESS_SPACE];
int conn_usage_count;
int conn_waiting_on_uc;
atomic_t check_immediate_queue;
@@ -561,8 +563,8 @@ struct iscsi_conn {
struct hash_desc conn_tx_hash;
/* Used for scheduling TX and RX connection kthreads */
cpumask_var_t conn_cpumask;
- int conn_rx_reset_cpumask:1;
- int conn_tx_reset_cpumask:1;
+ unsigned int conn_rx_reset_cpumask:1;
+ unsigned int conn_tx_reset_cpumask:1;
/* list_head of struct iscsi_cmd for this connection */
struct list_head conn_cmd_list;
struct list_head immed_queue_list;
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 255c0d67e898..27901e37c125 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
{
struct iscsi_conn *conn = cmd->conn;
struct iscsi_session *sess = conn->sess;
- struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+ struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
spin_lock_bh(&cmd->dataout_timeout_lock);
if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
@@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
struct iscsi_conn *conn)
{
struct iscsi_session *sess = conn->sess;
- struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+ struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
return;
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 373b0cc6abd8..38cb7ce8469e 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -615,8 +615,8 @@ static int iscsi_post_login_handler(
}
pr_debug("iSCSI Login successful on CID: %hu from %s to"
- " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
- np->np_port, tpg->tpgt);
+ " %s:%hu,%hu\n", conn->cid, conn->login_ip,
+ conn->local_ip, conn->local_port, tpg->tpgt);
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
atomic_inc(&sess->nconn);
@@ -658,7 +658,8 @@ static int iscsi_post_login_handler(
sess->session_state = TARG_SESS_STATE_LOGGED_IN;
pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
- conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
+ conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
+ tpg->tpgt);
spin_lock_bh(&sess->conn_lock);
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
@@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(
goto fail;
}
+ ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
+ (char *)&opt, sizeof(opt));
+ if (ret < 0) {
+ pr_err("kernel_setsockopt() for IP_FREEBIND"
+ " failed\n");
+ goto fail;
+ }
+
ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
if (ret < 0) {
pr_err("kernel_bind() failed: %d\n", ret);
@@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
&sock_in6.sin6_addr.in6_u);
conn->login_port = ntohs(sock_in6.sin6_port);
+
+ if (conn->sock->ops->getname(conn->sock,
+ (struct sockaddr *)&sock_in6, &err, 0) < 0) {
+ pr_err("sock_ops->getname() failed.\n");
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_TARGET_ERROR);
+ goto new_sess_out;
+ }
+ snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
+ &sock_in6.sin6_addr.in6_u);
+ conn->local_port = ntohs(sock_in6.sin6_port);
+
} else {
memset(&sock_in, 0, sizeof(struct sockaddr_in));
@@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
}
sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
conn->login_port = ntohs(sock_in.sin_port);
+
+ if (conn->sock->ops->getname(conn->sock,
+ (struct sockaddr *)&sock_in, &err, 0) < 0) {
+ pr_err("sock_ops->getname() failed.\n");
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_TARGET_ERROR);
+ goto new_sess_out;
+ }
+ sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
+ conn->local_port = ntohs(sock_in.sin_port);
}
conn->network_transport = np->np_network_transport;
@@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
pr_debug("Received iSCSI login request from %s on %s Network"
" Portal %s:%hu\n", conn->login_ip,
(conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
- np->np_ip, np->np_port);
+ conn->local_ip, conn->local_port);
pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
conn->conn_state = TARG_CONN_STATE_IN_LOGIN;
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index a05ca1c4f01c..11287e1ece13 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
case ISCSI_OP_SCSI_TMFUNC:
transport_generic_free_cmd(&cmd->se_cmd, 1);
break;
+ case ISCSI_OP_REJECT:
+ /*
+ * Handle special case for REJECT when iscsi_add_reject*() has
+ * overwritten the original iscsi_opcode assignment, and the
+ * associated cmd->se_cmd needs to be released.
+ */
+ if (cmd->se_cmd.se_tfo != NULL) {
+ transport_generic_free_cmd(&cmd->se_cmd, 1);
+ break;
+ }
+ /* Fall-through */
default:
iscsit_release_cmd(cmd);
break;
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 1b1edd14f4bf..01a2691dfb47 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
@@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
buf[2] = ((rd_len >> 8) & 0xff);
buf[3] = (rd_len & 0xff);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
@@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
/*
* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
@@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
}
out:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
return 0;
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 2f2235edefff..f3d71fa88a28 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
buf[0] = 0x3f; /* Not connected */
@@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
buf[4] = 31; /* Set additional length to 31 */
out:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
return 0;
}
@@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)
int p, ret;
if (!(cdb[1] & 0x1)) {
+ if (cdb[2]) {
+ pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
+ cdb[2]);
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+ return -EINVAL;
+ }
+
ret = target_emulate_inquiry_std(cmd);
goto out;
}
@@ -716,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = dev->transport->get_device_type(dev);
@@ -729,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)
}
pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
- cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
out_unmap:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
out:
if (!ret) {
task->task_scsi_status = GOOD;
@@ -755,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)
else
blocks = (u32)blocks_long;
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = (blocks >> 24) & 0xff;
buf[1] = (blocks >> 16) & 0xff;
@@ -771,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
put_unaligned_be32(0xFFFFFFFF, &buf[0]);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
@@ -785,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
unsigned char *buf;
unsigned long long blocks = dev->transport->get_blocks(dev);
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = (blocks >> 56) & 0xff;
buf[1] = (blocks >> 48) & 0xff;
@@ -806,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
buf[14] = 0x80;
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
@@ -1019,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)
offset = cmd->data_length;
}
- rbuf = transport_kmap_first_data_page(cmd);
+ rbuf = transport_kmap_data_sg(cmd);
memcpy(rbuf, buf, offset);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
@@ -1043,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)
return -ENOSYS;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
/*
@@ -1051,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)
*/
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
- /*
- * Make sure request data length is enough for additional
- * sense data.
- */
- if (cmd->data_length <= 18) {
+
+ if (cmd->data_length < 18) {
buf[7] = 0x00;
err = -EINVAL;
goto end;
@@ -1072,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)
*/
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
- /*
- * Make sure request data length is enough for additional
- * sense data.
- */
- if (cmd->data_length <= 18) {
+
+ if (cmd->data_length < 18) {
buf[7] = 0x00;
err = -EINVAL;
goto end;
@@ -1089,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)
}
end:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
return 0;
@@ -1123,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)
dl = get_unaligned_be16(&cdb[0]);
bd_dl = get_unaligned_be16(&cdb[2]);
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
ptr = &buf[offset];
pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
@@ -1147,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)
}
err:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
if (!ret) {
task->task_scsi_status = GOOD;
transport_complete_task(task, 1);
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 0955bb8979fb..6e043eeb1db9 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias(
return -EINVAL;
}
- se_dev->su_dev_flags |= SDF_USING_ALIAS;
read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
"%s", page);
-
+ if (!read_bytes)
+ return -EINVAL;
if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
se_dev->se_dev_alias[read_bytes - 1] = '\0';
+ se_dev->su_dev_flags |= SDF_USING_ALIAS;
+
pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
@@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path(
return -EINVAL;
}
- se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
"%s", page);
-
+ if (!read_bytes)
+ return -EINVAL;
if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
+ se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
+
pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 0c5992f0d946..edbcabbf85f7 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -320,11 +320,12 @@ int core_free_device_list_for_node(
void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
{
struct se_dev_entry *deve;
+ unsigned long flags;
- spin_lock_irq(&se_nacl->device_list_lock);
+ spin_lock_irqsave(&se_nacl->device_list_lock, flags);
deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
deve->deve_cmds--;
- spin_unlock_irq(&se_nacl->device_list_lock);
+ spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
}
void core_update_device_list_access(
@@ -656,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
unsigned char *buf;
u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
- buf = transport_kmap_first_data_page(se_cmd);
+ buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
/*
* If no struct se_session pointer is present, this struct se_cmd is
@@ -694,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
* See SPC3 r07, page 159.
*/
done:
- transport_kunmap_first_data_page(se_cmd);
+ transport_kunmap_data_sg(se_cmd);
lun_count *= 8;
buf[0] = ((lun_count >> 24) & 0xff);
buf[1] = ((lun_count >> 16) & 0xff);
@@ -1294,24 +1295,26 @@ struct se_lun *core_dev_add_lun(
{
struct se_lun *lun_p;
u32 lun_access = 0;
+ int rc;
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
atomic_read(&dev->dev_access_obj.obj_access_count));
- return NULL;
+ return ERR_PTR(-EACCES);
}
lun_p = core_tpg_pre_addlun(tpg, lun);
- if ((IS_ERR(lun_p)) || !lun_p)
- return NULL;
+ if (IS_ERR(lun_p))
+ return lun_p;
if (dev->dev_flags & DF_READ_ONLY)
lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
else
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
- if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
- return NULL;
+ rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
+ if (rc < 0)
+ return ERR_PTR(rc);
pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -1348,11 +1351,10 @@ int core_dev_del_lun(
u32 unpacked_lun)
{
struct se_lun *lun;
- int ret = 0;
- lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
- if (!lun)
- return ret;
+ lun = core_tpg_pre_dellun(tpg, unpacked_lun);
+ if (IS_ERR(lun))
+ return PTR_ERR(lun);
core_tpg_post_dellun(tpg, lun);
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 4f77cce22646..9a2ce11e1a6e 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -766,9 +766,9 @@ static int target_fabric_port_link(
lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
lun->unpacked_lun);
- if (IS_ERR(lun_p) || !lun_p) {
+ if (IS_ERR(lun_p)) {
pr_err("core_dev_add_lun() failed\n");
- ret = -EINVAL;
+ ret = PTR_ERR(lun_p);
goto out;
}
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index cc8e6b58ef20..8572eae62da7 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(
/*
* These settings need to be made tunable..
*/
- ib_dev->ibd_bio_set = bioset_create(32, 64);
+ ib_dev->ibd_bio_set = bioset_create(32, 0);
if (!ib_dev->ibd_bio_set) {
pr_err("IBLOCK: Unable to create bioset()\n");
return ERR_PTR(-ENOMEM);
@@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(
*/
dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
dev->se_sub_dev->se_dev_attrib.unmap_granularity =
- q->limits.discard_granularity;
+ q->limits.discard_granularity >> 9;
dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
q->limits.discard_alignment;
@@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
struct iblock_req *ib_req = IBLOCK_REQ(task);
struct bio *bio;
+ /*
+ * Only allocate as many vector entries as the bio code allows us to,
+ * we'll loop later on until we have handled the whole request.
+ */
+ if (sg_num > BIO_MAX_PAGES)
+ sg_num = BIO_MAX_PAGES;
+
bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
if (!bio) {
pr_err("Unable to allocate memory for bio\n");
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 26f135e94f6e..45001364788a 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -90,7 +90,7 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
u32, void *);
-struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
+struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
/* target_core_transport.c */
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 429ad7291664..b7c779389eea 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(
case READ_MEDIA_SERIAL_NUMBER:
case REPORT_LUNS:
case REQUEST_SENSE:
+ case PERSISTENT_RESERVE_IN:
ret = 0; /*/ Allowed CDBs */
break;
default:
@@ -1534,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
tidh_new->dest_local_nexus = 1;
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
/*
* For a PERSISTENT RESERVE OUT specify initiator ports payload,
* first extract TransportID Parameter Data Length, and make sure
@@ -1785,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
}
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
/*
* Go ahead and create a registrations from tid_dest_list for the
@@ -1833,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(
return 0;
out:
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
/*
* For the failure case, release everything from tid_dest_list
* including *dest_pr_reg and the configfs dependances..
@@ -3120,7 +3121,7 @@ static int core_scsi3_pro_preempt(
if (!calling_it_nexus)
core_scsi3_ua_allocate(pr_reg_nacl,
pr_res_mapped_lun, 0x2A,
- ASCQ_2AH_RESERVATIONS_PREEMPTED);
+ ASCQ_2AH_REGISTRATIONS_PREEMPTED);
}
spin_unlock(&pr_tmpl->registration_lock);
/*
@@ -3233,7 +3234,7 @@ static int core_scsi3_pro_preempt(
* additional sense code set to REGISTRATIONS PREEMPTED;
*/
core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
- ASCQ_2AH_RESERVATIONS_PREEMPTED);
+ ASCQ_2AH_REGISTRATIONS_PREEMPTED);
}
spin_unlock(&pr_tmpl->registration_lock);
/*
@@ -3410,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(
* will be moved to for the TransportID containing SCSI initiator WWN
* information.
*/
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
rtpi = (buf[18] & 0xff) << 8;
rtpi |= buf[19] & 0xff;
tid_len = (buf[20] & 0xff) << 24;
tid_len |= (buf[21] & 0xff) << 16;
tid_len |= (buf[22] & 0xff) << 8;
tid_len |= buf[23] & 0xff;
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
buf = NULL;
if ((tid_len + 24) != cmd->data_length) {
@@ -3469,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
proto_ident = (buf[24] & 0x0f);
#if 0
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
@@ -3503,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(
goto out;
}
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
buf = NULL;
pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
@@ -3768,13 +3769,13 @@ after_iport_check:
" REGISTER_AND_MOVE\n");
}
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
core_scsi3_put_pr_reg(dest_pr_reg);
return 0;
out:
if (buf)
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
if (dest_se_deve)
core_scsi3_lunacl_undepend_item(dest_se_deve);
if (dest_node_acl)
@@ -3848,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
scope = (cdb[2] & 0xf0);
type = (cdb[2] & 0x0f);
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
/*
* From PERSISTENT_RESERVE_OUT parameter list (payload)
*/
@@ -3866,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
aptpl = (buf[17] & 0x01);
unreg = (buf[17] & 0x02);
}
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
buf = NULL;
/*
@@ -3966,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4000,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
buf[6] = ((add_len >> 8) & 0xff);
buf[7] = (add_len & 0xff);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
return 0;
}
@@ -4026,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4085,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
err:
spin_unlock(&se_dev->dev_reservation_lock);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
return 0;
}
@@ -4109,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = ((add_len << 8) & 0xff);
buf[1] = (add_len & 0xff);
@@ -4141,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
return 0;
}
@@ -4171,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
return -EINVAL;
}
- buf = transport_kmap_first_data_page(cmd);
+ buf = transport_kmap_data_sg(cmd);
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
@@ -4292,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
buf[6] = ((add_len >> 8) & 0xff);
buf[7] = (add_len & 0xff);
- transport_kunmap_first_data_page(cmd);
+ transport_kunmap_data_sg(cmd);
return 0;
}
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index d35467d42e12..8d4def30e9e8 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)
if (task->task_se_cmd->se_deve->lun_flags &
TRANSPORT_LUNFLAGS_READ_ONLY) {
- unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd);
+ unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
if (cdb[0] == MODE_SENSE_10) {
if (!(buf[3] & 0x80))
@@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)
buf[2] |= 0x80;
}
- transport_kunmap_first_data_page(task->task_se_cmd);
+ transport_kunmap_data_sg(task->task_se_cmd);
}
}
after_mode_sense:
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index b7668029bb31..06336ecd872d 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun(
struct se_lun *core_tpg_pre_dellun(
struct se_portal_group *tpg,
- u32 unpacked_lun,
- int *ret)
+ u32 unpacked_lun)
{
struct se_lun *lun;
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d3ddd1361949..58cea07b12fb 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev)
static void scsi_dump_inquiry(struct se_device *dev)
{
struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
+ char buf[17];
int i, device_type;
/*
* Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
*/
- pr_debug(" Vendor: ");
for (i = 0; i < 8; i++)
if (wwn->vendor[i] >= 0x20)
- pr_debug("%c", wwn->vendor[i]);
+ buf[i] = wwn->vendor[i];
else
- pr_debug(" ");
+ buf[i] = ' ';
+ buf[i] = '\0';
+ pr_debug(" Vendor: %s\n", buf);
- pr_debug(" Model: ");
for (i = 0; i < 16; i++)
if (wwn->model[i] >= 0x20)
- pr_debug("%c", wwn->model[i]);
+ buf[i] = wwn->model[i];
else
- pr_debug(" ");
+ buf[i] = ' ';
+ buf[i] = '\0';
+ pr_debug(" Model: %s\n", buf);
- pr_debug(" Revision: ");
for (i = 0; i < 4; i++)
if (wwn->revision[i] >= 0x20)
- pr_debug("%c", wwn->revision[i]);
+ buf[i] = wwn->revision[i];
else
- pr_debug(" ");
-
- pr_debug("\n");
+ buf[i] = ' ';
+ buf[i] = '\0';
+ pr_debug(" Revision: %s\n", buf);
device_type = dev->transport->get_device_type(dev);
pr_debug(" Type: %s ", scsi_device_type(device_type));
@@ -1655,7 +1657,7 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
* This may only be called from process context, and also currently
* assumes internal allocation of fabric payload buffer by target-core.
**/
-int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
u32 data_length, int task_attr, int data_dir, int flags)
{
@@ -1688,15 +1690,21 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
/*
* Locate se_lun pointer and attach it to struct se_cmd
*/
- if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0)
- goto out_check_cond;
+ if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
+ transport_send_check_condition_and_sense(se_cmd,
+ se_cmd->scsi_sense_reason, 0);
+ target_put_sess_cmd(se_sess, se_cmd);
+ return;
+ }
/*
* Sanitize CDBs via transport_generic_cmd_sequencer() and
* allocate the necessary tasks to complete the received CDB+data
*/
rc = transport_generic_allocate_tasks(se_cmd, cdb);
- if (rc != 0)
- goto out_check_cond;
+ if (rc != 0) {
+ transport_generic_request_failure(se_cmd);
+ return;
+ }
/*
* Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
* for immediate execution of READs, otherwise wait for
@@ -1704,12 +1712,7 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
* when fabric has filled the incoming buffer.
*/
transport_handle_cdb_direct(se_cmd);
- return 0;
-
-out_check_cond:
- transport_send_check_condition_and_sense(se_cmd,
- se_cmd->scsi_sense_reason, 0);
- return 0;
+ return;
}
EXPORT_SYMBOL(target_submit_cmd);
@@ -2694,7 +2697,7 @@ static int transport_generic_cmd_sequencer(
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (target_check_write_same_discard(&cdb[10], dev) < 0)
- goto out_invalid_cdb_field;
+ goto out_unsupported_cdb;
if (!passthrough)
cmd->execute_task = target_emulate_write_same;
break;
@@ -2977,7 +2980,7 @@ static int transport_generic_cmd_sequencer(
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
if (target_check_write_same_discard(&cdb[1], dev) < 0)
- goto out_invalid_cdb_field;
+ goto out_unsupported_cdb;
if (!passthrough)
cmd->execute_task = target_emulate_write_same;
break;
@@ -3000,7 +3003,7 @@ static int transport_generic_cmd_sequencer(
* of byte 1 bit 3 UNMAP instead of original reserved field
*/
if (target_check_write_same_discard(&cdb[1], dev) < 0)
- goto out_invalid_cdb_field;
+ goto out_unsupported_cdb;
if (!passthrough)
cmd->execute_task = target_emulate_write_same;
break;
@@ -3082,11 +3085,6 @@ static int transport_generic_cmd_sequencer(
(cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
goto out_unsupported_cdb;
- /* Let's limit control cdbs to a page, for simplicity's sake. */
- if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
- size > PAGE_SIZE)
- goto out_invalid_cdb_field;
-
transport_set_supported_SAM_opcode(cmd);
return ret;
@@ -3490,9 +3488,11 @@ int transport_generic_map_mem_to_cmd(
}
EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
-void *transport_kmap_first_data_page(struct se_cmd *cmd)
+void *transport_kmap_data_sg(struct se_cmd *cmd)
{
struct scatterlist *sg = cmd->t_data_sg;
+ struct page **pages;
+ int i;
BUG_ON(!sg);
/*
@@ -3500,15 +3500,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)
* tcm_loop who may be using a contig buffer from the SCSI midlayer for
* control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
*/
- return kmap(sg_page(sg)) + sg->offset;
+ if (!cmd->t_data_nents)
+ return NULL;
+ else if (cmd->t_data_nents == 1)
+ return kmap(sg_page(sg)) + sg->offset;
+
+ /* >1 page. use vmap */
+ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
+ if (!pages)
+ return NULL;
+
+ /* convert sg[] to pages[] */
+ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
+ pages[i] = sg_page(sg);
+ }
+
+ cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL);
+ kfree(pages);
+ if (!cmd->t_data_vmap)
+ return NULL;
+
+ return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
}
-EXPORT_SYMBOL(transport_kmap_first_data_page);
+EXPORT_SYMBOL(transport_kmap_data_sg);
-void transport_kunmap_first_data_page(struct se_cmd *cmd)
+void transport_kunmap_data_sg(struct se_cmd *cmd)
{
- kunmap(sg_page(cmd->t_data_sg));
+ if (!cmd->t_data_nents)
+ return;
+ else if (cmd->t_data_nents == 1)
+ kunmap(sg_page(cmd->t_data_sg));
+
+ vunmap(cmd->t_data_vmap);
+ cmd->t_data_vmap = NULL;
}
-EXPORT_SYMBOL(transport_kunmap_first_data_page);
+EXPORT_SYMBOL(transport_kunmap_data_sg);
static int
transport_generic_get_mem(struct se_cmd *cmd)
@@ -3516,6 +3542,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
u32 length = cmd->data_length;
unsigned int nents;
struct page *page;
+ gfp_t zero_flag;
int i = 0;
nents = DIV_ROUND_UP(length, PAGE_SIZE);
@@ -3526,9 +3553,11 @@ transport_generic_get_mem(struct se_cmd *cmd)
cmd->t_data_nents = nents;
sg_init_table(cmd->t_data_sg, nents);
+ zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
+
while (length) {
u32 page_len = min_t(u32, length, PAGE_SIZE);
- page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ page = alloc_page(GFP_KERNEL | zero_flag);
if (!page)
goto out;
@@ -3756,6 +3785,11 @@ transport_allocate_control_task(struct se_cmd *cmd)
struct se_task *task;
unsigned long flags;
+ /* Workaround for handling zero-length control CDBs */
+ if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
+ !cmd->data_length)
+ return 0;
+
task = transport_generic_get_task(cmd, cmd->data_direction);
if (!task)
return -ENOMEM;
@@ -3827,6 +3861,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
cmd->t_state = TRANSPORT_COMPLETE;
atomic_set(&cmd->t_transport_active, 1);
+
+ if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
+ u8 ua_asc = 0, ua_ascq = 0;
+
+ core_scsi3_ua_clear_for_request_sense(cmd,
+ &ua_asc, &ua_ascq);
+ }
+
INIT_WORK(&cmd->work, target_complete_ok_work);
queue_work(target_completion_wq, &cmd->work);
return 0;
@@ -4448,8 +4490,8 @@ int transport_send_check_condition_and_sense(
/* CURRENT ERROR */
buffer[offset] = 0x70;
buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
- /* ABORTED COMMAND */
- buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+ /* ILLEGAL REQUEST */
+ buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN CDB */
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
break;
@@ -4457,8 +4499,8 @@ int transport_send_check_condition_and_sense(
/* CURRENT ERROR */
buffer[offset] = 0x70;
buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
- /* ABORTED COMMAND */
- buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+ /* ILLEGAL REQUEST */
+ buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN PARAMETER LIST */
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
break;
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index addc18f727ea..9e7e26c74c79 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -540,7 +540,6 @@ static void ft_send_work(struct work_struct *work)
int data_dir = 0;
u32 data_len;
int task_attr;
- int ret;
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
if (!fcp)
@@ -603,14 +602,10 @@ static void ft_send_work(struct work_struct *work)
* Use a single se_cmd->cmd_kref as we expect to release se_cmd
* directly from ft_check_stop_free callback in response path.
*/
- ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
+ target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
&cmd->ft_sense_buffer[0], cmd->lun, data_len,
task_attr, data_dir, 0);
- pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret);
- if (ret < 0) {
- ft_dump_cmd(cmd, __func__);
- return;
- }
+ pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
return;
err:
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 9f50c4e3c2be..9b7336fcfbb3 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -45,7 +45,7 @@
#include "8250.h"
#ifdef CONFIG_SPARC
-#include "suncore.h"
+#include "../suncore.h"
#endif
/*
diff --git a/drivers/tty/serial/8250/m32r_sio.c b/drivers/tty/serial/m32r_sio.c
index 94a6792bf97b..94a6792bf97b 100644
--- a/drivers/tty/serial/8250/m32r_sio.c
+++ b/drivers/tty/serial/m32r_sio.c
diff --git a/drivers/tty/serial/8250/m32r_sio.h b/drivers/tty/serial/m32r_sio.h
index e9b7e11793b1..e9b7e11793b1 100644
--- a/drivers/tty/serial/8250/m32r_sio.h
+++ b/drivers/tty/serial/m32r_sio.h
diff --git a/drivers/tty/serial/8250/m32r_sio_reg.h b/drivers/tty/serial/m32r_sio_reg.h
index 4671473793e3..4671473793e3 100644
--- a/drivers/tty/serial/8250/m32r_sio_reg.h
+++ b/drivers/tty/serial/m32r_sio_reg.h
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 1c2426931484..f80904145fd4 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -46,6 +46,13 @@
#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
+/* SCR register bitmasks */
+#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
+
+/* FCR register bitmasks */
+#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
+#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
@@ -129,6 +136,7 @@ static void serial_omap_enable_ms(struct uart_port *port)
static void serial_omap_stop_tx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
if (up->use_dma &&
up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
@@ -151,6 +159,9 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
+ if (!up->use_dma && pdata->set_forceidle)
+ pdata->set_forceidle(up->pdev);
+
pm_runtime_mark_last_busy(&up->pdev->dev);
pm_runtime_put_autosuspend(&up->pdev->dev);
}
@@ -279,6 +290,7 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
static void serial_omap_start_tx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
struct circ_buf *xmit;
unsigned int start;
int ret = 0;
@@ -286,6 +298,8 @@ static void serial_omap_start_tx(struct uart_port *port)
if (!up->use_dma) {
pm_runtime_get_sync(&up->pdev->dev);
serial_omap_enable_ier_thri(up);
+ if (pdata->set_noidle)
+ pdata->set_noidle(up->pdev);
pm_runtime_mark_last_busy(&up->pdev->dev);
pm_runtime_put_autosuspend(&up->pdev->dev);
return;
@@ -726,8 +740,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
quot = serial_omap_get_divisor(port, baud);
/* calculate wakeup latency constraint */
- up->calc_latency = (1000000 * up->port.fifosize) /
- (1000 * baud / 8);
+ up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);
up->latency = up->calc_latency;
schedule_work(&up->qos_work);
@@ -811,14 +824,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
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, UART_LCR_CONF_MODE_B);
+
+ up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
if (up->use_dma) {
serial_out(up, UART_TI752_TLR, 0);
- up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8);
+ up->scr |= UART_FCR_TRIGGER_4;
+ } else {
+ /* Set receive FIFO threshold to 1 byte */
+ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
+ up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
}
+ serial_out(up, UART_FCR, up->fcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
serial_out(up, UART_OMAP_SCR, up->scr);
serial_out(up, UART_EFR, up->efr);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f96f37b5fec6..c55e5fb16fa3 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1593,7 +1593,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#endif
-#ifdef CONFIG_CPU_EXYNOS4210
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \
+ defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung Exynos4 UART",
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 5e096f43bcea..65447c5f91d7 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
if (!perm && op->op != KD_FONT_OP_GET)
return -EPERM;
op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
- op->flags |= KD_FONT_FLAG_OLD;
i = con_font_op(vc, op);
if (i)
return i;
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 6d87f288df4e..2c0cd824c667 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -418,7 +418,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
/* support autoresume for remote wakeup testing */
if (autoresume)
- sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 91413cac97be..353cdd488b93 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -130,7 +130,7 @@ config USB_FSL_MPH_DR_OF
tristate
config USB_EHCI_FSL
- bool "Support for Freescale on-chip EHCI USB controller"
+ bool "Support for Freescale PPC on-chip EHCI USB controller"
depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF if OF
@@ -138,7 +138,7 @@ config USB_EHCI_FSL
Variation of ARC USB block used in some Freescale chips.
config USB_EHCI_MXC
- bool "Support for Freescale on-chip EHCI USB controller"
+ bool "Support for Freescale i.MX on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_MXC
select USB_EHCI_ROOT_HUB_TT
---help---
@@ -546,7 +546,7 @@ config USB_RENESAS_USBHS_HCD
config USB_WHCI_HCD
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on PCI && USB
+ depends on PCI && USB && UWB
select USB_WUSB
select UWB_WHCI
help
@@ -559,7 +559,7 @@ config USB_WHCI_HCD
config USB_HWA_HCD
tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on USB
+ depends on USB && UWB
select USB_WUSB
select UWB_HWA
help
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b556a72264d1..c26a82e83f6e 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -239,7 +239,7 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}
-static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
{
struct usb_hcd *hcd = ehci_to_hcd(ehci);
struct fsl_usb2_platform_data *pdata;
@@ -299,12 +299,19 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
#endif
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
}
+
+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) {
+ printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
+ return -ENODEV;
+ }
+ return 0;
}
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
{
- ehci_fsl_usb_setup(ehci);
+ if (ehci_fsl_usb_setup(ehci))
+ return -ENODEV;
ehci_port_power(ehci, 0);
return 0;
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 491806221165..bdf43e2adc51 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -45,5 +45,6 @@
#define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */
#define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */
#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */
+#define CTRL_PHY_CLK_VALID (1 << 17)
#define SNOOP_SIZE_2GB 0x1e
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index caf87428ca43..ac53a662a6a3 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -867,6 +867,12 @@ hc_init:
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{
+ /* Skip Netlogic mips SoC's internal PCI USB controller.
+ * This device does not need/support EHCI/OHCI handoff
+ */
+ if (pdev->vendor == 0x184e) /* vendor Netlogic */
+ return;
+
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index e61aa95f2d2a..1d5eda26fbd1 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -39,7 +39,8 @@
#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
&& !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
- && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN)
+ && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
+ && !defined(CONFIG_MIPS)
static inline void readsl(const void __iomem *addr, void *buf, int len)
{ insl((unsigned long)addr, buf, len); }
static inline void readsw(const void __iomem *addr, void *buf, int len)
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 76d629345418..735ef4c2339a 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -118,7 +118,7 @@ config FSL_USB2_OTG
config USB_MV_OTG
tristate "Marvell USB OTG support"
- depends on USB_MV_UDC && USB_SUSPEND
+ depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ad654f8208ef..f770415305f8 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -839,6 +839,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index f994503df2dd..6f6058f0db1b 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1187,3 +1187,10 @@
*/
/* ZigBee controller */
#define FTDI_RF_R106 0x8A28
+
+/*
+ * Product: HCP HIT GPRS modem
+ * Manufacturer: HCP d.o.o.
+ * ATI command output: Cinterion MC55i
+ */
+#define FTDI_CINTERION_MC55I_PID 0xA951
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ea126a4490cd..39ed1f46cec0 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -855,6 +855,18 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0098, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0099, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
@@ -883,7 +895,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
@@ -892,6 +903,12 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1066,6 +1083,116 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1403, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1404, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1405, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1406, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1407, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1408, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1409, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1410, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1411, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1412, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1413, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1414, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1415, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1416, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1417, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1418, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1419, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1420, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1421, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1422, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1423, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1427, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1429, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1430, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1431, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1432, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1433, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1434, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1435, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1436, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1437, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1438, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1439, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1440, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1441, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1442, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1443, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1444, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1445, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1446, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1447, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1448, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1449, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1450, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1451, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1452, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1453, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1454, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1455, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1456, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1457, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1458, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1459, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1460, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1461, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1462, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1463, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1464, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1465, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1466, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1467, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1468, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1469, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1470, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1471, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1472, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1473, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1474, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1475, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1476, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1477, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1478, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1479, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1480, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1482, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1483, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1484, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1485, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1486, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1487, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1488, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1489, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1490, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1491, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1492, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1493, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1494, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1495, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1496, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1497, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1498, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1499, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1500, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1501, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1502, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1503, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1504, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1505, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1506, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1507, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1508, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1509, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1510, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 1d5deee3be52..f98800f2324c 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -36,6 +36,11 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
{USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
{USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */
+ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */
{USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
{USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
{USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
@@ -86,7 +91,16 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
+ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
+ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
{USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
+ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -123,8 +137,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
spin_lock_init(&data->susp_lock);
- usb_enable_autosuspend(serial->dev);
-
switch (nintf) {
case 1:
/* QDL mode */
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 0d7b20d4285d..e40c00f2c2ba 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -1108,7 +1108,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
*/
lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
- sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+ sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index acf292bfba02..6af3f16754f0 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
struct fsl_diu_data *data;
data = dev_get_drvdata(&ofdev->dev);
- disable_lcdc(data->fsl_diu_info[0]);
+ disable_lcdc(data->fsl_diu_info);
return 0;
}
@@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev)
struct fsl_diu_data *data;
data = dev_get_drvdata(&ofdev->dev);
- enable_lcdc(data->fsl_diu_info[0]);
+ enable_lcdc(data->fsl_diu_info);
return 0;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index c6afa33a4532..02fd2263610c 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
ERR_MSG("Could not allocate cmap for intelfb_info.\n");
goto err_out_cmap;
- return -ENODEV;
}
dinfo = info->par;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index a5ec7f37c185..e1626a1d5c45 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -401,7 +401,7 @@ void dispc_runtime_put(void)
DSSDBG("dispc_runtime_put\n");
- r = pm_runtime_put(&dispc.pdev->dev);
+ r = pm_runtime_put_sync(&dispc.pdev->dev);
WARN_ON(r < 0);
}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 395d658a94fc..faaf305fda27 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -180,6 +180,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
{
int r;
+ if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
+ DSSERR("no VDSS_DSI regulator\n");
+ return -ENODEV;
+ }
+
if (dssdev->manager == NULL) {
DSSERR("failed to enable display: no manager\n");
return -ENODEV;
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index d4d676c82c12..52f36ec1c8bb 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1079,7 +1079,7 @@ void dsi_runtime_put(struct platform_device *dsidev)
DSSDBG("dsi_runtime_put\n");
- r = pm_runtime_put(&dsi->pdev->dev);
+ r = pm_runtime_put_sync(&dsi->pdev->dev);
WARN_ON(r < 0);
}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 17033457ee89..77c2b5a32b5d 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -720,7 +720,7 @@ void dss_runtime_put(void)
DSSDBG("dss_runtime_put\n");
- r = pm_runtime_put(&dss.pdev->dev);
+ r = pm_runtime_put_sync(&dss.pdev->dev);
WARN_ON(r < 0);
}
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b4c270edb915..d7aa3b056529 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -176,7 +176,7 @@ static void hdmi_runtime_put(void)
DSSDBG("hdmi_runtime_put\n");
- r = pm_runtime_put(&hdmi.pdev->dev);
+ r = pm_runtime_put_sync(&hdmi.pdev->dev);
WARN_ON(r < 0);
}
@@ -497,6 +497,7 @@ bool omapdss_hdmi_detect(void)
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
{
+ struct omap_dss_hdmi_data *priv = dssdev->data;
int r = 0;
DSSDBG("ENTER hdmi_display_enable\n");
@@ -509,6 +510,8 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
goto err0;
}
+ hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 814bb9500dca..55f398014f33 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -140,7 +140,7 @@ static void rfbi_runtime_put(void)
DSSDBG("rfbi_runtime_put\n");
- r = pm_runtime_put(&rfbi.pdev->dev);
+ r = pm_runtime_put_sync(&rfbi.pdev->dev);
WARN_ON(r < 0);
}
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 7503f7f619a7..50dadba5070a 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -126,6 +126,10 @@ struct hdmi_ip_data {
const struct ti_hdmi_ip_ops *ops;
struct hdmi_config cfg;
struct hdmi_pll_info pll_data;
+
+ /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
+ int hpd_gpio;
+ bool phy_tx_enabled;
};
int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index 9af81f18f163..2d72334ca3da 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/seq_file.h>
+#include <linux/gpio.h>
#include "ti_hdmi_4xxx_ip.h"
#include "dss.h"
@@ -223,6 +224,49 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
}
+static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data)
+{
+ unsigned long flags;
+ bool hpd;
+ int r;
+ /* this should be in ti_hdmi_4xxx_ip private data */
+ static DEFINE_SPINLOCK(phy_tx_lock);
+
+ spin_lock_irqsave(&phy_tx_lock, flags);
+
+ hpd = gpio_get_value(ip_data->hpd_gpio);
+
+ if (hpd == ip_data->phy_tx_enabled) {
+ spin_unlock_irqrestore(&phy_tx_lock, flags);
+ return 0;
+ }
+
+ if (hpd)
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+ else
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+
+ if (r) {
+ DSSERR("Failed to %s PHY TX power\n",
+ hpd ? "enable" : "disable");
+ goto err;
+ }
+
+ ip_data->phy_tx_enabled = hpd;
+err:
+ spin_unlock_irqrestore(&phy_tx_lock, flags);
+ return r;
+}
+
+static irqreturn_t hpd_irq_handler(int irq, void *data)
+{
+ struct hdmi_ip_data *ip_data = data;
+
+ hdmi_check_hpd_state(ip_data);
+
+ return IRQ_HANDLED;
+}
+
int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
{
u16 r = 0;
@@ -232,10 +276,6 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
if (r)
return r;
- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
- if (r)
- return r;
-
/*
* Read address 0 in order to get the SCP reset done completed
* Dummy access performed to make sure reset is done
@@ -257,12 +297,32 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
/* Write to phy address 3 to change the polarity control */
REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+ r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
+ NULL, hpd_irq_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "hpd", ip_data);
+ if (r) {
+ DSSERR("HPD IRQ request failed\n");
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+ return r;
+ }
+
+ r = hdmi_check_hpd_state(ip_data);
+ if (r) {
+ free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+ return r;
+ }
+
return 0;
}
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
{
+ free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+ ip_data->phy_tx_enabled = false;
}
static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index b3e9f9091581..5c3d0f901510 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -401,7 +401,7 @@ static void venc_runtime_put(void)
DSSDBG("venc_runtime_put\n");
- r = pm_runtime_put(&venc.pdev->dev);
+ r = pm_runtime_put_sync(&venc.pdev->dev);
WARN_ON(r < 0);
}
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 14e2d995e958..4dcfced107f5 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -30,7 +30,8 @@ static int vcpu_online(unsigned int cpu)
sprintf(dir, "cpu/%u", cpu);
err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
if (err != 1) {
- printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
+ if (!xen_initial_domain())
+ printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
return err;
}
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 7944a17f5cbf..19834d1c7c36 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -884,7 +884,7 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
int err;
err =
- sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+ sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot,
func, reg, size, mask);
if (err == 7)
return 0;
@@ -904,7 +904,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
pci_dev_id->bus = bus;
pci_dev_id->devfn = PCI_DEVFN(slot, func);
- pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%01x\n",
+ pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
domain, bus, slot, func);
spin_lock_irqsave(&device_ids_lock, flags);
@@ -934,7 +934,7 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
err = 0;
- pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%01x from "
+ pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%d from "
"seize list\n", domain, bus, slot, func);
}
}
@@ -1029,7 +1029,7 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
break;
count += scnprintf(buf + count, PAGE_SIZE - count,
- "%04x:%02x:%02x.%01x\n",
+ "%04x:%02x:%02x.%d\n",
pci_dev_id->domain, pci_dev_id->bus,
PCI_SLOT(pci_dev_id->devfn),
PCI_FUNC(pci_dev_id->devfn));
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index d5dcf8d5d3d9..64b11f99eacc 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -206,6 +206,7 @@ static int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev,
goto out;
}
+ /* Note: The PV protocol uses %02x, don't change it */
err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
"%04x:%02x:%02x.%02x", domain, bus,
PCI_SLOT(devfn), PCI_FUNC(devfn));
@@ -229,7 +230,7 @@ static int xen_pcibk_export_device(struct xen_pcibk_device *pdev,
err = -EINVAL;
xenbus_dev_fatal(pdev->xdev, err,
"Couldn't locate PCI device "
- "(%04x:%02x:%02x.%01x)! "
+ "(%04x:%02x:%02x.%d)! "
"perhaps already in-use?",
domain, bus, slot, func);
goto out;
@@ -274,7 +275,7 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
if (!dev) {
err = -EINVAL;
dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
- "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
+ "(%04x:%02x:%02x.%d)! not owned by this domain\n",
domain, bus, slot, func);
goto out;
}
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 527dc2a3b89f..89f76252a16f 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -369,6 +369,10 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
goto out;
}
token++;
+ if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) {
+ rc = -EILSEQ;
+ goto out;
+ }
if (msg_type == XS_WATCH) {
watch = alloc_watch_adapter(path, token);
diff --git a/fs/bio.c b/fs/bio.c
index b1fe82cf88cf..b980ecde026a 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -505,13 +505,9 @@ EXPORT_SYMBOL(bio_clone);
int bio_get_nr_vecs(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
- int nr_pages;
-
- nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT;
- if (nr_pages > queue_max_segments(q))
- nr_pages = queue_max_segments(q);
-
- return nr_pages;
+ return min_t(unsigned,
+ queue_max_segments(q),
+ queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1);
}
EXPORT_SYMBOL(bio_get_nr_vecs);
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index b60fc8bfb3e9..620daad201db 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap)
unsigned long ttl;
u32 gen;
- spin_lock(&cap->session->s_cap_lock);
+ spin_lock(&cap->session->s_gen_ttl_lock);
gen = cap->session->s_cap_gen;
ttl = cap->session->s_cap_ttl;
- spin_unlock(&cap->session->s_cap_lock);
+ spin_unlock(&cap->session->s_gen_ttl_lock);
if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
dout("__cap_is_valid %p cap %p issued %s "
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 618246bc2196..3e8094be4604 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry)
di = ceph_dentry(dentry);
if (di->lease_session) {
s = di->lease_session;
- spin_lock(&s->s_cap_lock);
+ spin_lock(&s->s_gen_ttl_lock);
gen = s->s_cap_gen;
ttl = s->s_cap_ttl;
- spin_unlock(&s->s_cap_lock);
+ spin_unlock(&s->s_gen_ttl_lock);
if (di->lease_gen == gen &&
time_before(jiffies, dentry->d_time) &&
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 23ab6a3f1825..866e8d7ca37d 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg,
/* trace */
ceph_decode_32_safe(&p, end, len, bad);
if (len > 0) {
+ ceph_decode_need(&p, end, len, bad);
err = parse_reply_info_trace(&p, p+len, info, features);
if (err < 0)
goto out_bad;
@@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg,
/* extra */
ceph_decode_32_safe(&p, end, len, bad);
if (len > 0) {
+ ceph_decode_need(&p, end, len, bad);
err = parse_reply_info_extra(&p, p+len, info, features);
if (err < 0)
goto out_bad;
@@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
s->s_con.peer_name.num = cpu_to_le64(mds);
- spin_lock_init(&s->s_cap_lock);
+ spin_lock_init(&s->s_gen_ttl_lock);
s->s_cap_gen = 0;
s->s_cap_ttl = 0;
+
+ spin_lock_init(&s->s_cap_lock);
s->s_renew_requested = 0;
s->s_renew_seq = 0;
INIT_LIST_HEAD(&s->s_caps);
@@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session,
case CEPH_SESSION_STALE:
pr_info("mds%d caps went stale, renewing\n",
session->s_mds);
- spin_lock(&session->s_cap_lock);
+ spin_lock(&session->s_gen_ttl_lock);
session->s_cap_gen++;
session->s_cap_ttl = 0;
- spin_unlock(&session->s_cap_lock);
+ spin_unlock(&session->s_gen_ttl_lock);
send_renew_caps(mdsc, session);
break;
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index a50ca0e39475..8c7c04ebb595 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -117,10 +117,13 @@ struct ceph_mds_session {
void *s_authorizer_buf, *s_authorizer_reply_buf;
size_t s_authorizer_buf_len, s_authorizer_reply_buf_len;
- /* protected by s_cap_lock */
- spinlock_t s_cap_lock;
+ /* protected by s_gen_ttl_lock */
+ spinlock_t s_gen_ttl_lock;
u32 s_cap_gen; /* inc each time we get mds stale msg */
unsigned long s_cap_ttl; /* when session caps expire */
+
+ /* protected by s_cap_lock */
+ spinlock_t s_cap_lock;
struct list_head s_caps; /* all caps issued by this session */
int s_nr_caps, s_trim_caps;
int s_num_cap_releases;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 857214ae8c08..a76f697303d9 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
}
static struct ceph_vxattr_cb ceph_file_vxattrs[] = {
+ { true, "ceph.file.layout", ceph_vxattrcb_layout},
+ /* The following extended attribute name is deprecated */
{ true, "ceph.layout", ceph_vxattrcb_layout},
- { NULL, NULL }
+ { true, NULL, NULL }
};
static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode)
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 0554b00a7b33..2b243af70aa3 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -139,7 +139,7 @@ config CIFS_DFS_UPCALL
points. If unsure, say N.
config CIFS_FSCACHE
- bool "Provide CIFS client caching support (EXPERIMENTAL)"
+ bool "Provide CIFS client caching support"
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
@@ -147,7 +147,7 @@ config CIFS_FSCACHE
manager. If unsure, say N.
config CIFS_ACL
- bool "Provide CIFS ACL support (EXPERIMENTAL)"
+ bool "Provide CIFS ACL support"
depends on CIFS_XATTR && KEYS
help
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 986709a8d903..602f77c304c9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -773,10 +773,11 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
cifs_dump_mem("Bad SMB: ", buf,
min_t(unsigned int, server->total_read, 48));
- if (mid)
- handle_mid(mid, server, smb_buffer, length);
+ if (!mid)
+ return length;
- return length;
+ handle_mid(mid, server, smb_buffer, length);
+ return 0;
}
static int
@@ -2125,7 +2126,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
down_read(&key->sem);
upayload = key->payload.data;
if (IS_ERR_OR_NULL(upayload)) {
- rc = PTR_ERR(key);
+ rc = upayload ? PTR_ERR(upayload) : -EINVAL;
goto out_key_put;
}
@@ -2142,14 +2143,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
len = delim - payload;
if (len > MAX_USERNAME_SIZE || len <= 0) {
- cFYI(1, "Bad value from username search (len=%ld)", len);
+ cFYI(1, "Bad value from username search (len=%zd)", len);
rc = -EINVAL;
goto out_key_put;
}
vol->username = kstrndup(payload, len, GFP_KERNEL);
if (!vol->username) {
- cFYI(1, "Unable to allocate %ld bytes for username", len);
+ cFYI(1, "Unable to allocate %zd bytes for username", len);
rc = -ENOMEM;
goto out_key_put;
}
@@ -2157,7 +2158,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
len = key->datalen - (len + 1);
if (len > MAX_PASSWORD_SIZE || len <= 0) {
- cFYI(1, "Bad len for password search (len=%ld)", len);
+ cFYI(1, "Bad len for password search (len=%zd)", len);
rc = -EINVAL;
kfree(vol->username);
vol->username = NULL;
@@ -2167,7 +2168,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
++delim;
vol->password = kstrndup(delim, len, GFP_KERNEL);
if (!vol->password) {
- cFYI(1, "Unable to allocate %ld bytes for password", len);
+ cFYI(1, "Unable to allocate %zd bytes for password", len);
rc = -ENOMEM;
kfree(vol->username);
vol->username = NULL;
@@ -3857,10 +3858,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
struct smb_vol *vol_info;
vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
- if (vol_info == NULL) {
- tcon = ERR_PTR(-ENOMEM);
- goto out;
- }
+ if (vol_info == NULL)
+ return ERR_PTR(-ENOMEM);
vol_info->local_nls = cifs_sb->local_nls;
vol_info->linux_uid = fsuid;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index df8fecb5b993..63a196b97d50 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
{
int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
- __u32 oplock = 0;
+ __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
__u16 fileHandle = 0;
bool posix_open = false;
struct cifs_sb_info *cifs_sb;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index d85efad5765f..551d0c2b9736 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
/* copy user */
/* BB what about null user mounts - check that we do this BB */
/* copy user */
- if (ses->user_name != NULL)
+ if (ses->user_name != NULL) {
strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
+ bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
+ }
/* else null user mount */
-
- bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
*bcc_ptr = 0;
bcc_ptr++; /* account for null termination */
/* copy domain */
-
if (ses->domainName != NULL) {
strncpy(bcc_ptr, ses->domainName, 256);
bcc_ptr += strnlen(ses->domainName, 256);
@@ -395,6 +394,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
+ if (tioffset > blob_len || tioffset + tilen > blob_len) {
+ cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen);
+ return -EINVAL;
+ }
if (tilen) {
ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
if (!ses->auth_key.response) {
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 63ab24510649..ea9931281557 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1990,6 +1990,17 @@ out:
return;
}
+static size_t ecryptfs_max_decoded_size(size_t encoded_size)
+{
+ /* Not exact; conservatively long. Every block of 4
+ * encoded characters decodes into a block of 3
+ * decoded characters. This segment of code provides
+ * the caller with the maximum amount of allocated
+ * space that @dst will need to point to in a
+ * subsequent call. */
+ return ((encoded_size + 1) * 3) / 4;
+}
+
/**
* ecryptfs_decode_from_filename
* @dst: If NULL, this function only sets @dst_size and returns. If
@@ -2008,13 +2019,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
size_t dst_byte_offset = 0;
if (dst == NULL) {
- /* Not exact; conservatively long. Every block of 4
- * encoded characters decodes into a block of 3
- * decoded characters. This segment of code provides
- * the caller with the maximum amount of allocated
- * space that @dst will need to point to in a
- * subsequent call. */
- (*dst_size) = (((src_size + 1) * 3) / 4);
+ (*dst_size) = ecryptfs_max_decoded_size(src_size);
goto out;
}
while (src_byte_offset < src_size) {
@@ -2239,3 +2244,52 @@ out_free:
out:
return rc;
}
+
+#define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143
+
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+ struct blkcipher_desc desc;
+ struct mutex *tfm_mutex;
+ size_t cipher_blocksize;
+ int rc;
+
+ if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
+ (*namelen) = lower_namelen;
+ return 0;
+ }
+
+ rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
+ mount_crypt_stat->global_default_fn_cipher_name);
+ if (unlikely(rc)) {
+ (*namelen) = 0;
+ return rc;
+ }
+
+ mutex_lock(tfm_mutex);
+ cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm);
+ mutex_unlock(tfm_mutex);
+
+ /* Return an exact amount for the common cases */
+ if (lower_namelen == NAME_MAX
+ && (cipher_blocksize == 8 || cipher_blocksize == 16)) {
+ (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16;
+ return 0;
+ }
+
+ /* Return a safe estimate for the uncommon cases */
+ (*namelen) = lower_namelen;
+ (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
+ /* Since this is the max decoded size, subtract 1 "decoded block" len */
+ (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3;
+ (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE;
+ (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES;
+ /* Worst case is that the filename is padded nearly a full block size */
+ (*namelen) -= cipher_blocksize - 1;
+
+ if ((*namelen) < 0)
+ (*namelen) = 0;
+
+ return 0;
+}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a2362df58ae8..867b64c5d84f 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -162,6 +162,10 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */
#define MD5_DIGEST_SIZE 16
#define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE
+#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \
+ + ECRYPTFS_SIG_SIZE + 1 + 1)
+#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \
+ + ECRYPTFS_SIG_SIZE + 1 + 1)
#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED."
#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23
#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
@@ -701,6 +705,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
size_t *packet_size,
struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
char *data, size_t max_packet_size);
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
loff_t offset);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 19892d7d2ed1..ab35b113003b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -1085,6 +1085,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
}
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
+ if (!rc)
+ fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode);
out:
return rc;
}
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 8e3b943e330f..2333203a120b 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -679,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
* Octets N3-N4: Block-aligned encrypted filename
* - Consists of a minimum number of random characters, a \0
* separator, and then the filename */
- s->max_packet_size = (1 /* Tag 70 identifier */
- + 3 /* Max Tag 70 packet size */
- + ECRYPTFS_SIG_SIZE /* FNEK sig */
- + 1 /* Cipher identifier */
+ s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE
+ s->block_aligned_filename_size);
if (dest == NULL) {
(*packet_size) = s->max_packet_size;
@@ -934,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
goto out;
}
s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
- if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) {
+ if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
"at least [%d]\n", __func__, max_packet_size,
- (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1));
+ ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
rc = -EINVAL;
goto out;
}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 10ec695ccd68..a46b3a8fee1e 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -150,7 +150,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
/* This is a header extent */
char *page_virt;
- page_virt = kmap_atomic(page, KM_USER0);
+ page_virt = kmap_atomic(page);
memset(page_virt, 0, PAGE_CACHE_SIZE);
/* TODO: Support more than one header extent */
if (view_extent_num == 0) {
@@ -163,7 +163,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
crypt_stat,
&written);
}
- kunmap_atomic(page_virt, KM_USER0);
+ kunmap_atomic(page_virt);
flush_dcache_page(page);
if (rc) {
printk(KERN_ERR "%s: Error reading xattr "
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 5c0106f75775..b2a34a192f4f 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -156,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
ecryptfs_page_idx, rc);
goto out;
}
- ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+ ecryptfs_page_virt = kmap_atomic(ecryptfs_page);
/*
* pos: where we're now writing, offset: where the request was
@@ -179,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
(data + data_offset), num_bytes);
data_offset += num_bytes;
}
- kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+ kunmap_atomic(ecryptfs_page_virt);
flush_dcache_page(ecryptfs_page);
SetPageUptodate(ecryptfs_page);
unlock_page(ecryptfs_page);
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index 9df7fd6e0c39..cf152823bbf4 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -30,6 +30,8 @@
#include <linux/seq_file.h>
#include <linux/file.h>
#include <linux/crypto.h>
+#include <linux/statfs.h>
+#include <linux/magic.h>
#include "ecryptfs_kernel.h"
struct kmem_cache *ecryptfs_inode_info_cache;
@@ -102,10 +104,20 @@ static void ecryptfs_destroy_inode(struct inode *inode)
static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ int rc;
if (!lower_dentry->d_sb->s_op->statfs)
return -ENOSYS;
- return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+
+ rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+ if (rc)
+ return rc;
+
+ buf->f_type = ECRYPTFS_SUPER_MAGIC;
+ rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen,
+ &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat);
+
+ return rc;
}
/**
diff --git a/fs/exec.c b/fs/exec.c
index aeb135c7ff5c..92ce83a11e90 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf)
perf_event_comm(tsk);
}
+static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len)
+{
+ int i, ch;
+
+ /* Copies the binary name from after last slash */
+ for (i = 0; (ch = *(fn++)) != '\0';) {
+ if (ch == '/')
+ i = 0; /* overwrite what we wrote */
+ else
+ if (i < len - 1)
+ tcomm[i++] = ch;
+ }
+ tcomm[i] = '\0';
+}
+
int flush_old_exec(struct linux_binprm * bprm)
{
int retval;
@@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm)
set_mm_exe_file(bprm->mm, bprm->file);
+ filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm));
/*
* Release all of the old mmap stuff
*/
@@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump);
void setup_new_exec(struct linux_binprm * bprm)
{
- int i, ch;
- const char *name;
- char tcomm[sizeof(current->comm)];
-
arch_pick_mmap_layout(current->mm);
/* This is the point of no return */
@@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)
else
set_dumpable(current->mm, suid_dumpable);
- name = bprm->filename;
-
- /* Copies the binary name from after last slash */
- for (i=0; (ch = *(name++)) != '\0';) {
- if (ch == '/')
- i = 0; /* overwrite what we wrote */
- else
- if (i < (sizeof(tcomm) - 1))
- tcomm[i++] = ch;
- }
- tcomm[i] = '\0';
- set_task_comm(current, tcomm);
+ set_task_comm(current, bprm->tcomm);
/* Set the new mm task size. We have to do that late because it may
* depend on TIF_32BIT which is only updated in flush_thread() on
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index f855916657ba..5b4a9362d5aa 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -53,14 +53,6 @@ struct wb_writeback_work {
};
/*
- * Include the creation of the trace points after defining the
- * wb_writeback_work structure so that the definition remains local to this
- * file.
- */
-#define CREATE_TRACE_POINTS
-#include <trace/events/writeback.h>
-
-/*
* We don't actually have pdflush, but this one is exported though /proc...
*/
int nr_pdflush_threads;
@@ -92,6 +84,14 @@ static inline struct inode *wb_inode(struct list_head *head)
return list_entry(head, struct inode, i_wb_list);
}
+/*
+ * Include the creation of the trace points after defining the
+ * wb_writeback_work structure and inline functions so that the definition
+ * remains local to this file.
+ */
+#define CREATE_TRACE_POINTS
+#include <trace/events/writeback.h>
+
/* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */
static void bdi_wakeup_flusher(struct backing_dev_info *bdi)
{
diff --git a/fs/ioprio.c b/fs/ioprio.c
index f84b380d65e5..0f1b9515213b 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -51,7 +51,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);
if (ioc) {
ioc_ioprio_changed(ioc, ioprio);
- put_io_context(ioc, NULL);
+ put_io_context(ioc);
}
return err;
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index a01cdad6aad1..eafb8d37a6fb 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
void *ebuf;
uint32_t ofs;
size_t retlen;
- int ret = -EIO;
+ int ret;
unsigned long *wordebuf;
ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen,
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index e97404d611e0..9c501449450d 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs)
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = 0;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs += mtd->erasesize;
@@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs)
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = mtd->size - mtd->erasesize;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs -= mtd->erasesize;
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 886649627c3d..2a70fce70c65 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
nsegs = argv[4].v_nmembs;
if (argv[4].v_size != argsz[4])
goto out;
+ if (nsegs > UINT_MAX / sizeof(__u64))
+ goto out;
/*
* argv[4] points to segment numbers this ioctl cleans. We
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9cde9edf9c4d..d4548dd49b02 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
return result;
}
-static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
-{
- struct mm_struct *mm;
- int err;
-
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
- if (err)
- return ERR_PTR(err);
-
- mm = get_task_mm(task);
- if (mm && mm != current->mm &&
- !ptrace_may_access(task, mode)) {
- mmput(mm);
- mm = ERR_PTR(-EACCES);
- }
- mutex_unlock(&task->signal->cred_guard_mutex);
-
- return mm;
-}
-
struct mm_struct *mm_for_maps(struct task_struct *task)
{
return mm_access(task, PTRACE_MODE_READ);
@@ -711,6 +691,13 @@ static int mem_open(struct inode* inode, struct file* file)
if (IS_ERR(mm))
return PTR_ERR(mm);
+ if (mm) {
+ /* ensure this mm_struct can't be freed */
+ atomic_inc(&mm->mm_count);
+ /* but do not pin its memory */
+ mmput(mm);
+ }
+
/* OK to pass negative loff_t, we can catch out-of-range */
file->f_mode |= FMODE_UNSIGNED_OFFSET;
file->private_data = mm;
@@ -718,57 +705,13 @@ static int mem_open(struct inode* inode, struct file* file)
return 0;
}
-static ssize_t mem_read(struct file * file, char __user * buf,
- size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos, int write)
{
- int ret;
- char *page;
- unsigned long src = *ppos;
struct mm_struct *mm = file->private_data;
-
- if (!mm)
- return 0;
-
- page = (char *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- return -ENOMEM;
-
- ret = 0;
-
- while (count > 0) {
- int this_len, retval;
-
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- retval = access_remote_vm(mm, src, page, this_len, 0);
- if (!retval) {
- if (!ret)
- ret = -EIO;
- break;
- }
-
- if (copy_to_user(buf, page, retval)) {
- ret = -EFAULT;
- break;
- }
-
- ret += retval;
- src += retval;
- buf += retval;
- count -= retval;
- }
- *ppos = src;
-
- free_page((unsigned long) page);
- return ret;
-}
-
-static ssize_t mem_write(struct file * file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- int copied;
+ unsigned long addr = *ppos;
+ ssize_t copied;
char *page;
- unsigned long dst = *ppos;
- struct mm_struct *mm = file->private_data;
if (!mm)
return 0;
@@ -778,31 +721,54 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
return -ENOMEM;
copied = 0;
+ if (!atomic_inc_not_zero(&mm->mm_users))
+ goto free;
+
while (count > 0) {
- int this_len, retval;
+ int this_len = min_t(int, count, PAGE_SIZE);
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- if (copy_from_user(page, buf, this_len)) {
+ if (write && copy_from_user(page, buf, this_len)) {
copied = -EFAULT;
break;
}
- retval = access_remote_vm(mm, dst, page, this_len, 1);
- if (!retval) {
+
+ this_len = access_remote_vm(mm, addr, page, this_len, write);
+ if (!this_len) {
if (!copied)
copied = -EIO;
break;
}
- copied += retval;
- buf += retval;
- dst += retval;
- count -= retval;
+
+ if (!write && copy_to_user(buf, page, this_len)) {
+ copied = -EFAULT;
+ break;
+ }
+
+ buf += this_len;
+ addr += this_len;
+ copied += this_len;
+ count -= this_len;
}
- *ppos = dst;
+ *ppos = addr;
+ mmput(mm);
+free:
free_page((unsigned long) page);
return copied;
}
+static ssize_t mem_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, buf, count, ppos, 0);
+}
+
+static ssize_t mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
+
loff_t mem_lseek(struct file *file, loff_t offset, int orig)
{
switch (orig) {
@@ -822,8 +788,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
static int mem_release(struct inode *inode, struct file *file)
{
struct mm_struct *mm = file->private_data;
-
- mmput(mm);
+ if (mm)
+ mmdrop(mm);
return 0;
}
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 292eff198030..ab7c53fe346e 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -110,10 +110,4 @@ kmem_zone_destroy(kmem_zone_t *zone)
extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
-static inline int
-kmem_shake_allow(gfp_t gfp_mask)
-{
- return ((gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS));
-}
-
#endif /* __XFS_SUPPORT_KMEM_H__ */
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index b4ff40b5f918..cbcb7bea38e2 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -63,82 +63,6 @@ int xfs_dqerror_mod = 33;
static struct lock_class_key xfs_dquot_other_class;
/*
- * Allocate and initialize a dquot. We don't always allocate fresh memory;
- * we try to reclaim a free dquot if the number of incore dquots are above
- * a threshold.
- * The only field inside the core that gets initialized at this point
- * is the d_id field. The idea is to fill in the entire q_core
- * when we read in the on disk dquot.
- */
-STATIC xfs_dquot_t *
-xfs_qm_dqinit(
- xfs_mount_t *mp,
- xfs_dqid_t id,
- uint type)
-{
- xfs_dquot_t *dqp;
- boolean_t brandnewdquot;
-
- brandnewdquot = xfs_qm_dqalloc_incore(&dqp);
- dqp->dq_flags = type;
- dqp->q_core.d_id = cpu_to_be32(id);
- dqp->q_mount = mp;
-
- /*
- * No need to re-initialize these if this is a reclaimed dquot.
- */
- if (brandnewdquot) {
- INIT_LIST_HEAD(&dqp->q_freelist);
- mutex_init(&dqp->q_qlock);
- init_waitqueue_head(&dqp->q_pinwait);
-
- /*
- * Because we want to use a counting completion, complete
- * the flush completion once to allow a single access to
- * the flush completion without blocking.
- */
- init_completion(&dqp->q_flush);
- complete(&dqp->q_flush);
-
- trace_xfs_dqinit(dqp);
- } else {
- /*
- * Only the q_core portion was zeroed in dqreclaim_one().
- * So, we need to reset others.
- */
- dqp->q_nrefs = 0;
- dqp->q_blkno = 0;
- INIT_LIST_HEAD(&dqp->q_mplist);
- INIT_LIST_HEAD(&dqp->q_hashlist);
- dqp->q_bufoffset = 0;
- dqp->q_fileoffset = 0;
- dqp->q_transp = NULL;
- dqp->q_gdquot = NULL;
- dqp->q_res_bcount = 0;
- dqp->q_res_icount = 0;
- dqp->q_res_rtbcount = 0;
- atomic_set(&dqp->q_pincount, 0);
- dqp->q_hash = NULL;
- ASSERT(list_empty(&dqp->q_freelist));
-
- trace_xfs_dqreuse(dqp);
- }
-
- /*
- * In either case we need to make sure group quotas have a different
- * lock class than user quotas, to make sure lockdep knows we can
- * locks of one of each at the same time.
- */
- if (!(type & XFS_DQ_USER))
- lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);
-
- /*
- * log item gets initialized later
- */
- return (dqp);
-}
-
-/*
* This is called to free all the memory associated with a dquot
*/
void
@@ -567,7 +491,32 @@ xfs_qm_dqread(
int error;
int cancelflags = 0;
- dqp = xfs_qm_dqinit(mp, id, type);
+
+ dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
+
+ dqp->dq_flags = type;
+ dqp->q_core.d_id = cpu_to_be32(id);
+ dqp->q_mount = mp;
+ INIT_LIST_HEAD(&dqp->q_freelist);
+ mutex_init(&dqp->q_qlock);
+ init_waitqueue_head(&dqp->q_pinwait);
+
+ /*
+ * Because we want to use a counting completion, complete
+ * the flush completion once to allow a single access to
+ * the flush completion without blocking.
+ */
+ init_completion(&dqp->q_flush);
+ complete(&dqp->q_flush);
+
+ /*
+ * Make sure group quotas have a different lock class than user
+ * quotas.
+ */
+ if (!(type & XFS_DQ_USER))
+ lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);
+
+ atomic_inc(&xfs_Gqm->qm_totaldquots);
trace_xfs_dqread(dqp);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 541a508adea1..15ff5392fb65 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1489,7 +1489,7 @@ xlog_recover_add_to_cont_trans(
old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
old_len = item->ri_buf[item->ri_cnt-1].i_len;
- ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
+ ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP);
memcpy(&ptr[old_len], dp, len); /* d, s, l */
item->ri_buf[item->ri_cnt-1].i_len += len;
item->ri_buf[item->ri_cnt-1].i_addr = ptr;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 671f37eae1c7..c436def733bf 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -50,7 +50,6 @@
*/
struct mutex xfs_Gqm_lock;
struct xfs_qm *xfs_Gqm;
-uint ndquot;
kmem_zone_t *qm_dqzone;
kmem_zone_t *qm_dqtrxzone;
@@ -93,7 +92,6 @@ xfs_Gqm_init(void)
goto out_free_udqhash;
hsize /= sizeof(xfs_dqhash_t);
- ndquot = hsize << 8;
xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
xqm->qm_dqhashmask = hsize - 1;
@@ -137,7 +135,6 @@ xfs_Gqm_init(void)
xqm->qm_dqtrxzone = qm_dqtrxzone;
atomic_set(&xqm->qm_totaldquots, 0);
- xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO;
xqm->qm_nrefs = 0;
return xqm;
@@ -1600,216 +1597,150 @@ xfs_qm_init_quotainos(
return 0;
}
+STATIC void
+xfs_qm_dqfree_one(
+ struct xfs_dquot *dqp)
+{
+ struct xfs_mount *mp = dqp->q_mount;
+ struct xfs_quotainfo *qi = mp->m_quotainfo;
+ mutex_lock(&dqp->q_hash->qh_lock);
+ list_del_init(&dqp->q_hashlist);
+ dqp->q_hash->qh_version++;
+ mutex_unlock(&dqp->q_hash->qh_lock);
-/*
- * Pop the least recently used dquot off the freelist and recycle it.
- */
-STATIC struct xfs_dquot *
-xfs_qm_dqreclaim_one(void)
+ mutex_lock(&qi->qi_dqlist_lock);
+ list_del_init(&dqp->q_mplist);
+ qi->qi_dquots--;
+ qi->qi_dqreclaims++;
+ mutex_unlock(&qi->qi_dqlist_lock);
+
+ xfs_qm_dqdestroy(dqp);
+}
+
+STATIC void
+xfs_qm_dqreclaim_one(
+ struct xfs_dquot *dqp,
+ struct list_head *dispose_list)
{
- struct xfs_dquot *dqp;
- int restarts = 0;
+ struct xfs_mount *mp = dqp->q_mount;
+ int error;
- mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-restart:
- list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
- struct xfs_mount *mp = dqp->q_mount;
+ if (!xfs_dqlock_nowait(dqp))
+ goto out_busy;
- if (!xfs_dqlock_nowait(dqp))
- continue;
+ /*
+ * This dquot has acquired a reference in the meantime remove it from
+ * the freelist and try again.
+ */
+ if (dqp->q_nrefs) {
+ xfs_dqunlock(dqp);
- /*
- * This dquot has already been grabbed by dqlookup.
- * Remove it from the freelist and try again.
- */
- if (dqp->q_nrefs) {
- trace_xfs_dqreclaim_want(dqp);
- XQM_STATS_INC(xqmstats.xs_qm_dqwants);
-
- list_del_init(&dqp->q_freelist);
- xfs_Gqm->qm_dqfrlist_cnt--;
- restarts++;
- goto dqunlock;
- }
+ trace_xfs_dqreclaim_want(dqp);
+ XQM_STATS_INC(xqmstats.xs_qm_dqwants);
- ASSERT(dqp->q_hash);
- ASSERT(!list_empty(&dqp->q_mplist));
+ list_del_init(&dqp->q_freelist);
+ xfs_Gqm->qm_dqfrlist_cnt--;
+ return;
+ }
- /*
- * Try to grab the flush lock. If this dquot is in the process
- * of getting flushed to disk, we don't want to reclaim it.
- */
- if (!xfs_dqflock_nowait(dqp))
- goto dqunlock;
+ ASSERT(dqp->q_hash);
+ ASSERT(!list_empty(&dqp->q_mplist));
- /*
- * We have the flush lock so we know that this is not in the
- * process of being flushed. So, if this is dirty, flush it
- * DELWRI so that we don't get a freelist infested with
- * dirty dquots.
- */
- if (XFS_DQ_IS_DIRTY(dqp)) {
- int error;
+ /*
+ * Try to grab the flush lock. If this dquot is in the process of
+ * getting flushed to disk, we don't want to reclaim it.
+ */
+ if (!xfs_dqflock_nowait(dqp))
+ goto out_busy;
- trace_xfs_dqreclaim_dirty(dqp);
+ /*
+ * We have the flush lock so we know that this is not in the
+ * process of being flushed. So, if this is dirty, flush it
+ * DELWRI so that we don't get a freelist infested with
+ * dirty dquots.
+ */
+ if (XFS_DQ_IS_DIRTY(dqp)) {
+ trace_xfs_dqreclaim_dirty(dqp);
- /*
- * We flush it delayed write, so don't bother
- * releasing the freelist lock.
- */
- error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK);
- if (error) {
- xfs_warn(mp, "%s: dquot %p flush failed",
- __func__, dqp);
- }
- goto dqunlock;
+ /*
+ * We flush it delayed write, so don't bother releasing the
+ * freelist lock.
+ */
+ error = xfs_qm_dqflush(dqp, 0);
+ if (error) {
+ xfs_warn(mp, "%s: dquot %p flush failed",
+ __func__, dqp);
}
- xfs_dqfunlock(dqp);
/*
- * Prevent lookup now that we are going to reclaim the dquot.
- * Once XFS_DQ_FREEING is set lookup won't touch the dquot,
- * thus we can drop the lock now.
+ * Give the dquot another try on the freelist, as the
+ * flushing will take some time.
*/
- dqp->dq_flags |= XFS_DQ_FREEING;
- xfs_dqunlock(dqp);
-
- mutex_lock(&dqp->q_hash->qh_lock);
- list_del_init(&dqp->q_hashlist);
- dqp->q_hash->qh_version++;
- mutex_unlock(&dqp->q_hash->qh_lock);
-
- mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
- list_del_init(&dqp->q_mplist);
- mp->m_quotainfo->qi_dquots--;
- mp->m_quotainfo->qi_dqreclaims++;
- mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
+ goto out_busy;
+ }
+ xfs_dqfunlock(dqp);
- ASSERT(dqp->q_nrefs == 0);
- list_del_init(&dqp->q_freelist);
- xfs_Gqm->qm_dqfrlist_cnt--;
+ /*
+ * Prevent lookups now that we are past the point of no return.
+ */
+ dqp->dq_flags |= XFS_DQ_FREEING;
+ xfs_dqunlock(dqp);
- mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
- return dqp;
-dqunlock:
- xfs_dqunlock(dqp);
- if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
- break;
- goto restart;
- }
+ ASSERT(dqp->q_nrefs == 0);
+ list_move_tail(&dqp->q_freelist, dispose_list);
+ xfs_Gqm->qm_dqfrlist_cnt--;
- mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
- return NULL;
-}
+ trace_xfs_dqreclaim_done(dqp);
+ XQM_STATS_INC(xqmstats.xs_qm_dqreclaims);
+ return;
-/*
- * Traverse the freelist of dquots and attempt to reclaim a maximum of
- * 'howmany' dquots. This operation races with dqlookup(), and attempts to
- * favor the lookup function ...
- */
-STATIC int
-xfs_qm_shake_freelist(
- int howmany)
-{
- int nreclaimed = 0;
- xfs_dquot_t *dqp;
+out_busy:
+ xfs_dqunlock(dqp);
- if (howmany <= 0)
- return 0;
+ /*
+ * Move the dquot to the tail of the list so that we don't spin on it.
+ */
+ list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
- while (nreclaimed < howmany) {
- dqp = xfs_qm_dqreclaim_one();
- if (!dqp)
- return nreclaimed;
- xfs_qm_dqdestroy(dqp);
- nreclaimed++;
- }
- return nreclaimed;
+ trace_xfs_dqreclaim_busy(dqp);
+ XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);
}
-/*
- * The kmem_shake interface is invoked when memory is running low.
- */
-/* ARGSUSED */
STATIC int
xfs_qm_shake(
- struct shrinker *shrink,
- struct shrink_control *sc)
+ struct shrinker *shrink,
+ struct shrink_control *sc)
{
- int ndqused, nfree, n;
- gfp_t gfp_mask = sc->gfp_mask;
-
- if (!kmem_shake_allow(gfp_mask))
- return 0;
- if (!xfs_Gqm)
- return 0;
-
- nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */
- /* incore dquots in all f/s's */
- ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree;
-
- ASSERT(ndqused >= 0);
+ int nr_to_scan = sc->nr_to_scan;
+ LIST_HEAD (dispose_list);
+ struct xfs_dquot *dqp;
- if (nfree <= ndqused && nfree < ndquot)
+ if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
return 0;
+ if (!nr_to_scan)
+ goto out;
- ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */
- n = nfree - ndqused - ndquot; /* # over target */
-
- return xfs_qm_shake_freelist(MAX(nfree, n));
-}
-
-
-/*------------------------------------------------------------------*/
-
-/*
- * Return a new incore dquot. Depending on the number of
- * dquots in the system, we either allocate a new one on the kernel heap,
- * or reclaim a free one.
- * Return value is B_TRUE if we allocated a new dquot, B_FALSE if we managed
- * to reclaim an existing one from the freelist.
- */
-boolean_t
-xfs_qm_dqalloc_incore(
- xfs_dquot_t **O_dqpp)
-{
- xfs_dquot_t *dqp;
-
- /*
- * Check against high water mark to see if we want to pop
- * a nincompoop dquot off the freelist.
- */
- if (atomic_read(&xfs_Gqm->qm_totaldquots) >= ndquot) {
- /*
- * Try to recycle a dquot from the freelist.
- */
- if ((dqp = xfs_qm_dqreclaim_one())) {
- XQM_STATS_INC(xqmstats.xs_qm_dqreclaims);
- /*
- * Just zero the core here. The rest will get
- * reinitialized by caller. XXX we shouldn't even
- * do this zero ...
- */
- memset(&dqp->q_core, 0, sizeof(dqp->q_core));
- *O_dqpp = dqp;
- return B_FALSE;
- }
- XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);
+ mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
+ while (!list_empty(&xfs_Gqm->qm_dqfrlist)) {
+ if (nr_to_scan-- <= 0)
+ break;
+ dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot,
+ q_freelist);
+ xfs_qm_dqreclaim_one(dqp, &dispose_list);
}
+ mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
- /*
- * Allocate a brand new dquot on the kernel heap and return it
- * to the caller to initialize.
- */
- ASSERT(xfs_Gqm->qm_dqzone != NULL);
- *O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
- atomic_inc(&xfs_Gqm->qm_totaldquots);
-
- return B_TRUE;
+ while (!list_empty(&dispose_list)) {
+ dqp = list_first_entry(&dispose_list, struct xfs_dquot,
+ q_freelist);
+ list_del_init(&dqp->q_freelist);
+ xfs_qm_dqfree_one(dqp);
+ }
+out:
+ return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure;
}
-
/*
* Start a transaction and write the incore superblock changes to
* disk. flags parameter indicates which fields have changed.
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 9b4f3adefbc5..9a9b997e1a0a 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -26,24 +26,12 @@
struct xfs_qm;
struct xfs_inode;
-extern uint ndquot;
extern struct mutex xfs_Gqm_lock;
extern struct xfs_qm *xfs_Gqm;
extern kmem_zone_t *qm_dqzone;
extern kmem_zone_t *qm_dqtrxzone;
/*
- * Ditto, for xfs_qm_dqreclaim_one.
- */
-#define XFS_QM_RECLAIM_MAX_RESTARTS 4
-
-/*
- * Ideal ratio of free to in use dquots. Quota manager makes an attempt
- * to keep this balance.
- */
-#define XFS_QM_DQFREE_RATIO 2
-
-/*
* Dquot hashtable constants/threshold values.
*/
#define XFS_QM_HASHSIZE_LOW (PAGE_SIZE / sizeof(xfs_dqhash_t))
@@ -74,7 +62,6 @@ typedef struct xfs_qm {
int qm_dqfrlist_cnt;
atomic_t qm_totaldquots; /* total incore dquots */
uint qm_nrefs; /* file systems with quota on */
- int qm_dqfree_ratio;/* ratio of free to inuse dquots */
kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */
kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */
} xfs_qm_t;
@@ -143,7 +130,6 @@ extern int xfs_qm_quotacheck(xfs_mount_t *);
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
/* dquot stuff */
-extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint);
extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
diff --git a/fs/xfs/xfs_qm_stats.c b/fs/xfs/xfs_qm_stats.c
index 8671a0b32644..5729ba570877 100644
--- a/fs/xfs/xfs_qm_stats.c
+++ b/fs/xfs/xfs_qm_stats.c
@@ -42,9 +42,9 @@ static int xqm_proc_show(struct seq_file *m, void *v)
{
/* maximum; incore; ratio free to inuse; freelist */
seq_printf(m, "%d\t%d\t%d\t%u\n",
- ndquot,
+ 0,
xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
- xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
+ 0,
xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0);
return 0;
}
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 6b6df5802e95..bb134a819930 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -733,11 +733,10 @@ DEFINE_EVENT(xfs_dquot_class, name, \
DEFINE_DQUOT_EVENT(xfs_dqadjust);
DEFINE_DQUOT_EVENT(xfs_dqreclaim_want);
DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty);
-DEFINE_DQUOT_EVENT(xfs_dqreclaim_unlink);
+DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy);
+DEFINE_DQUOT_EVENT(xfs_dqreclaim_done);
DEFINE_DQUOT_EVENT(xfs_dqattach_found);
DEFINE_DQUOT_EVENT(xfs_dqattach_get);
-DEFINE_DQUOT_EVENT(xfs_dqinit);
-DEFINE_DQUOT_EVENT(xfs_dqreuse);
DEFINE_DQUOT_EVENT(xfs_dqalloc);
DEFINE_DQUOT_EVENT(xfs_dqtobp_read);
DEFINE_DQUOT_EVENT(xfs_dqread);
diff --git a/include/asm-generic/pci_iomap.h b/include/asm-generic/pci_iomap.h
index 8de4b73e19e2..e58fcf891370 100644
--- a/include/asm-generic/pci_iomap.h
+++ b/include/asm-generic/pci_iomap.h
@@ -15,6 +15,16 @@ struct pci_dev;
#ifdef CONFIG_PCI
/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+/* Create a virtual mapping cookie for a port on a given PCI device.
+ * Do not call this directly, it exists to make it easier for architectures
+ * to override */
+#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP
+extern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port,
+ unsigned int nr);
+#else
+#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr))
+#endif
+
#else
static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
{
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index fd88a3945aa1..0092102db2de 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -18,7 +18,7 @@ struct pt_regs;
#define BINPRM_BUF_SIZE 128
#ifdef __KERNEL__
-#include <linux/list.h>
+#include <linux/sched.h>
#define CORENAME_MAX_SIZE 128
@@ -58,6 +58,7 @@ struct linux_binprm {
unsigned interp_flags;
unsigned interp_data;
unsigned long loader, exec;
+ char tcomm[TASK_COMM_LEN];
};
#define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 3c1063acb2ab..94300fe46cce 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -56,6 +56,26 @@ static inline unsigned long hweight_long(unsigned long w)
}
/**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 rol64(__u64 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 ror64(__u64 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (64 - shift));
+}
+
+/**
* rol32 - rotate a 32-bit value left
* @word: value to rotate
* @shift: bits to roll
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6c6a1f008065..606cf339bb56 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -399,9 +399,6 @@ struct request_queue {
/* Throttle data */
struct throtl_data *td;
#endif
-#ifdef CONFIG_LOCKDEP
- int ioc_release_depth;
-#endif
};
#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 35eae4b67503..7c48029dffe6 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -952,7 +952,8 @@ struct cdrom_device_info {
char name[20]; /* name of the device type */
/* per-device flags */
__u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
- __u8 reserved : 6; /* not used yet */
+ __u8 keeplocked : 1; /* CDROM_LOCKDOOR status */
+ __u8 reserved : 5; /* not used yet */
int cdda_method; /* see flags */
__u8 last_sense;
__u8 media_written; /* dirty flag, DVD+RW bookkeeping */
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index c24f3d7fbf1e..7d4e0356f329 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -42,12 +42,6 @@ struct elevator_ops
elevator_merged_fn *elevator_merged_fn;
elevator_merge_req_fn *elevator_merge_req_fn;
elevator_allow_merge_fn *elevator_allow_merge_fn;
-
- /*
- * Used for both plugged list and elevator merging and in the
- * former case called without queue_lock. Read comment on top of
- * attempt_plug_merge() for details.
- */
elevator_bio_merged_fn *elevator_bio_merged_fn;
elevator_dispatch_fn *elevator_dispatch_fn;
@@ -122,7 +116,6 @@ extern void elv_dispatch_add_tail(struct request_queue *, struct request *);
extern void elv_add_request(struct request_queue *, struct request *, int);
extern void __elv_add_request(struct request_queue *, struct request *, int);
extern int elv_merge(struct request_queue *, struct request **, struct bio *);
-extern int elv_try_merge(struct request *, struct bio *);
extern void elv_merge_requests(struct request_queue *, struct request *,
struct request *);
extern void elv_merged_request(struct request_queue *, struct request *, int);
@@ -155,7 +148,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
extern int elevator_init(struct request_queue *, char *);
extern void elevator_exit(struct elevator_queue *);
extern int elevator_change(struct request_queue *, const char *);
-extern int elv_rq_merge_ok(struct request *, struct bio *);
+extern bool elv_rq_merge_ok(struct request *, struct bio *);
/*
* Helper functions.
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index b5ca4b2c08ec..004ff33ab38e 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -1,6 +1,8 @@
#ifndef _GPIO_KEYS_H
#define _GPIO_KEYS_H
+struct device;
+
struct gpio_keys_button {
/* Configuration parameters */
unsigned int code; /* input event code (KEY_*, SW_*) */
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 62b908e0e591..0ae065a5fcb2 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -35,7 +35,7 @@
#include <linux/mod_devicetable.h>
-#define MAX_PAGE_BUFFER_COUNT 18
+#define MAX_PAGE_BUFFER_COUNT 19
#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */
#pragma pack(push, 1)
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 7e1371c4bccf..119773eebe31 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -133,7 +133,7 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)
struct task_struct;
#ifdef CONFIG_BLOCK
-void put_io_context(struct io_context *ioc, struct request_queue *locked_q);
+void put_io_context(struct io_context *ioc);
void exit_io_context(struct task_struct *task);
struct io_context *get_task_io_context(struct task_struct *task,
gfp_t gfp_flags, int node);
@@ -141,8 +141,7 @@ void ioc_ioprio_changed(struct io_context *ioc, int ioprio);
void ioc_cgroup_changed(struct io_context *ioc);
#else
struct io_context;
-static inline void put_io_context(struct io_context *ioc,
- struct request_queue *locked_q) { }
+static inline void put_io_context(struct io_context *ioc) { }
static inline void exit_io_context(struct task_struct *task) { }
#endif
diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h
index d21fa2865bf4..d21fa2865bf4 100755..100644
--- a/include/linux/lp8727.h
+++ b/include/linux/lp8727.h
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 2463c2619596..9bc9ac651dad 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -187,8 +187,10 @@ struct twl6040 {
int rev;
u8 vibra_ctrl_cache[2];
+ /* PLL configuration */
int pll;
unsigned int sysclk;
+ unsigned int mclk;
unsigned int irq;
unsigned int irq_base;
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 3fb1f407d5e6..dc3e05011689 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -185,6 +185,9 @@ struct wm8994_pdata {
unsigned int jd_scthr:2;
unsigned int jd_thr:2;
+ /* Configure WM1811 jack detection for use with external capacitor */
+ unsigned int jd_ext_cap:1;
+
/* WM8958 microphone bias configuration */
int micbias[2];
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 9f22ba572de0..19a41d1737af 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -217,6 +217,7 @@ struct mmc_card {
#define MMC_CARD_SDXC (1<<6) /* card is SDXC */
#define MMC_CARD_REMOVED (1<<7) /* card has been removed */
#define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */
+#define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */
unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
@@ -382,6 +383,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
+#define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -393,7 +395,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
+#define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP)
+#define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP)
/*
* Quirk add/remove for MMC products.
*/
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index e8779c6d1759..aae5d1f1bb39 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -14,6 +14,8 @@
#ifndef LINUX_MMC_DW_MMC_H
#define LINUX_MMC_DW_MMC_H
+#include <linux/scatterlist.h>
+
#define MAX_MCI_SLOTS 2
enum dw_mci_state {
@@ -40,7 +42,7 @@ struct mmc_data;
* @lock: Spinlock protecting the queue and associated data.
* @regs: Pointer to MMIO registers.
* @sg: Scatterlist entry currently being processed by PIO code, if any.
- * @pio_offset: Offset into the current scatterlist entry.
+ * @sg_miter: PIO mapping scatterlist iterator.
* @cur_slot: The slot which is currently using the controller.
* @mrq: The request currently being processed on @cur_slot,
* or NULL if the controller is idle.
@@ -115,7 +117,7 @@ struct dw_mci {
void __iomem *regs;
struct scatterlist *sg;
- unsigned int pio_offset;
+ struct sg_mapping_iter sg_miter;
struct dw_mci_slot *cur_slot;
struct mmc_request *mrq;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0beba1e5e1ed..ee2b0363c040 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -257,6 +257,7 @@ struct mmc_host {
#define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */
#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
MMC_CAP2_HS200_1_2V_SDR)
+#define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */
mmc_pm_flag_t pm_caps; /* supported pm features */
unsigned int power_notify_type;
@@ -444,4 +445,23 @@ static inline int mmc_boot_partition_access(struct mmc_host *host)
return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC);
}
+#ifdef CONFIG_MMC_CLKGATE
+void mmc_host_clk_hold(struct mmc_host *host);
+void mmc_host_clk_release(struct mmc_host *host);
+unsigned int mmc_host_clk_rate(struct mmc_host *host);
+
+#else
+static inline void mmc_host_clk_hold(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_release(struct mmc_host *host)
+{
+}
+
+static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+ return host->ios.clock;
+}
+#endif
#endif /* LINUX_MMC_HOST_H */
diff --git a/include/linux/mpi.h b/include/linux/mpi.h
index 06f88994ccaa..d02cca6cc8ce 100644
--- a/include/linux/mpi.h
+++ b/include/linux/mpi.h
@@ -57,8 +57,6 @@ struct gcry_mpi {
typedef struct gcry_mpi *MPI;
-#define MPI_NULL NULL
-
#define mpi_get_nlimbs(a) ((a)->nlimbs)
#define mpi_is_neg(a) ((a)->sign)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 221295208fd0..d43dc25af82e 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
static inline int mtd_suspend(struct mtd_info *mtd)
{
- if (!mtd->suspend)
- return -EOPNOTSUPP;
- return mtd->suspend(mtd);
+ return mtd->suspend ? mtd->suspend(mtd) : 0;
}
static inline void mtd_resume(struct mtd_info *mtd)
@@ -489,7 +487,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
{
- return 0;
+ return !!mtd->block_isbad;
}
/* Kernel-side ioctl definitions */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 08855613ceb3..abb2776be1ba 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -587,6 +587,7 @@ struct hw_perf_event {
u64 sample_period;
u64 last_period;
local64_t period_left;
+ u64 interrupts_seq;
u64 interrupts;
u64 freq_time_stamp;
diff --git a/include/linux/platform_data/omap-abe-twl6040.h b/include/linux/platform_data/omap-abe-twl6040.h
new file mode 100644
index 000000000000..5d298ac10fc2
--- /dev/null
+++ b/include/linux/platform_data/omap-abe-twl6040.h
@@ -0,0 +1,49 @@
+/**
+ * omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * All rights reserved.
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@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_ABE_TWL6040_H_
+#define _OMAP_ABE_TWL6040_H_
+
+/* To select if only one channel is connected in a stereo port */
+#define ABE_TWL6040_LEFT (1 << 0)
+#define ABE_TWL6040_RIGHT (1 << 1)
+
+struct omap_abe_twl6040_data {
+ char *card_name;
+ /* Feature flags for connected audio pins */
+ u8 has_hs;
+ u8 has_hf;
+ bool has_ep;
+ u8 has_aux;
+ u8 has_vibra;
+ bool has_dmic;
+ bool has_hsmic;
+ bool has_mainmic;
+ bool has_submic;
+ u8 has_afm;
+ /* Other features */
+ bool jack_detection; /* board can detect jack events */
+ int mclk_freq; /* MCLK frequency speed for twl6040 */
+};
+
+#endif /* _OMAP_ABE_TWL6040_H_ */
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index e5bbcbaa6f57..4d99e4e6ef83 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req)
{ return; }
static inline int pm_qos_request(int pm_qos_class)
- { return 0; }
+{
+ switch (pm_qos_class) {
+ case PM_QOS_CPU_DMA_LATENCY:
+ return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+ case PM_QOS_NETWORK_LATENCY:
+ return PM_QOS_NETWORK_LAT_DEFAULT_VALUE;
+ case PM_QOS_NETWORK_THROUGHPUT:
+ return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE;
+ default:
+ return PM_QOS_DEFAULT_VALUE;
+ }
+}
+
static inline int pm_qos_add_notifier(int pm_qos_class,
struct notifier_block *notifier)
{ return 0; }
diff --git a/include/linux/proportions.h b/include/linux/proportions.h
index ef35bb73f69b..26a8a4ed9b07 100644
--- a/include/linux/proportions.h
+++ b/include/linux/proportions.h
@@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
* Limit the time part in order to ensure there are some bits left for the
* cycle counter and fraction multiply.
*/
+#if BITS_PER_LONG == 32
#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+#else
+#define PROP_MAX_SHIFT (BITS_PER_LONG/2)
+#endif
#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index eb93921cdd30..c47898d47c8a 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -143,12 +143,16 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
int regmap_update_bits_check(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change);
+int regmap_get_val_bytes(struct regmap *map);
int regcache_sync(struct regmap *map);
void regcache_cache_only(struct regmap *map, bool enable);
void regcache_cache_bypass(struct regmap *map, bool enable);
void regcache_mark_dirty(struct regmap *map);
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+ int num_regs);
+
/**
* Description of an IRQ for the generic regmap irq_chip.
*
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index f2698a0edfc4..35c42834ba3d 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -132,9 +132,12 @@ struct regulator_bulk_data {
/* regulator get and put */
struct regulator *__must_check regulator_get(struct device *dev,
const char *id);
+struct regulator *__must_check devm_regulator_get(struct device *dev,
+ const char *id);
struct regulator *__must_check regulator_get_exclusive(struct device *dev,
const char *id);
void regulator_put(struct regulator *regulator);
+void devm_regulator_free(struct regulator *regulator);
/* regulator output control and status */
int regulator_enable(struct regulator *regulator);
@@ -145,6 +148,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms);
int regulator_bulk_get(struct device *dev, int num_consumers,
struct regulator_bulk_data *consumers);
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
int regulator_bulk_enable(int num_consumers,
struct regulator_bulk_data *consumers);
int regulator_bulk_disable(int num_consumers,
@@ -200,6 +205,13 @@ static inline struct regulator *__must_check regulator_get(struct device *dev,
*/
return NULL;
}
+
+static inline struct regulator *__must_check
+devm_regulator_get(struct device *dev, const char *id)
+{
+ return NULL;
+}
+
static inline void regulator_put(struct regulator *regulator)
{
}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2234985a5e65..7d379a6bfd88 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm)
extern void mmput(struct mm_struct *);
/* Grab a reference to a task's mm, if it is not already going away */
extern struct mm_struct *get_task_mm(struct task_struct *task);
+/*
+ * Grab a reference to a task's mm, if it is not already going away
+ * and ptrace_may_access with the mode parameter passed to it
+ * succeeds.
+ */
+extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);
/* Remove the current tasks stale references to the old mm_struct */
extern void mm_release(struct task_struct *, struct mm_struct *);
/* Allocate a new mm structure and copy contents from tsk->mm */
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 8cd7fe59cf1a..425450b980b8 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -70,6 +70,7 @@ struct sh_dmae_pdata {
unsigned int needs_tend_set:1;
unsigned int no_dmars:1;
unsigned int chclr_present:1;
+ unsigned int slave_only:1;
};
/* DMA register */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 61b29057b054..3b6f628880f8 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -589,7 +589,7 @@ static inline int usb_endpoint_is_isoc_out(
*/
static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
{
- return le16_to_cpu(epd->wMaxPacketSize);
+ return __le16_to_cpu(epd->wMaxPacketSize);
}
/*-------------------------------------------------------------------------*/
diff --git a/include/net/flow.h b/include/net/flow.h
index 9b582437fbea..6c469dbdb917 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -93,6 +93,16 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
}
+
+/* Reset some input parameters after previous lookup */
+static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
+ __be32 daddr, __be32 saddr)
+{
+ fl4->flowi4_oif = oif;
+ fl4->flowi4_tos = tos;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+}
struct flowi6 {
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
index 7b2d43139c8e..d58fdec47597 100644
--- a/include/net/netprio_cgroup.h
+++ b/include/net/netprio_cgroup.h
@@ -37,19 +37,51 @@ extern int net_prio_subsys_id;
extern void sock_update_netprioidx(struct sock *sk);
-static inline struct cgroup_netprio_state
- *task_netprio_state(struct task_struct *p)
+#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
{
-#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
- return container_of(task_subsys_state(p, net_prio_subsys_id),
- struct cgroup_netprio_state, css);
-#else
- return NULL;
-#endif
+ struct cgroup_netprio_state *state;
+ u32 idx;
+
+ rcu_read_lock();
+ state = container_of(task_subsys_state(p, net_prio_subsys_id),
+ struct cgroup_netprio_state, css);
+ idx = state->prioidx;
+ rcu_read_unlock();
+ return idx;
+}
+
+#elif IS_MODULE(CONFIG_NETPRIO_CGROUP)
+
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+ struct cgroup_netprio_state *state;
+ int subsys_id;
+ u32 idx = 0;
+
+ rcu_read_lock();
+ subsys_id = rcu_dereference_index_check(net_prio_subsys_id,
+ rcu_read_lock_held());
+ if (subsys_id >= 0) {
+ state = container_of(task_subsys_state(p, subsys_id),
+ struct cgroup_netprio_state, css);
+ idx = state->prioidx;
+ }
+ rcu_read_unlock();
+ return idx;
}
#else
+static inline u32 task_netprioidx(struct task_struct *p)
+{
+ return 0;
+}
+
+#endif /* CONFIG_NETPRIO_CGROUP */
+
+#else
#define sock_update_netprioidx(sk)
#endif
diff --git a/include/net/route.h b/include/net/route.h
index 91855d185b53..b1c0d5b564c2 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -270,6 +270,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
if (IS_ERR(rt))
return rt;
ip_rt_put(rt);
+ flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
}
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(net, fl4, sk);
@@ -284,6 +285,9 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
ip_rt_put(rt);
+ flowi4_update_output(fl4, sk->sk_bound_dev_if,
+ RT_CONN_FLAGS(sk), fl4->daddr,
+ fl4->saddr);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(sock_net(sk), fl4, sk);
}
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f6bb08b73ca4..55ce96b53b09 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -220,9 +220,16 @@ struct tcf_proto {
struct qdisc_skb_cb {
unsigned int pkt_len;
- long data[];
+ unsigned char data[24];
};
+static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
+{
+ struct qdisc_skb_cb *qcb;
+ BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz);
+ BUILD_BUG_ON(sizeof(qcb->data) < sz);
+}
+
static inline int qdisc_qlen(const struct Qdisc *q)
{
return q->q.qlen;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d49db0113a06..42c29bfbcee3 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -273,6 +273,14 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
return seq3 - seq2 >= seq1 - seq2;
}
+static inline bool tcp_out_of_memory(struct sock *sk)
+{
+ if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+ sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
+ return true;
+ return false;
+}
+
static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
{
struct percpu_counter *ocp = sk->sk_prot->orphan_count;
@@ -283,13 +291,11 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
if (orphans << shift > sysctl_tcp_max_orphans)
return true;
}
-
- if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
- sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
- return true;
return false;
}
+extern bool tcp_check_oom(struct sock *sk, int shift);
+
/* syncookies: remember time of last synqueue overflow */
static inline void tcp_synq_overflow(struct sock *sk)
{
diff --git a/include/sound/control.h b/include/sound/control.h
index b2796e83c7ac..8332e865c759 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -40,7 +40,7 @@ struct snd_kcontrol_new {
snd_ctl_elem_iface_t iface; /* interface identifier */
unsigned int device; /* device/client number */
unsigned int subdevice; /* subdevice (substream) number */
- unsigned char *name; /* ASCII name of item */
+ const unsigned char *name; /* ASCII name of item */
unsigned int index; /* index of item */
unsigned int access; /* access rights */
unsigned int count; /* count of same elements */
@@ -227,6 +227,11 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
}
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
+ void (*hook)(void *private_data, int),
+ void *private_data);
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl);
+
/*
* Helper functions for jack-detection controls
*/
diff --git a/include/sound/core.h b/include/sound/core.h
index 5ab255f196cc..cea1b5426dfa 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond)
#define gameport_get_port_data(gp) (gp)->port_data
#endif
+#ifdef CONFIG_PCI
/* PCI quirk list helper */
struct snd_pci_quirk {
unsigned short subvendor; /* PCI subvendor ID */
@@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
const struct snd_pci_quirk *
snd_pci_quirk_lookup_id(u16 vendor, u16 device,
const struct snd_pci_quirk *list);
+#endif
#endif /* __SOUND_CORE_H */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
new file mode 100644
index 000000000000..a8fcaa6d531f
--- /dev/null
+++ b/include/sound/dmaengine_pcm.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012, Analog Devices Inc.
+ * Author: 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 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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 __SOUND_DMAENGINE_PCM_H__
+#define __SOUND_DMAENGINE_PCM_H__
+
+#include <sound/pcm.h>
+#include <linux/dmaengine.h>
+
+/**
+ * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM
+ * substream
+ * @substream: PCM substream
+ */
+static inline enum dma_transfer_direction
+snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return DMA_MEM_TO_DEV;
+ else
+ return DMA_DEV_TO_MEM;
+}
+
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data);
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream);
+
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+ const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream);
+
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+ dma_filter_fn filter_fn, void *filter_data);
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
+
+#endif
diff --git a/include/sound/max9768.h b/include/sound/max9768.h
new file mode 100644
index 000000000000..0f78b41d030e
--- /dev/null
+++ b/include/sound/max9768.h
@@ -0,0 +1,24 @@
+/*
+ * Platform data for MAX9768
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ * same licence as the driver
+ */
+
+#ifndef __SOUND_MAX9768_PDATA_H__
+#define __SOUND_MAX9768_PDATA_H__
+
+/**
+ * struct max9768_pdata - optional platform specific MAX9768 configuration
+ * @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH
+ * @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added
+ * @flags: configuration flags, e.g. set classic PWM mode (check datasheet
+ * regarding "filterless modulation" which is default).
+ */
+struct max9768_pdata {
+ int shdn_gpio;
+ int mute_gpio;
+ unsigned flags;
+#define MAX9768_FLAG_CLASSIC_PWM (1 << 0)
+};
+
+#endif /* __SOUND_MAX9768_PDATA_H__*/
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 0cf91b2f08ca..0d1112815be3 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -264,7 +264,7 @@ struct snd_pcm_hw_constraint_ratdens {
struct snd_pcm_hw_constraint_list {
unsigned int count;
- unsigned int *list;
+ const unsigned int *list;
unsigned int mask;
};
@@ -454,6 +454,7 @@ struct snd_pcm {
void *private_data;
void (*private_free) (struct snd_pcm *pcm);
struct device *dev; /* actual hw device this belongs to */
+ bool internal; /* pcm is for internal use only */
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
struct snd_pcm_oss oss;
#endif
@@ -475,6 +476,9 @@ extern const struct file_operations snd_pcm_f_ops[2];
int snd_pcm_new(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count,
struct snd_pcm **rpcm);
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count,
+ struct snd_pcm **rpcm);
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
@@ -781,7 +785,8 @@ void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interva
unsigned int k, struct snd_interval *c);
void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
const struct snd_interval *b, struct snd_interval *c);
-int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask);
+int snd_interval_list(struct snd_interval *i, unsigned int count,
+ const unsigned int *list, unsigned int mask);
int snd_interval_ratnum(struct snd_interval *i,
unsigned int rats_count, struct snd_ratnum *rats,
unsigned int *nump, unsigned int *denp);
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 9b1aacaa82fe..b457e87fbd08 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -72,10 +72,16 @@
#define SH_FSI_BPFMD_32 (5 << 4)
#define SH_FSI_BPFMD_16 (6 << 4)
+struct sh_fsi_port_info {
+ unsigned long flags;
+ int tx_id;
+ int rx_id;
+ int (*set_rate)(struct device *dev, int rate, int enable);
+};
+
struct sh_fsi_platform_info {
- unsigned long porta_flags;
- unsigned long portb_flags;
- int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
+ struct sh_fsi_port_info port_a;
+ struct sh_fsi_port_info port_b;
};
/*
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 2413acc54883..c429f248cf4e 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -17,6 +17,7 @@
#include <linux/list.h>
struct snd_pcm_substream;
+struct snd_soc_dapm_widget;
/*
* DAI hardware audio formats.
@@ -238,6 +239,9 @@ struct snd_soc_dai {
unsigned char pop_wait:1;
unsigned char probed:1;
+ struct snd_soc_dapm_widget *playback_widget;
+ struct snd_soc_dapm_widget *capture_widget;
+
/* DAI DMA data */
void *playback_dma_data;
void *capture_dma_data;
@@ -246,10 +250,9 @@ struct snd_soc_dai {
unsigned int rate;
/* parent platform/codec */
- union {
- struct snd_soc_platform *platform;
- struct snd_soc_codec *codec;
- };
+ struct snd_soc_platform *platform;
+ struct snd_soc_codec *codec;
+
struct snd_soc_card *card;
struct list_head list;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index d26a9b784772..e46107fffeb4 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -243,6 +243,10 @@
{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \
.shift = wshift, .invert = winvert, .event = wevent, \
.event_flags = wflags}
+#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \
+{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
+ .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
+ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
/* dapm kcontrol types */
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
@@ -322,6 +326,8 @@ struct snd_soc_dapm_context;
int dapm_reg_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
/* dapm controls */
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -346,11 +352,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uncontrol);
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uncontrol);
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget);
int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget,
int num);
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai);
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
@@ -361,10 +368,16 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num);
/* dapm events */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event);
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ struct snd_soc_dai *dai, int event);
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
+/* external DAPM widget events */
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int connect);
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
+
/* dapm sys fs - used by the core */
int snd_soc_dapm_sys_add(struct device *dev);
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
@@ -411,9 +424,11 @@ enum snd_soc_dapm_type {
snd_soc_dapm_pre, /* machine specific pre widget - exec first */
snd_soc_dapm_post, /* machine specific post widget - exec last */
snd_soc_dapm_supply, /* power/clock supply */
+ snd_soc_dapm_regulator_supply, /* external regulator */
snd_soc_dapm_aif_in, /* audio interface input */
snd_soc_dapm_aif_out, /* audio interface output */
snd_soc_dapm_siggen, /* signal generator */
+ snd_soc_dapm_dai, /* link to DAI structure */
};
/*
@@ -434,8 +449,8 @@ struct snd_soc_dapm_route {
/* dapm audio path between two widgets */
struct snd_soc_dapm_path {
- char *name;
- char *long_name;
+ const char *name;
+ const char *long_name;
/* source (input) and sink (output) widgets */
struct snd_soc_dapm_widget *source;
@@ -458,13 +473,15 @@ struct snd_soc_dapm_path {
/* dapm widget */
struct snd_soc_dapm_widget {
enum snd_soc_dapm_type id;
- char *name; /* widget name */
- char *sname; /* stream name */
+ const char *name; /* widget name */
+ const char *sname; /* stream name */
struct snd_soc_codec *codec;
struct snd_soc_platform *platform;
struct list_head list;
struct snd_soc_dapm_context *dapm;
+ void *priv; /* widget specific data */
+
/* dapm control */
short reg; /* negative reg = no direct dapm */
unsigned char shift; /* bits to shift */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0992dff55959..2ebf7877c148 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -185,6 +185,20 @@
.rreg = xreg_right, .shift = xshift, \
.min = xmin, .max = xmax} }
+#define SND_SOC_BYTES(xname, xbase, xregs) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+ .put = snd_soc_bytes_put, .private_value = \
+ ((unsigned long)&(struct soc_bytes) \
+ {.base = xbase, .num_regs = xregs }) }
+
+#define SND_SOC_BYTES_MASK(xname, xbase, xregs, xmask) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+ .put = snd_soc_bytes_put, .private_value = \
+ ((unsigned long)&(struct soc_bytes) \
+ {.base = xbase, .num_regs = xregs, \
+ .mask = xmask }) }
/*
* Simplified versions of above macros, declaring a struct and calculating
@@ -366,12 +380,16 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
*Controls
*/
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
- void *data, char *long_name,
+ void *data, const char *long_name,
const char *prefix);
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+ const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+ const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -409,6 +427,13 @@ int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
/**
* struct snd_soc_reg_access - Describes whether a given register is
@@ -505,6 +530,7 @@ struct snd_soc_pcm_stream {
unsigned int rate_max; /* max rate */
unsigned int channels_min; /* min channels */
unsigned int channels_max; /* max channels */
+ unsigned int sig_bits; /* number of bits of content */
};
/* SoC audio ops */
@@ -559,6 +585,7 @@ struct snd_soc_codec {
unsigned int ac97_created:1; /* Codec has been created by SoC */
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
unsigned int cache_init:1; /* codec cache has been initialized */
+ unsigned int using_regmap:1; /* using regmap access */
u32 cache_only; /* Suppress writes to hardware */
u32 cache_sync; /* Cache needs to be synced to hardware */
@@ -637,6 +664,8 @@ struct snd_soc_codec_driver {
/* codec stream completion event */
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+ bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
+
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
@@ -689,6 +718,7 @@ struct snd_soc_platform {
int id;
struct device *dev;
struct snd_soc_platform_driver *driver;
+ struct mutex mutex;
unsigned int suspended:1; /* platform is suspended */
unsigned int probed:1;
@@ -698,6 +728,11 @@ struct snd_soc_platform {
struct list_head card_list;
struct snd_soc_dapm_context dapm;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_platform_root;
+ struct dentry *debugfs_dapm;
+#endif
};
struct snd_soc_dai_link {
@@ -875,6 +910,12 @@ struct soc_mixer_control {
unsigned int reg, rreg, shift, rshift, invert;
};
+struct soc_bytes {
+ int base;
+ int num_regs;
+ u32 mask;
+};
+
/* enumerated kcontrol */
struct soc_enum {
unsigned short reg;
diff --git a/include/sound/version.h b/include/sound/version.h
index 8fc5321e1ecc..cc75024c1089 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h */
-#define CONFIG_SND_VERSION "1.0.24"
+#define CONFIG_SND_VERSION "1.0.25"
#define CONFIG_SND_DATE ""
diff --git a/include/sound/wm2200.h b/include/sound/wm2200.h
new file mode 100644
index 000000000000..79bf55be7ffa
--- /dev/null
+++ b/include/sound/wm2200.h
@@ -0,0 +1,41 @@
+/*
+ * linux/sound/wm2200.h -- Platform data for WM2200
+ *
+ * Copyright 2012 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_WM2200_H
+#define __LINUX_SND_WM2200_H
+
+#define WM2200_GPIO_SET 0x10000
+
+enum wm2200_in_mode {
+ WM2200_IN_SE = 0,
+ WM2200_IN_DIFF = 1,
+ WM2200_IN_DMIC = 2,
+};
+
+enum wm2200_dmic_sup {
+ WM2200_DMIC_SUP_MICVDD = 0,
+ WM2200_DMIC_SUP_MICBIAS1 = 1,
+ WM2200_DMIC_SUP_MICBIAS2 = 2,
+};
+
+struct wm2200_pdata {
+ int reset; /** GPIO controlling /RESET, if any */
+ int ldo_ena; /** GPIO controlling LODENA, if any */
+ int irq_flags;
+
+ int gpio_defaults[4];
+
+ enum wm2200_in_mode in_mode[3];
+ enum wm2200_dmic_sup dmic_sup[3];
+
+ int micbias_cfg[2]; /** Register value to configure MICBIAS */
+};
+
+#endif
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
index 1750bed7c2f6..79e6d427b858 100644
--- a/include/sound/wm8962.h
+++ b/include/sound/wm8962.h
@@ -49,6 +49,12 @@ struct wm8962_pdata {
bool irq_active_low;
bool spk_mono; /* Speaker outputs tied together as mono */
+
+ /**
+ * This flag should be set if one or both IN4 inputs is wired
+ * in a DC measurement configuration.
+ */
+ bool in4_dc_measure;
};
#endif
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 444cd6ba0ba7..41199664666b 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -366,6 +366,8 @@ struct snd_ymfpci {
#ifdef CONFIG_PM
u32 *saved_regs;
u32 saved_ydsxgr_mode;
+ u16 saved_dsxg_legacy;
+ u16 saved_dsxg_elegacy;
#endif
};
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 4866499bdeeb..e5e6ff98f0fa 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -59,7 +59,7 @@ int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
int transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
/* core helpers also used by command snooping in pscsi */
-void *transport_kmap_first_data_page(struct se_cmd *);
-void transport_kunmap_first_data_page(struct se_cmd *);
+void *transport_kmap_data_sg(struct se_cmd *);
+void transport_kunmap_data_sg(struct se_cmd *);
#endif /* TARGET_CORE_BACKEND_H */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index daf532bc721a..dc4e345a0163 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -582,6 +582,7 @@ struct se_cmd {
struct scatterlist *t_data_sg;
unsigned int t_data_nents;
+ void *t_data_vmap;
struct scatterlist *t_bidi_data_sg;
unsigned int t_bidi_data_nents;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 523e8bc104d4..d36fad317e78 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -114,7 +114,7 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
struct se_session *, u32, int, int, unsigned char *);
int transport_lookup_cmd_lun(struct se_cmd *, u32);
int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
-int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
+void target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
unsigned char *, u32, u32, int, int, int);
int transport_handle_cdb_direct(struct se_cmd *);
int transport_generic_handle_cdb_map(struct se_cmd *);
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 8588a8918023..5973410e8f8c 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -47,7 +47,10 @@ DECLARE_EVENT_CLASS(writeback_work_class,
__field(int, reason)
),
TP_fast_assign(
- strncpy(__entry->name, dev_name(bdi->dev), 32);
+ struct device *dev = bdi->dev;
+ if (!dev)
+ dev = default_backing_dev_info.dev;
+ strncpy(__entry->name, dev_name(dev), 32);
__entry->nr_pages = work->nr_pages;
__entry->sb_dev = work->sb ? work->sb->s_dev : 0;
__entry->sync_mode = work->sync_mode;
@@ -426,7 +429,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
TP_fast_assign(
strncpy(__entry->name,
- dev_name(inode->i_mapping->backing_dev_info->dev), 32);
+ dev_name(inode_to_bdi(inode)->dev), 32);
__entry->ino = inode->i_ino;
__entry->state = inode->i_state;
__entry->dirtied_when = inode->dirtied_when;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 062b3b24ff10..483f67caa7ad 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -590,6 +590,11 @@ struct omap_dss_device {
int (*get_backlight)(struct omap_dss_device *dssdev);
};
+struct omap_dss_hdmi_data
+{
+ int hpd_gpio;
+};
+
struct omap_dss_driver {
struct device_driver driver;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 32b48c889711..1b5c081d8b9f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2300,7 +2300,10 @@ do { \
return div64_u64(dividend, divisor);
}
-static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
+static DEFINE_PER_CPU(int, perf_throttled_count);
+static DEFINE_PER_CPU(u64, perf_throttled_seq);
+
+static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bool disable)
{
struct hw_perf_event *hwc = &event->hw;
s64 period, sample_period;
@@ -2319,22 +2322,40 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
hwc->sample_period = sample_period;
if (local64_read(&hwc->period_left) > 8*sample_period) {
- event->pmu->stop(event, PERF_EF_UPDATE);
+ if (disable)
+ event->pmu->stop(event, PERF_EF_UPDATE);
+
local64_set(&hwc->period_left, 0);
- event->pmu->start(event, PERF_EF_RELOAD);
+
+ if (disable)
+ event->pmu->start(event, PERF_EF_RELOAD);
}
}
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
+/*
+ * combine freq adjustment with unthrottling to avoid two passes over the
+ * events. At the same time, make sure, having freq events does not change
+ * the rate of unthrottling as that would introduce bias.
+ */
+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
+ int needs_unthr)
{
struct perf_event *event;
struct hw_perf_event *hwc;
- u64 interrupts, now;
+ u64 now, period = TICK_NSEC;
s64 delta;
- if (!ctx->nr_freq)
+ /*
+ * only need to iterate over all events iff:
+ * - context have events in frequency mode (needs freq adjust)
+ * - there are events to unthrottle on this cpu
+ */
+ if (!(ctx->nr_freq || needs_unthr))
return;
+ raw_spin_lock(&ctx->lock);
+ perf_pmu_disable(ctx->pmu);
+
list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
if (event->state != PERF_EVENT_STATE_ACTIVE)
continue;
@@ -2344,13 +2365,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
hwc = &event->hw;
- interrupts = hwc->interrupts;
- hwc->interrupts = 0;
-
- /*
- * unthrottle events on the tick
- */
- if (interrupts == MAX_INTERRUPTS) {
+ if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) {
+ hwc->interrupts = 0;
perf_log_throttle(event, 1);
event->pmu->start(event, 0);
}
@@ -2358,14 +2374,30 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
if (!event->attr.freq || !event->attr.sample_freq)
continue;
- event->pmu->read(event);
+ /*
+ * stop the event and update event->count
+ */
+ event->pmu->stop(event, PERF_EF_UPDATE);
+
now = local64_read(&event->count);
delta = now - hwc->freq_count_stamp;
hwc->freq_count_stamp = now;
+ /*
+ * restart the event
+ * reload only if value has changed
+ * we have stopped the event so tell that
+ * to perf_adjust_period() to avoid stopping it
+ * twice.
+ */
if (delta > 0)
- perf_adjust_period(event, period, delta);
+ perf_adjust_period(event, period, delta, false);
+
+ event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
}
+
+ perf_pmu_enable(ctx->pmu);
+ raw_spin_unlock(&ctx->lock);
}
/*
@@ -2388,16 +2420,13 @@ static void rotate_ctx(struct perf_event_context *ctx)
*/
static void perf_rotate_context(struct perf_cpu_context *cpuctx)
{
- u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
struct perf_event_context *ctx = NULL;
- int rotate = 0, remove = 1, freq = 0;
+ int rotate = 0, remove = 1;
if (cpuctx->ctx.nr_events) {
remove = 0;
if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
rotate = 1;
- if (cpuctx->ctx.nr_freq)
- freq = 1;
}
ctx = cpuctx->task_ctx;
@@ -2405,37 +2434,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
remove = 0;
if (ctx->nr_events != ctx->nr_active)
rotate = 1;
- if (ctx->nr_freq)
- freq = 1;
}
- if (!rotate && !freq)
+ if (!rotate)
goto done;
perf_ctx_lock(cpuctx, cpuctx->task_ctx);
perf_pmu_disable(cpuctx->ctx.pmu);
- if (freq) {
- perf_ctx_adjust_freq(&cpuctx->ctx, interval);
- if (ctx)
- perf_ctx_adjust_freq(ctx, interval);
- }
-
- if (rotate) {
- cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
- if (ctx)
- ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
+ if (ctx)
+ ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
- rotate_ctx(&cpuctx->ctx);
- if (ctx)
- rotate_ctx(ctx);
+ rotate_ctx(&cpuctx->ctx);
+ if (ctx)
+ rotate_ctx(ctx);
- perf_event_sched_in(cpuctx, ctx, current);
- }
+ perf_event_sched_in(cpuctx, ctx, current);
perf_pmu_enable(cpuctx->ctx.pmu);
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-
done:
if (remove)
list_del_init(&cpuctx->rotation_list);
@@ -2445,10 +2463,22 @@ void perf_event_task_tick(void)
{
struct list_head *head = &__get_cpu_var(rotation_list);
struct perf_cpu_context *cpuctx, *tmp;
+ struct perf_event_context *ctx;
+ int throttled;
WARN_ON(!irqs_disabled());
+ __this_cpu_inc(perf_throttled_seq);
+ throttled = __this_cpu_xchg(perf_throttled_count, 0);
+
list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+ ctx = &cpuctx->ctx;
+ perf_adjust_freq_unthr_context(ctx, throttled);
+
+ ctx = cpuctx->task_ctx;
+ if (ctx)
+ perf_adjust_freq_unthr_context(ctx, throttled);
+
if (cpuctx->jiffies_interval == 1 ||
!(jiffies % cpuctx->jiffies_interval))
perf_rotate_context(cpuctx);
@@ -4509,6 +4539,7 @@ static int __perf_event_overflow(struct perf_event *event,
{
int events = atomic_read(&event->event_limit);
struct hw_perf_event *hwc = &event->hw;
+ u64 seq;
int ret = 0;
/*
@@ -4518,14 +4549,20 @@ static int __perf_event_overflow(struct perf_event *event,
if (unlikely(!is_sampling_event(event)))
return 0;
- if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
- if (throttle) {
+ seq = __this_cpu_read(perf_throttled_seq);
+ if (seq != hwc->interrupts_seq) {
+ hwc->interrupts_seq = seq;
+ hwc->interrupts = 1;
+ } else {
+ hwc->interrupts++;
+ if (unlikely(throttle
+ && hwc->interrupts >= max_samples_per_tick)) {
+ __this_cpu_inc(perf_throttled_count);
hwc->interrupts = MAX_INTERRUPTS;
perf_log_throttle(event, 0);
ret = 1;
}
- } else
- hwc->interrupts++;
+ }
if (event->attr.freq) {
u64 now = perf_clock();
@@ -4534,7 +4571,7 @@ static int __perf_event_overflow(struct perf_event *event,
hwc->freq_time_stamp = now;
if (delta > 0 && delta < 2*TICK_NSEC)
- perf_adjust_period(event, delta, hwc->last_period);
+ perf_adjust_period(event, delta, hwc->last_period, true);
}
/*
diff --git a/kernel/exit.c b/kernel/exit.c
index 294b1709170d..4b4042f9bc6a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1038,6 +1038,22 @@ void do_exit(long code)
if (tsk->nr_dirtied)
__this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
exit_rcu();
+
+ /*
+ * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+ * when the following two conditions become true.
+ * - There is race condition of mmap_sem (It is acquired by
+ * exit_mm()), and
+ * - SMI occurs before setting TASK_RUNINNG.
+ * (or hypervisor of virtual machine switches to other guest)
+ * As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+ *
+ * To avoid it, we have to wait for releasing tsk->pi_lock which
+ * is held by try_to_wake_up()
+ */
+ smp_mb();
+ raw_spin_unlock_wait(&tsk->pi_lock);
+
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
tsk->flags |= PF_NOFREEZE; /* tell freezer to ignore us */
diff --git a/kernel/fork.c b/kernel/fork.c
index 051f090d40c1..b77fd559c78e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)
}
EXPORT_SYMBOL_GPL(get_task_mm);
+struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
+{
+ struct mm_struct *mm;
+ int err;
+
+ err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+ if (err)
+ return ERR_PTR(err);
+
+ mm = get_task_mm(task);
+ if (mm && mm != current->mm &&
+ !ptrace_may_access(task, mode)) {
+ mmput(mm);
+ mm = ERR_PTR(-EACCES);
+ }
+ mutex_unlock(&task->signal->cred_guard_mutex);
+
+ return mm;
+}
+
/* Please note the differences between mmput and mm_release.
* mmput is called whenever we stop holding onto a mm_struct,
* error success whatever.
@@ -890,7 +910,7 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
return -ENOMEM;
new_ioc->ioprio = ioc->ioprio;
- put_io_context(new_ioc, NULL);
+ put_io_context(new_ioc);
}
#endif
return 0;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 29f5b65bee29..9788c0ec6f43 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
ri->rp = rp;
ri->task = current;
- if (rp->entry_handler && rp->entry_handler(ri, regs))
+ if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+ raw_spin_lock_irqsave(&rp->lock, flags);
+ hlist_add_head(&ri->hlist, &rp->free_instances);
+ raw_spin_unlock_irqrestore(&rp->lock, flags);
return 0;
+ }
arch_prepare_kretprobe(ri, regs);
diff --git a/kernel/params.c b/kernel/params.c
index 32ee04308285..4bc965d8a1fe 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -97,7 +97,8 @@ static int parse_one(char *param,
for (i = 0; i < num_params; i++) {
if (parameq(param, params[i].name)) {
/* No one handled NULL, so do it here. */
- if (!val && params[i].ops->set != param_set_bool)
+ if (!val && params[i].ops->set != param_set_bool
+ && params[i].ops->set != param_set_bint)
return -EINVAL;
pr_debug("They are equal! Calling %p\n",
params[i].ops->set);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 0c4defe6d3b8..21724eee5206 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -231,8 +231,28 @@ extern int pm_test_level;
#ifdef CONFIG_SUSPEND_FREEZER
static inline int suspend_freeze_processes(void)
{
- int error = freeze_processes();
- return error ? : freeze_kernel_threads();
+ int error;
+
+ error = freeze_processes();
+
+ /*
+ * freeze_processes() automatically thaws every task if freezing
+ * fails. So we need not do anything extra upon error.
+ */
+ if (error)
+ goto Finish;
+
+ error = freeze_kernel_threads();
+
+ /*
+ * freeze_kernel_threads() thaws only kernel threads upon freezing
+ * failure. So we have to thaw the userspace tasks ourselves.
+ */
+ if (error)
+ thaw_processes();
+
+ Finish:
+ return error;
}
static inline void suspend_thaw_processes(void)
diff --git a/kernel/power/process.c b/kernel/power/process.c
index eeca00311f39..7e426459e60a 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -143,7 +143,10 @@ int freeze_processes(void)
/**
* freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
*
- * On success, returns 0. On failure, -errno and system is fully thawed.
+ * On success, returns 0. On failure, -errno and only the kernel threads are
+ * thawed, so as to give a chance to the caller to do additional cleanups
+ * (if any) before thawing the userspace tasks. So, it is the responsibility
+ * of the caller to thaw the userspace tasks, when the time is right.
*/
int freeze_kernel_threads(void)
{
@@ -159,7 +162,7 @@ int freeze_kernel_threads(void)
BUG_ON(in_atomic());
if (error)
- thaw_processes();
+ thaw_kernel_threads();
return error;
}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index e5a21a857302..3e100075b13c 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
}
pm_restore_gfp_mask();
error = hibernation_snapshot(data->platform_support);
- if (!error) {
+ if (error) {
+ thaw_kernel_threads();
+ } else {
error = put_user(in_suspend, (int __user *)arg);
if (!error && !freezer_test_done)
data->ready = 1;
if (freezer_test_done) {
freezer_test_done = false;
- thaw_processes();
+ thaw_kernel_threads();
}
}
break;
diff --git a/kernel/relay.c b/kernel/relay.c
index 4335e1d7ee2d..ab56a1764d4d 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -164,10 +164,14 @@ depopulate:
*/
static struct rchan_buf *relay_create_buf(struct rchan *chan)
{
- struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
- if (!buf)
+ struct rchan_buf *buf;
+
+ if (chan->n_subbufs > UINT_MAX / sizeof(size_t *))
return NULL;
+ buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
+ if (!buf)
+ return NULL;
buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
if (!buf->padding)
goto free_buf;
@@ -574,6 +578,8 @@ struct rchan *relay_open(const char *base_filename,
if (!(subbuf_size && n_subbufs))
return NULL;
+ if (subbuf_size > UINT_MAX / n_subbufs)
+ return NULL;
chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
if (!chan)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index df00cb09263e..5255c9d2e053 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -74,6 +74,7 @@
#include <asm/tlb.h>
#include <asm/irq_regs.h>
+#include <asm/mutex.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
@@ -723,9 +724,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
p->sched_class->dequeue_task(rq, p, flags);
}
-/*
- * activate_task - move a task to the runqueue.
- */
void activate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
@@ -734,9 +732,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags)
enqueue_task(rq, p, flags);
}
-/*
- * deactivate_task - remove a task from the runqueue.
- */
void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
@@ -4134,7 +4129,7 @@ recheck:
on_rq = p->on_rq;
running = task_current(rq, p);
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
if (running)
p->sched_class->put_prev_task(rq, p);
@@ -4147,7 +4142,7 @@ recheck:
if (running)
p->sched_class->set_curr_task(rq);
if (on_rq)
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
check_class_changed(rq, p, prev_class, oldprio);
task_rq_unlock(rq, p, &flags);
@@ -4998,9 +4993,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
* placed properly.
*/
if (p->on_rq) {
- deactivate_task(rq_src, p, 0);
+ dequeue_task(rq_src, p, 0);
set_task_cpu(p, dest_cpu);
- activate_task(rq_dest, p, 0);
+ enqueue_task(rq_dest, p, 0);
check_preempt_curr(rq_dest, p, 0);
}
done:
@@ -7032,10 +7027,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p)
on_rq = p->on_rq;
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
__setscheduler(rq, p, SCHED_NORMAL, 0);
if (on_rq) {
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
resched_task(rq->curr);
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 84adb2d66cbd..7c6414fc669d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)
return;
}
+static inline void clear_nohz_tick_stopped(int cpu)
+{
+ if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
+ cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+ atomic_dec(&nohz.nr_cpus);
+ clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
+ }
+}
+
static inline void set_cpu_sd_state_busy(void)
{
struct sched_domain *sd;
@@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)
{
int cpu = smp_processor_id();
+ /*
+ * If this cpu is going down, then nothing needs to be done.
+ */
+ if (!cpu_active(cpu))
+ return;
+
if (stop_tick) {
if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
return;
@@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)
}
return;
}
+
+static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_DYING:
+ clear_nohz_tick_stopped(smp_processor_id());
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+}
#endif
static DEFINE_SPINLOCK(balancing);
@@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
* busy tick after returning from idle, we will update the busy stats.
*/
set_cpu_sd_state_busy();
- if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
- clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
- cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
- atomic_dec(&nohz.nr_cpus);
- }
+ clear_nohz_tick_stopped(cpu);
/*
* None are in tickless mode and hence no need for NOHZ idle load
@@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)
#ifdef CONFIG_NO_HZ
zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
+ cpu_notifier(sched_ilb_notifier, 0);
#endif
#endif /* SMP */
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 3640ebbb466b..f42ae7fb5ec5 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq)
if (!next_task)
return 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ if (unlikely(task_running(rq, next_task)))
+ return 0;
+#endif
+
retry:
if (unlikely(next_task == rq->curr)) {
WARN_ON(1);
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 1d7bca7f4f52..d117262deba3 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
if (__this_cpu_read(soft_watchdog_warn) == true)
return HRTIMER_RESTART;
- printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+ printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
smp_processor_id(), duration,
current->comm, task_pid_nr(current));
print_modules();
diff --git a/lib/Kconfig b/lib/Kconfig
index 169eb7c598e5..028aba9e72af 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -19,6 +19,9 @@ config RATIONAL
config GENERIC_FIND_FIRST_BIT
bool
+config NO_GENERIC_PCI_IOPORT_MAP
+ bool
+
config GENERIC_PCI_IOMAP
bool
@@ -279,6 +282,9 @@ config AVERAGE
If unsure, say N.
+config CLZ_TAB
+ bool
+
config CORDIC
tristate "CORDIC algorithm"
help
@@ -287,6 +293,7 @@ config CORDIC
config MPILIB
tristate
+ select CLZ_TAB
help
Multiprecision maths library from GnuPG.
It is used to implement RSA digital signature verification,
diff --git a/lib/Makefile b/lib/Makefile
index d71aae1b01b3..18515f0267c4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_SIGNATURE) += digsig.o
+obj-$(CONFIG_CLZ_TAB) += clz_tab.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/bug.c b/lib/bug.c
index 19552096d16b..a28c1415357c 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
return BUG_TRAP_TYPE_WARN;
}
- printk(KERN_EMERG "------------[ cut here ]------------\n");
+ printk(KERN_DEFAULT "------------[ cut here ]------------\n");
if (file)
printk(KERN_CRIT "kernel BUG at %s:%u!\n",
diff --git a/lib/clz_tab.c b/lib/clz_tab.c
new file mode 100644
index 000000000000..7287b4a991a7
--- /dev/null
+++ b/lib/clz_tab.c
@@ -0,0 +1,18 @@
+const unsigned char __clz_tab[] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+};
diff --git a/lib/digsig.c b/lib/digsig.c
index fd2402f67f89..286d558033e2 100644
--- a/lib/digsig.c
+++ b/lib/digsig.c
@@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
unsigned long msglen,
unsigned long modulus_bitlen,
unsigned char *out,
- unsigned long *outlen,
- int *is_valid)
+ unsigned long *outlen)
{
unsigned long modulus_len, ps_len, i;
- int result;
-
- /* default to invalid packet */
- *is_valid = 0;
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
@@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
return -EINVAL;
/* separate encoded message */
- if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
- result = -EINVAL;
- goto bail;
- }
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
+ return -EINVAL;
for (i = 2; i < modulus_len - 1; i++)
if (msg[i] != 0xFF)
break;
/* separator check */
- if (msg[i] != 0) {
+ if (msg[i] != 0)
/* There was no octet with hexadecimal value 0x00
to separate ps from m. */
- result = -EINVAL;
- goto bail;
- }
+ return -EINVAL;
ps_len = i - 2;
if (*outlen < (msglen - (2 + ps_len + 1))) {
*outlen = msglen - (2 + ps_len + 1);
- result = -EOVERFLOW;
- goto bail;
+ return -EOVERFLOW;
}
*outlen = (msglen - (2 + ps_len + 1));
memcpy(out, &msg[2 + ps_len + 1], *outlen);
- /* valid packet */
- *is_valid = 1;
- result = 0;
-bail:
- return result;
+ return 0;
}
/*
@@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key,
unsigned long len;
unsigned long mlen, mblen;
unsigned nret, l;
- int valid, head, i;
+ int head, i;
unsigned char *out1 = NULL, *out2 = NULL;
MPI in = NULL, res = NULL, pkey[2];
uint8_t *p, *datap, *endp;
@@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key,
down_read(&key->sem);
ukp = key->payload.data;
+
+ if (ukp->datalen < sizeof(*pkh))
+ goto err1;
+
pkh = (struct pubkey_hdr *)ukp->data;
if (pkh->version != 1)
@@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key,
goto err1;
datap = pkh->mpi;
- endp = datap + ukp->datalen;
+ endp = ukp->data + ukp->datalen;
+
+ err = -ENOMEM;
for (i = 0; i < pkh->nmpi; i++) {
unsigned int remaining = endp - datap;
pkey[i] = mpi_read_from_buffer(datap, &remaining);
+ if (!pkey[i])
+ goto err;
datap += remaining;
}
mblen = mpi_get_nbits(pkey[0]);
mlen = (mblen + 7)/8;
- err = -ENOMEM;
+ if (mlen == 0)
+ goto err;
out1 = kzalloc(mlen, GFP_KERNEL);
if (!out1)
@@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key,
memset(out1, 0, head);
memcpy(out1 + head, p, l);
- err = -EINVAL;
- pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
+ err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
- if (valid && len == hlen)
+ if (!err && len == hlen)
err = memcmp(out2, h, hlen);
err:
@@ -178,8 +172,8 @@ err:
mpi_free(res);
kfree(out1);
kfree(out2);
- mpi_free(pkey[0]);
- mpi_free(pkey[1]);
+ while (--i >= 0)
+ mpi_free(pkey[i]);
err1:
up_read(&key->sem);
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index 7a94c8f14e29..b1dd3e7d88cb 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -44,12 +44,13 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
*
* Don't you dare use this function.
*/
-unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res)
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
{
+ unsigned long long res;
unsigned int rv;
int overflow;
- *res = 0;
+ res = 0;
rv = 0;
overflow = 0;
while (*s) {
@@ -64,12 +65,19 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long
if (val >= base)
break;
- if (*res > div_u64(ULLONG_MAX - val, base))
- overflow = 1;
- *res = *res * base + val;
+ /*
+ * Check for overflow only if we are within range of
+ * it in the max base we support (16)
+ */
+ if (unlikely(res & (~0ull << 60))) {
+ if (res > div_u64(ULLONG_MAX - val, base))
+ overflow = 1;
+ }
+ res = res * base + val;
rv++;
s++;
}
+ *p = res;
if (overflow)
rv |= KSTRTOX_OVERFLOW;
return rv;
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
index b87487b40a8b..29f98624ef93 100644
--- a/lib/mpi/longlong.h
+++ b/lib/mpi/longlong.h
@@ -1200,18 +1200,40 @@ do { \
"r" ((USItype)(v)) \
: "%g1", "%g2" __AND_CLOBBER_CC)
#define UMUL_TIME 39 /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+ The default udiv_qrnnd (in C) is more than 10 times slower! */
#define udiv_qrnnd(q, r, n1, n0, d) \
-do { USItype __r; \
- (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
- (r) = __r; \
-} while (0)
- extern USItype __udiv_qrnnd();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
+ __asm__ ("! Inlined udiv_qrnnd\n\t" \
+ "mov 32,%%g1\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "1: bcs 5f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "addx %1,%1,%1 ! so this can't give carry\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "2: bne 1b\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "bcs 3f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "b 3f\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "4: sub %1,%2,%1\n\t" \
+ "5: addxcc %1,%1,%1\n\t" \
+ "bcc 2b\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "! Got carry from n. Subtract next step to cancel this carry.\n\t" \
+ "bne 4b\n\t" \
+ "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \
+ "sub %1,%2,%1\n\t" \
+ "3: xnor %0,0,%0\n\t" \
+ "! End of inline udiv_qrnnd\n" \
+ : "=&r" ((USItype)(q)), \
+ "=&r" ((USItype)(r)) \
+ : "r" ((USItype)(d)), \
+ "1" ((USItype)(n1)), \
+ "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
+#endif
#endif /* __sparc__ */
/***************************************
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c
index 854c9c6da025..2f526627e4f5 100644
--- a/lib/mpi/mpi-bit.c
+++ b/lib/mpi/mpi-bit.c
@@ -21,25 +21,6 @@
#include "mpi-internal.h"
#include "longlong.h"
-const unsigned char __clz_tab[] = {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
-};
-
#define A_LIMB_1 ((mpi_limb_t) 1)
/****************
diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c
index c3087d1390ce..f68cbbb4d4a4 100644
--- a/lib/mpi/mpi-div.c
+++ b/lib/mpi/mpi-div.c
@@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
mpi_ptr_t marker[5];
int markidx = 0;
+ if (!dsize)
+ return -EINVAL;
+
memset(marker, 0, sizeof(marker));
/* Ensure space is enough for quotient and remainder.
@@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
* numerator would be gradually overwritten by the quotient limbs. */
if (qp == np) { /* Copy NP object to temporary space. */
np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+ if (!np)
+ goto nomem;
MPN_COPY(np, qp, nsize);
}
} else /* Put quotient at top of remainder. */
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
index b04a3cf80080..67f3e79af914 100644
--- a/lib/mpi/mpi-pow.c
+++ b/lib/mpi/mpi-pow.c
@@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
ep = exp->d;
if (!msize)
- msize = 1 / msize; /* provoke a signal */
+ return -EINVAL;
if (!esize) {
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 716802b774ea..f26b41fcb48c 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -20,78 +20,15 @@
#include "mpi-internal.h"
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define MAX_EXTERN_MPI_BITS 16384
-static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
- 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-MPI do_encode_md(const void *sha_buffer, unsigned nbits)
-{
- int nframe = (nbits + 7) / 8;
- uint8_t *frame, *fr_pt;
- int i = 0, n;
- size_t asnlen = DIM(asn);
- MPI a = MPI_NULL;
-
- if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
- pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
- (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
-
- /* We encode the MD in this way:
- *
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = kmalloc(nframe, GFP_KERNEL);
- if (!frame)
- return MPI_NULL;
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
-
- if (i <= 1) {
- pr_info("MPI: message digest encoding failed\n");
- kfree(frame);
- return a;
- }
-
- memset(frame + n, 0xff, i);
- n += i;
- frame[n++] = 0;
- memcpy(frame + n, &asn, asnlen);
- n += asnlen;
- memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
- n += SHA1_DIGEST_LENGTH;
-
- i = nframe;
- fr_pt = frame;
-
- if (n != nframe) {
- printk
- ("MPI: message digest encoding failed, frame length is wrong\n");
- kfree(frame);
- return a;
- }
-
- a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
- mpi_set_buffer(a, frame, nframe, 0);
- kfree(frame);
-
- return a;
-}
-
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
{
const uint8_t *buffer = xbuffer;
int i, j;
unsigned nbits, nbytes, nlimbs, nread = 0;
mpi_limb_t a;
- MPI val = MPI_NULL;
+ MPI val = NULL;
if (*ret_nread < 2)
goto leave;
@@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
val = mpi_alloc(nlimbs);
if (!val)
- return MPI_NULL;
+ return NULL;
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
@@ -212,30 +149,6 @@ int mpi_fromstr(MPI val, const char *str)
EXPORT_SYMBOL_GPL(mpi_fromstr);
/****************
- * Special function to get the low 8 bytes from an mpi.
- * This can be used as a keyid; KEYID is an 2 element array.
- * Return the low 4 bytes.
- */
-u32 mpi_get_keyid(const MPI a, u32 *keyid)
-{
-#if BYTES_PER_MPI_LIMB == 4
- if (keyid) {
- keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
- keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
- }
- return a->nlimbs >= 1 ? a->d[0] : 0;
-#elif BYTES_PER_MPI_LIMB == 8
- if (keyid) {
- keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
- keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
- }
- return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-#else
-#error Make this function work with other LIMB sizes
-#endif
-}
-
-/****************
* Return an allocated buffer with the MPI (msb first).
* NBYTES receives the length of this buffer. Caller must free the
* return string (This function does return a 0 byte buffer with NBYTES
diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c
index 87ede162dfab..cde1aaec18da 100644
--- a/lib/mpi/mpih-div.c
+++ b/lib/mpi/mpih-div.c
@@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
case 0:
/* We are asked to divide by zero, so go ahead and do it! (To make
the compiler not remove this statement, return the value.) */
+ /*
+ * existing clients of this function have been modified
+ * not to call it with dsize == 0, so this should not happen
+ */
return 1 / dsize;
case 1:
diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c
index eefc55d6b7f5..26e4ed31e256 100644
--- a/lib/mpi/mpiutil.c
+++ b/lib/mpi/mpiutil.c
@@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
{
size_t len = nlimbs * sizeof(mpi_limb_t);
+ if (!len)
+ return NULL;
+
return kmalloc(len, GFP_KERNEL);
}
@@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a)
size_t i;
MPI b;
- *copied = MPI_NULL;
+ *copied = NULL;
if (a) {
b = mpi_alloc(a->nlimbs);
diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c
index 4b0fdc22e688..0d83ea8a9605 100644
--- a/lib/pci_iomap.c
+++ b/lib/pci_iomap.c
@@ -34,7 +34,7 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
if (maxlen && len > maxlen)
len = maxlen;
if (flags & IORESOURCE_IO)
- return ioport_map(start, len);
+ return __pci_ioport_map(dev, start, len);
if (flags & IORESOURCE_MEM) {
if (flags & IORESOURCE_CACHEABLE)
return ioremap(start, len);
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 7ba8feae11b8..dd8e2aafb07e 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -318,7 +318,7 @@ static void wakeup_timer_fn(unsigned long data)
if (bdi->wb.task) {
trace_writeback_wake_thread(bdi);
wake_up_process(bdi->wb.task);
- } else {
+ } else if (bdi->dev) {
/*
* When bdi tasks are inactive for long time, they are killed.
* In this case we have to wake-up the forker thread which
@@ -584,6 +584,8 @@ EXPORT_SYMBOL(bdi_register_dev);
*/
static void bdi_wb_shutdown(struct backing_dev_info *bdi)
{
+ struct task_struct *task;
+
if (!bdi_cap_writeback_dirty(bdi))
return;
@@ -602,8 +604,13 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
* Finally, kill the kernel thread. We don't need to be RCU
* safe anymore, since the bdi is gone from visibility.
*/
- if (bdi->wb.task)
- kthread_stop(bdi->wb.task);
+ spin_lock_bh(&bdi->wb_lock);
+ task = bdi->wb.task;
+ bdi->wb.task = NULL;
+ spin_unlock_bh(&bdi->wb_lock);
+
+ if (task)
+ kthread_stop(task);
}
/*
@@ -623,7 +630,9 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
void bdi_unregister(struct backing_dev_info *bdi)
{
- if (bdi->dev) {
+ struct device *dev = bdi->dev;
+
+ if (dev) {
bdi_set_min_ratio(bdi, 0);
trace_writeback_bdi_unregister(bdi);
bdi_prune_sb(bdi);
@@ -632,8 +641,12 @@ void bdi_unregister(struct backing_dev_info *bdi)
if (!bdi_cap_flush_forker(bdi))
bdi_wb_shutdown(bdi);
bdi_debug_unregister(bdi);
- device_unregister(bdi->dev);
+
+ spin_lock_bh(&bdi->wb_lock);
bdi->dev = NULL;
+ spin_unlock_bh(&bdi->wb_lock);
+
+ device_unregister(dev);
}
}
EXPORT_SYMBOL(bdi_unregister);
diff --git a/mm/compaction.c b/mm/compaction.c
index 71a58f67f481..d9ebebe1a2aa 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -313,12 +313,34 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
} else if (!locked)
spin_lock_irq(&zone->lru_lock);
+ /*
+ * migrate_pfn does not necessarily start aligned to a
+ * pageblock. Ensure that pfn_valid is called when moving
+ * into a new MAX_ORDER_NR_PAGES range in case of large
+ * memory holes within the zone
+ */
+ if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) {
+ if (!pfn_valid(low_pfn)) {
+ low_pfn += MAX_ORDER_NR_PAGES - 1;
+ continue;
+ }
+ }
+
if (!pfn_valid_within(low_pfn))
continue;
nr_scanned++;
- /* Get the page and skip if free */
+ /*
+ * Get the page and ensure the page is within the same zone.
+ * See the comment in isolate_freepages about overlapping
+ * nodes. It is deliberate that the new zone lock is not taken
+ * as memory compaction should not move pages between nodes.
+ */
page = pfn_to_page(low_pfn);
+ if (page_zone(page) != zone)
+ continue;
+
+ /* Skip if free */
if (PageBuddy(page))
continue;
diff --git a/mm/filemap.c b/mm/filemap.c
index 97f49ed35bd2..b66275757c28 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long seg = 0;
size_t count;
loff_t *ppos = &iocb->ki_pos;
- struct blk_plug plug;
count = 0;
retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
if (retval)
return retval;
- blk_start_plug(&plug);
-
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
loff_t size;
@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
retval = filemap_write_and_wait_range(mapping, pos,
pos + iov_length(iov, nr_segs) - 1);
if (!retval) {
+ struct blk_plug plug;
+
+ blk_start_plug(&plug);
retval = mapping->a_ops->direct_IO(READ, iocb,
iov, pos, nr_segs);
+ blk_finish_plug(&plug);
}
if (retval > 0) {
*ppos = pos + retval;
@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
break;
}
out:
- blk_finish_plug(&plug);
return retval;
}
EXPORT_SYMBOL(generic_file_aio_read);
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index f91b2f687343..a4eb31132229 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -263,7 +263,12 @@ found:
xip_pfn);
if (err == -ENOMEM)
return VM_FAULT_OOM;
- BUG_ON(err);
+ /*
+ * err == -EBUSY is fine, we've raced against another thread
+ * that faulted-in the same page
+ */
+ if (err != -EBUSY)
+ BUG_ON(err);
return VM_FAULT_NOPAGE;
} else {
int err, ret = VM_FAULT_OOM;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index b3ffc21ce801..91d3efb25d15 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2083,7 +2083,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
{
struct mm_struct *mm = mm_slot->mm;
- VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
if (khugepaged_test_exit(mm)) {
/* free mm_slot */
@@ -2113,7 +2113,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
int progress = 0;
VM_BUG_ON(!pages);
- VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
if (khugepaged_scan.mm_slot)
mm_slot = khugepaged_scan.mm_slot;
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index c833addd94d7..45eb6217bf38 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
{
pr_debug("%s(0x%p)\n", __func__, ptr);
- if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+ if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))
add_scan_area((unsigned long)ptr, size, gfp);
else if (atomic_read(&kmemleak_early_log))
log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
@@ -1757,6 +1757,7 @@ void __init kmemleak_init(void)
#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
if (!kmemleak_skip_disable) {
+ atomic_set(&kmemleak_early_log, 0);
kmemleak_disable();
return;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 556859fec4ef..6728a7ae6f2d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
/* threshold event is triggered in finer grain than soft limit */
if (unlikely(mem_cgroup_event_ratelimit(memcg,
MEM_CGROUP_TARGET_THRESH))) {
- bool do_softlimit, do_numainfo;
+ bool do_softlimit;
+ bool do_numainfo __maybe_unused;
do_softlimit = mem_cgroup_event_ratelimit(memcg,
MEM_CGROUP_TARGET_SOFTLIMIT);
diff --git a/mm/migrate.c b/mm/migrate.c
index 9871a56d82c3..df141f60289e 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page)
ClearPageSwapCache(page);
ClearPagePrivate(page);
set_page_private(page, 0);
- page->mapping = NULL;
/*
* If any waiters have accumulated on the new page then
@@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
} else {
if (remap_swapcache)
remove_migration_ptes(page, newpage);
+ page->mapping = NULL;
}
unlock_page(newpage);
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index e920aa3ce104..c20ff48994c2 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,
goto free_proc_pages;
}
- task_lock(task);
- if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
- task_unlock(task);
- rc = -EPERM;
- goto put_task_struct;
- }
- mm = task->mm;
-
- if (!mm || (task->flags & PF_KTHREAD)) {
- task_unlock(task);
- rc = -EINVAL;
+ mm = mm_access(task, PTRACE_MODE_ATTACH);
+ if (!mm || IS_ERR(mm)) {
+ rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
+ /*
+ * Explicitly map EACCES to EPERM as EPERM is a more a
+ * appropriate error code for process_vw_readv/writev
+ */
+ if (rc == -EACCES)
+ rc = -EPERM;
goto put_task_struct;
}
- atomic_inc(&mm->mm_users);
- task_unlock(task);
-
for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {
rc = process_vm_rw_single_vec(
(unsigned long)rvec[i].iov_base, rvec[i].iov_len,
diff --git a/mm/swap.c b/mm/swap.c
index b0f529b38979..fff1ff7fb9ad 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -659,7 +659,7 @@ void lru_add_page_tail(struct zone* zone,
VM_BUG_ON(!PageHead(page));
VM_BUG_ON(PageCompound(page_tail));
VM_BUG_ON(PageLRU(page_tail));
- VM_BUG_ON(!spin_is_locked(&zone->lru_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock));
SetPageLRU(page_tail);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index a98628086452..a97d97a3a512 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -539,8 +539,10 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
memset(skb->cb, 0, sizeof(struct caif_payload_info));
- if (cf_sk->layer.dn == NULL)
+ if (cf_sk->layer.dn == NULL) {
+ kfree_skb(skb);
return -EINVAL;
+ }
return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
}
@@ -683,10 +685,10 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
}
err = transmit_skb(skb, cf_sk,
msg->msg_flags&MSG_DONTWAIT, timeo);
- if (err < 0) {
- kfree_skb(skb);
+ if (err < 0)
+ /* skb is already freed */
goto pipe_err;
- }
+
sent += size;
}
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
index b36f24a4c8e7..94b08612a4d8 100644
--- a/net/caif/cfmuxl.c
+++ b/net/caif/cfmuxl.c
@@ -248,7 +248,6 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
{
struct cfmuxl *muxl = container_obj(layr);
struct cflayer *layer;
- int idx;
rcu_read_lock();
list_for_each_entry_rcu(layer, &muxl->srvl_list, node) {
@@ -257,14 +256,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||
ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) &&
- layer->id != 0) {
-
- idx = layer->id % UP_CACHE_SIZE;
- spin_lock_bh(&muxl->receive_lock);
- RCU_INIT_POINTER(muxl->up_cache[idx], NULL);
- list_del_rcu(&layer->node);
- spin_unlock_bh(&muxl->receive_lock);
- }
+ layer->id != 0)
+ cfmuxl_remove_uplayer(layr, layer->id);
+
/* NOTE: ctrlcmd is not allowed to block */
layer->ctrlcmd(layer, ctrl, phyid);
}
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 97f70e50ad3b..761ad9d6cc3b 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
} else {
pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
memcpy(&client->fsid, fsid, sizeof(*fsid));
- ceph_debugfs_client_init(client);
- client->have_fsid = true;
}
return 0;
}
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 0b62deae42bd..1845cde26227 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -8,8 +8,8 @@
#include <linux/ceph/mon_client.h>
#include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
#include <linux/ceph/decode.h>
-
#include <linux/ceph/auth.h>
/*
@@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,
client->monc.monmap = monmap;
kfree(old);
+ if (!client->have_fsid) {
+ client->have_fsid = true;
+ mutex_unlock(&monc->mutex);
+ /*
+ * do debugfs initialization without mutex to avoid
+ * creating a locking dependency
+ */
+ ceph_debugfs_client_init(client);
+ goto out_unlocked;
+ }
out:
mutex_unlock(&monc->mutex);
+out_unlocked:
wake_up_all(&client->auth_wq);
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 115dee1d985d..6ca32f6b3105 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3500,14 +3500,20 @@ static inline gro_result_t
__napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
struct sk_buff *p;
+ unsigned int maclen = skb->dev->hard_header_len;
for (p = napi->gro_list; p; p = p->next) {
unsigned long diffs;
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
diffs |= p->vlan_tci ^ skb->vlan_tci;
- diffs |= compare_ether_header(skb_mac_header(p),
- skb_gro_mac_header(skb));
+ if (maclen == ETH_HLEN)
+ diffs |= compare_ether_header(skb_mac_header(p),
+ skb_gro_mac_header(skb));
+ else if (!diffs)
+ diffs = memcmp(skb_mac_header(p),
+ skb_gro_mac_header(skb),
+ maclen);
NAPI_GRO_CB(p)->same_flow = !diffs;
NAPI_GRO_CB(p)->flush = 0;
}
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 369b41894527..3f79db1b612a 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1190,6 +1190,8 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev,
if (!dev->ethtool_ops->flash_device)
return -EOPNOTSUPP;
+ efl.data[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
+
return dev->ethtool_ops->flash_device(dev, &efl);
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 556b08298669..ddefc513b44a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -194,7 +194,7 @@ static void netpoll_poll_dev(struct net_device *dev)
poll_napi(dev);
- if (dev->priv_flags & IFF_SLAVE) {
+ if (dev->flags & IFF_SLAVE) {
if (dev->npinfo) {
struct net_device *bond_dev = dev->master;
struct sk_buff *skb;
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index 3a9fd4826b75..4dacc44637ef 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -58,11 +58,12 @@ static int get_prioidx(u32 *prio)
spin_lock_irqsave(&prioidx_map_lock, flags);
prioidx = find_first_zero_bit(prioidx_map, sizeof(unsigned long) * PRIOIDX_SZ);
+ if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ) {
+ spin_unlock_irqrestore(&prioidx_map_lock, flags);
+ return -ENOSPC;
+ }
set_bit(prioidx, prioidx_map);
spin_unlock_irqrestore(&prioidx_map_lock, flags);
- if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ)
- return -ENOSPC;
-
atomic_set(&max_prioidx, prioidx);
*prio = prioidx;
return 0;
@@ -107,7 +108,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)
static void update_netdev_tables(void)
{
struct net_device *dev;
- u32 max_len = atomic_read(&max_prioidx);
+ u32 max_len = atomic_read(&max_prioidx) + 1;
struct netprio_map *map;
rtnl_lock();
@@ -270,7 +271,6 @@ static int netprio_device_event(struct notifier_block *unused,
{
struct net_device *dev = ptr;
struct netprio_map *old;
- u32 max_len = atomic_read(&max_prioidx);
/*
* Note this is called with rtnl_lock held so we have update side
@@ -278,11 +278,6 @@ static int netprio_device_event(struct notifier_block *unused,
*/
switch (event) {
-
- case NETDEV_REGISTER:
- if (max_len)
- extend_netdev_table(dev, max_len);
- break;
case NETDEV_UNREGISTER:
old = rtnl_dereference(dev->priomap);
RCU_INIT_POINTER(dev->priomap, NULL);
diff --git a/net/core/sock.c b/net/core/sock.c
index 3e81fd2e3c75..02f8dfe320b7 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1171,13 +1171,10 @@ EXPORT_SYMBOL(sock_update_classid);
void sock_update_netprioidx(struct sock *sk)
{
- struct cgroup_netprio_state *state;
if (in_interrupt())
return;
- rcu_read_lock();
- state = task_netprio_state(current);
- sk->sk_cgrp_prioidx = state ? state->prioidx : 0;
- rcu_read_unlock();
+
+ sk->sk_cgrp_prioidx = task_netprioidx(current);
}
EXPORT_SYMBOL_GPL(sock_update_netprioidx);
#endif
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index aa2a2c79776f..d183262943d9 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -409,7 +409,7 @@ config INET_TCP_DIAG
config INET_UDP_DIAG
tristate "UDP: socket monitoring interface"
- depends on INET_DIAG
+ depends on INET_DIAG && (IPV6 || IPV6=n)
default n
---help---
Support for UDP socket monitoring interface used by the ss tool.
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 59402be133f0..63e49890ad31 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -863,7 +863,8 @@ static int arp_process(struct sk_buff *skb)
if (addr_type == RTN_UNICAST &&
(arp_fwd_proxy(in_dev, dev, rt) ||
arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
- pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
+ (rt->dst.dev != dev &&
+ pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n)
neigh_release(n);
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 1e60f7679075..42dd1a90edea 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -573,8 +573,8 @@ void ip_forward_options(struct sk_buff *skb)
}
if (srrptr + 3 <= srrspace) {
opt->is_changed = 1;
- ip_rt_get_source(&optptr[srrptr-1], skb, rt);
ip_hdr(skb)->daddr = opt->nexthop;
+ ip_rt_get_source(&optptr[srrptr-1], skb, rt);
optptr[2] = srrptr+4;
} else if (net_ratelimit())
printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 4cb9cd2f2c39..7a7724da9bff 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -778,7 +778,6 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
static __net_init int ipv4_sysctl_init_net(struct net *net)
{
struct ctl_table *table;
- unsigned long limit;
table = ipv4_net_table;
if (!net_eq(net, &init_net)) {
@@ -815,11 +814,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
net->ipv4.sysctl_rt_cache_rebuild_count = 4;
tcp_init_mem(net);
- limit = nr_free_buffer_pages() / 8;
- limit = max(limit, 128UL);
- net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
- net->ipv4.sysctl_tcp_mem[1] = limit;
- net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
net_ipv4_ctl_path, table);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 06373b4a449a..37755ccc0e96 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1876,6 +1876,20 @@ void tcp_shutdown(struct sock *sk, int how)
}
EXPORT_SYMBOL(tcp_shutdown);
+bool tcp_check_oom(struct sock *sk, int shift)
+{
+ bool too_many_orphans, out_of_socket_memory;
+
+ too_many_orphans = tcp_too_many_orphans(sk, shift);
+ out_of_socket_memory = tcp_out_of_memory(sk);
+
+ if (too_many_orphans && net_ratelimit())
+ pr_info("TCP: too many orphaned sockets\n");
+ if (out_of_socket_memory && net_ratelimit())
+ pr_info("TCP: out of memory -- consider tuning tcp_mem\n");
+ return too_many_orphans || out_of_socket_memory;
+}
+
void tcp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
@@ -2015,10 +2029,7 @@ adjudge_to_death:
}
if (sk->sk_state != TCP_CLOSE) {
sk_mem_reclaim(sk);
- if (tcp_too_many_orphans(sk, 0)) {
- if (net_ratelimit())
- printk(KERN_INFO "TCP: too many of orphaned "
- "sockets\n");
+ if (tcp_check_oom(sk, 0)) {
tcp_set_state(sk, TCP_CLOSE);
tcp_send_active_reset(sk, GFP_ATOMIC);
NET_INC_STATS_BH(sock_net(sk),
@@ -3218,7 +3229,6 @@ __setup("thash_entries=", set_thash_entries);
void tcp_init_mem(struct net *net)
{
- /* Set per-socket limits to no more than 1/128 the pressure threshold */
unsigned long limit = nr_free_buffer_pages() / 8;
limit = max(limit, 128UL);
net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
@@ -3287,7 +3297,8 @@ void __init tcp_init(void)
sysctl_max_syn_backlog = max(128, cnt / 256);
tcp_init_mem(&init_net);
- limit = nr_free_buffer_pages() / 8;
+ /* Set per-socket limits to no more than 1/128 the pressure threshold */
+ limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10);
limit = max(limit, 128UL);
max_share = min(4UL*1024*1024, limit);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 976034f82320..53c8ce4046b2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1307,25 +1307,26 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
return in_sack;
}
-static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
- struct tcp_sacktag_state *state,
+/* Mark the given newly-SACKed range as such, adjusting counters and hints. */
+static u8 tcp_sacktag_one(struct sock *sk,
+ struct tcp_sacktag_state *state, u8 sacked,
+ u32 start_seq, u32 end_seq,
int dup_sack, int pcount)
{
struct tcp_sock *tp = tcp_sk(sk);
- u8 sacked = TCP_SKB_CB(skb)->sacked;
int fack_count = state->fack_count;
/* Account D-SACK for retransmitted packet. */
if (dup_sack && (sacked & TCPCB_RETRANS)) {
if (tp->undo_marker && tp->undo_retrans &&
- after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
+ after(end_seq, tp->undo_marker))
tp->undo_retrans--;
if (sacked & TCPCB_SACKED_ACKED)
state->reord = min(fack_count, state->reord);
}
/* Nothing to do; acked frame is about to be dropped (was ACKed). */
- if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
+ if (!after(end_seq, tp->snd_una))
return sacked;
if (!(sacked & TCPCB_SACKED_ACKED)) {
@@ -1344,13 +1345,13 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
/* New sack for not retransmitted frame,
* which was in hole. It is reordering.
*/
- if (before(TCP_SKB_CB(skb)->seq,
+ if (before(start_seq,
tcp_highest_sack_seq(tp)))
state->reord = min(fack_count,
state->reord);
/* SACK enhanced F-RTO (RFC4138; Appendix B) */
- if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
+ if (!after(end_seq, tp->frto_highmark))
state->flag |= FLAG_ONLY_ORIG_SACKED;
}
@@ -1368,8 +1369,7 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
/* Lost marker hint past SACKed? Tweak RFC3517 cnt */
if (!tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) &&
- before(TCP_SKB_CB(skb)->seq,
- TCP_SKB_CB(tp->lost_skb_hint)->seq))
+ before(start_seq, TCP_SKB_CB(tp->lost_skb_hint)->seq))
tp->lost_cnt_hint += pcount;
if (fack_count > tp->fackets_out)
@@ -1388,6 +1388,9 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk,
return sacked;
}
+/* Shift newly-SACKed bytes from this skb to the immediately previous
+ * already-SACKed sk_buff. Mark the newly-SACKed bytes as such.
+ */
static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
struct tcp_sacktag_state *state,
unsigned int pcount, int shifted, int mss,
@@ -1395,10 +1398,13 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *prev = tcp_write_queue_prev(sk, skb);
+ u32 start_seq = TCP_SKB_CB(skb)->seq; /* start of newly-SACKed */
+ u32 end_seq = start_seq + shifted; /* end of newly-SACKed */
BUG_ON(!pcount);
- if (skb == tp->lost_skb_hint)
+ /* Adjust hint for FACK. Non-FACK is handled in tcp_sacktag_one(). */
+ if (tcp_is_fack(tp) && (skb == tp->lost_skb_hint))
tp->lost_cnt_hint += pcount;
TCP_SKB_CB(prev)->end_seq += shifted;
@@ -1424,8 +1430,11 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
skb_shinfo(skb)->gso_type = 0;
}
- /* We discard results */
- tcp_sacktag_one(skb, sk, state, dup_sack, pcount);
+ /* Adjust counters and hints for the newly sacked sequence range but
+ * discard the return value since prev is already marked.
+ */
+ tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
+ start_seq, end_seq, dup_sack, pcount);
/* Difference in this won't matter, both ACKed by the same cumul. ACK */
TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS);
@@ -1664,10 +1673,14 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
break;
if (in_sack) {
- TCP_SKB_CB(skb)->sacked = tcp_sacktag_one(skb, sk,
- state,
- dup_sack,
- tcp_skb_pcount(skb));
+ TCP_SKB_CB(skb)->sacked =
+ tcp_sacktag_one(sk,
+ state,
+ TCP_SKB_CB(skb)->sacked,
+ TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq,
+ dup_sack,
+ tcp_skb_pcount(skb));
if (!before(TCP_SKB_CB(skb)->seq,
tcp_highest_sack_seq(tp)))
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 337ba4cca052..94d683a61cba 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -651,6 +651,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
+ /* When socket is gone, all binding information is lost.
+ * routing might fail in this case. using iif for oif to
+ * make sure we can deliver it
+ */
+ arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
net = dev_net(skb_dst(skb)->dev);
arg.tos = ip_hdr(skb)->tos;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index a516d1e399df..cd2e0723266d 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -77,10 +77,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
if (sk->sk_err_soft)
shift++;
- if (tcp_too_many_orphans(sk, shift)) {
- if (net_ratelimit())
- printk(KERN_INFO "Out of socket memory\n");
-
+ if (tcp_check_oom(sk, shift)) {
/* Catch exceptional cases, when connection requires reset.
* 1. Last segment was sent recently. */
if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0a0d94ad9b08..b142bd4c2390 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
result);
+ ieee80211_led_init(local);
+
rtnl_lock();
result = ieee80211_init_rate_ctrl_alg(local,
@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
rtnl_unlock();
- ieee80211_led_init(local);
-
local->network_latency_notifier.notifier_call =
ieee80211_max_network_latency;
result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 751409120769..5a5e504a8ffb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -611,7 +611,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
tid_agg_rx->buf_size;
if (!tid_agg_rx->reorder_buf[index] &&
- tid_agg_rx->stored_mpdu_num > 1) {
+ tid_agg_rx->stored_mpdu_num) {
/*
* No buffers ready to be released, but check whether any
* frames in the reorder buffer have timed out.
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index 4cba13e46ffd..ae3a035f5390 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -232,7 +232,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
if (toklen <= (n_parts + 1) * 4)
return -EINVAL;
- princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL);
+ princ->name_parts = kcalloc(n_parts, sizeof(char *), GFP_KERNEL);
if (!princ->name_parts)
return -ENOMEM;
@@ -355,7 +355,7 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
_debug("n_elem %d", n_elem);
- td = kcalloc(sizeof(struct krb5_tagged_data), n_elem,
+ td = kcalloc(n_elem, sizeof(struct krb5_tagged_data),
GFP_KERNEL);
if (!td)
return -ENOMEM;
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index e465064d39a3..7e267d7b9c75 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -148,8 +148,7 @@ struct choke_skb_cb {
static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct choke_skb_cb));
return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data;
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 2776012132ea..e83d61ca78ca 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -130,8 +130,7 @@ struct netem_skb_cb {
static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 96e42cae4c7a..d7eea99333e9 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -94,8 +94,7 @@ struct sfb_skb_cb {
static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct sfb_skb_cb));
return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data;
}
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 67494aef9acf..60d47180f043 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -166,9 +166,8 @@ struct sfq_skb_cb {
static inline struct sfq_skb_cb *sfq_skb_cb(const struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct sfq_skb_cb));
- return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
+ qdisc_cb_private_validate(skb, sizeof(struct sfq_skb_cb));
+ return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
}
static unsigned int sfq_hash(const struct sfq_sched_data *q,
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index e3bfcbe8a520..a3b9782441f9 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1924,6 +1924,12 @@ sub process {
my $pre_ctx = "$1$2";
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
+
+ if ($line =~ /^\+\t{6,}/) {
+ WARN("DEEP_INDENTATION",
+ "Too many leading tabs - consider code refactoring\n" . $herecurr);
+ }
+
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e8c969577768..d0de2a2c3a2d 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -932,7 +932,7 @@ static int do_isapnp_entry(const char *filename,
(id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);
return 1;
}
-ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry);
+ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);
/*
* Append a match expression for a single masked hex digit.
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index 762af68c8996..270790d384e2 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -1132,15 +1132,4 @@ static struct i2c_driver onyx_driver = {
.id_table = onyx_i2c_id,
};
-static int __init onyx_init(void)
-{
- return i2c_add_driver(&onyx_driver);
-}
-
-static void __exit onyx_exit(void)
-{
- i2c_del_driver(&onyx_driver);
-}
-
-module_init(onyx_init);
-module_exit(onyx_exit);
+module_i2c_driver(onyx_driver);
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index fd2188c3df2b..8e63d1f35ce1 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -1026,15 +1026,4 @@ static struct i2c_driver tas_driver = {
.id_table = tas_i2c_id,
};
-static int __init tas_init(void)
-{
- return i2c_add_driver(&tas_driver);
-}
-
-static void __exit tas_exit(void)
-{
- i2c_del_driver(&tas_driver);
-}
-
-module_init(tas_init);
-module_exit(tas_exit);
+module_i2c_driver(tas_driver);
diff --git a/sound/core/control.c b/sound/core/control.c
index 819a5c579a39..2487a6bb1c54 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1313,7 +1313,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
err = -EPERM;
goto __kctl_end;
}
- err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+ err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
if (err > 0) {
up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
diff --git a/sound/core/init.c b/sound/core/init.c
index 3ac49b1b7cb8..068cf08d3ffb 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card)
EXPORT_SYMBOL(snd_card_free);
-static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
+/* retrieve the last word of shortname or longname */
+static const char *retrieve_id_from_card_name(const char *name)
{
- int i, len, idx_flag = 0, loops = SNDRV_CARDS;
- const char *spos, *src;
- char *id;
-
- if (nid == NULL) {
- id = card->shortname;
- spos = src = id;
- while (*id != '\0') {
- if (*id == ' ')
- spos = id + 1;
- id++;
- }
- } else {
- spos = src = nid;
+ const char *spos = name;
+
+ while (*name) {
+ if (isspace(*name) && isalnum(name[1]))
+ spos = name + 1;
+ name++;
}
- id = card->id;
- while (*spos != '\0' && !isalnum(*spos))
- spos++;
- if (isdigit(*spos))
- *id++ = isalpha(src[0]) ? src[0] : 'D';
- while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
- if (isalnum(*spos))
- *id++ = *spos;
- spos++;
+ return spos;
+}
+
+/* return true if the given id string doesn't conflict any other card ids */
+static bool card_id_ok(struct snd_card *card, const char *id)
+{
+ int i;
+ if (!snd_info_check_reserved_words(id))
+ return false;
+ for (i = 0; i < snd_ecards_limit; i++) {
+ if (snd_cards[i] && snd_cards[i] != card &&
+ !strcmp(snd_cards[i]->id, id))
+ return false;
}
- *id = '\0';
+ return true;
+}
- id = card->id;
+/* copy to card->id only with valid letters from nid */
+static void copy_valid_id_string(struct snd_card *card, const char *src,
+ const char *nid)
+{
+ char *id = card->id;
+
+ while (*nid && !isalnum(*nid))
+ nid++;
+ if (isdigit(*nid))
+ *id++ = isalpha(*src) ? *src : 'D';
+ while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
+ if (isalnum(*nid))
+ *id++ = *nid;
+ nid++;
+ }
+ *id = 0;
+}
+
+/* Set card->id from the given string
+ * If the string conflicts with other ids, add a suffix to make it unique.
+ */
+static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
+ const char *nid)
+{
+ int len, loops;
+ bool with_suffix;
+ bool is_default = false;
+ char *id;
- if (*id == '\0')
+ copy_valid_id_string(card, src, nid);
+ id = card->id;
+
+ again:
+ /* use "Default" for obviously invalid strings
+ * ("card" conflicts with proc directories)
+ */
+ if (!*id || !strncmp(id, "card", 4)) {
strcpy(id, "Default");
+ is_default = true;
+ }
- while (1) {
- if (loops-- == 0) {
- snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
- strcpy(card->id, card->proc_root->name);
- return;
- }
- if (!snd_info_check_reserved_words(id))
- goto __change;
- for (i = 0; i < snd_ecards_limit; i++) {
- if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
- goto __change;
- }
- break;
+ with_suffix = false;
+ for (loops = 0; loops < SNDRV_CARDS; loops++) {
+ if (card_id_ok(card, id))
+ return; /* OK */
- __change:
len = strlen(id);
- if (idx_flag) {
- if (id[len-1] != '9')
- id[len-1]++;
- else
- id[len-1] = 'A';
- } else if ((size_t)len <= sizeof(card->id) - 3) {
- strcat(id, "_1");
- idx_flag++;
+ if (!with_suffix) {
+ /* add the "_X" suffix */
+ char *spos = id + len;
+ if (len > sizeof(card->id) - 3)
+ spos = id + sizeof(card->id) - 3;
+ strcpy(spos, "_1");
+ with_suffix = true;
} else {
- spos = id + len - 2;
- if ((size_t)len <= sizeof(card->id) - 2)
- spos++;
- *(char *)spos++ = '_';
- *(char *)spos++ = '1';
- *(char *)spos++ = '\0';
- idx_flag++;
+ /* modify the existing suffix */
+ if (id[len - 1] != '9')
+ id[len - 1]++;
+ else
+ id[len - 1] = 'A';
}
}
+ /* fallback to the default id */
+ if (!is_default) {
+ *id = 0;
+ goto again;
+ }
+ /* last resort... */
+ snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
+ if (card->proc_root->name)
+ strcpy(card->id, card->proc_root->name);
}
/**
@@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
if (card->id[0] != '\0')
return;
mutex_lock(&snd_card_mutex);
- snd_card_set_id_no_lock(card, nid);
+ snd_card_set_id_no_lock(card, nid, nid);
mutex_unlock(&snd_card_mutex);
}
EXPORT_SYMBOL(snd_card_set_id);
@@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
memcpy(buf1, buf, copy);
buf1[copy] = '\0';
mutex_lock(&snd_card_mutex);
- if (!snd_info_check_reserved_words(buf1)) {
- __exist:
+ if (!card_id_ok(NULL, buf1)) {
mutex_unlock(&snd_card_mutex);
return -EEXIST;
}
- for (idx = 0; idx < snd_ecards_limit; idx++) {
- 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;
@@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card)
mutex_unlock(&snd_card_mutex);
return 0;
}
- snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
+ if (*card->id) {
+ /* make a unique id name from the given string */
+ char tmpid[sizeof(card->id)];
+ memcpy(tmpid, card->id, sizeof(card->id));
+ snd_card_set_id_no_lock(card, tmpid, tmpid);
+ } else {
+ /* create an id from either shortname or longname */
+ const char *src;
+ src = *card->shortname ? card->shortname : card->longname;
+ snd_card_set_id_no_lock(card, src,
+ retrieve_id_from_card_name(src));
+ }
snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex);
init_info_for_card(card);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 465f0ce772cb..768167925409 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -72,7 +72,7 @@ void __snd_printk(unsigned int level, const char *path, int line,
char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
#endif
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_DEBUG
if (debug < level)
return;
#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8928ca871c22..6e4bfcc14254 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -650,7 +650,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
pstr->stream = stream;
pstr->pcm = pcm;
pstr->substream_count = substream_count;
- if (substream_count > 0) {
+ if (substream_count > 0 && !pcm->internal) {
err = snd_pcm_stream_proc_init(pstr);
if (err < 0) {
snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -674,15 +674,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
pstr->substream = substream;
else
prev->next = substream;
- err = snd_pcm_substream_proc_init(substream);
- if (err < 0) {
- snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
- if (prev == NULL)
- pstr->substream = NULL;
- else
- prev->next = NULL;
- kfree(substream);
- return err;
+
+ if (!pcm->internal) {
+ err = snd_pcm_substream_proc_init(substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+ if (prev == NULL)
+ pstr->substream = NULL;
+ else
+ prev->next = NULL;
+ kfree(substream);
+ return err;
+ }
}
substream->group = &substream->self_group;
spin_lock_init(&substream->self_group.lock);
@@ -696,25 +699,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
EXPORT_SYMBOL(snd_pcm_new_stream);
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
- int playback_count, int capture_count,
- struct snd_pcm ** rpcm)
+static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count, bool internal,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -735,6 +722,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
}
pcm->card = card;
pcm->device = device;
+ pcm->internal = internal;
if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -756,8 +744,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
return 0;
}
+/**
+ * snd_pcm_new - create a new PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new PCM instance.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count, struct snd_pcm **rpcm)
+{
+ return _snd_pcm_new(card, id, device, playback_count, capture_count,
+ false, rpcm);
+}
EXPORT_SYMBOL(snd_pcm_new);
+/**
+ * snd_pcm_new_internal - create a new internal PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based - shared with normal PCMs)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new internal PCM instance with no userspace device or procfs
+ * entries. This is used by ASoC Back End PCMs in order to create a PCM that
+ * will only be used internally by kernel drivers. i.e. it cannot be opened
+ * by userspace. It provides existing ASoC components drivers with a substream
+ * and access to any private data.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count,
+ struct snd_pcm **rpcm)
+{
+ return _snd_pcm_new(card, id, device, playback_count, capture_count,
+ true, rpcm);
+}
+EXPORT_SYMBOL(snd_pcm_new_internal);
+
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
struct snd_pcm_substream *substream, *substream_next;
@@ -994,7 +1033,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
}
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
- if (pcm->streams[cidx].substream == NULL)
+ if (pcm->streams[cidx].substream == NULL || pcm->internal)
continue;
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3420bd3da5d7..4d18941178e6 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1029,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i,
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
+int snd_interval_list(struct snd_interval *i, unsigned int count,
+ const unsigned int *list, unsigned int mask)
{
unsigned int k;
struct snd_interval list_range;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 25ed9fe41b89..3fe99e644eb8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
struct file *file;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
+ struct snd_pcm_group *group;
file = snd_pcm_file_fd(fd);
if (!file)
return -EBADFD;
pcm_file = file->private_data;
substream1 = pcm_file->substream;
+ group = kmalloc(sizeof(*group), GFP_KERNEL);
+ if (!group) {
+ res = -ENOMEM;
+ goto _nolock;
+ }
down_write(&snd_pcm_link_rwsem);
write_lock_irq(&snd_pcm_link_rwlock);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
goto _end;
}
if (!snd_pcm_stream_linked(substream)) {
- substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC);
- if (substream->group == NULL) {
- res = -ENOMEM;
- goto _end;
- }
+ substream->group = group;
spin_lock_init(&substream->group->lock);
INIT_LIST_HEAD(&substream->group->substreams);
list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
_end:
write_unlock_irq(&snd_pcm_link_rwlock);
up_write(&snd_pcm_link_rwsem);
+ _nolock:
fput(file);
+ if (res < 0)
+ kfree(group);
return res;
}
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 130cfe677d60..14a286a7bf2b 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -37,6 +37,8 @@ struct link_master {
struct link_ctl_info info;
int val; /* the master value */
unsigned int tlv[4];
+ void (*hook)(void *private_data, int);
+ void *hook_private_data;
};
/*
@@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
master->info.count = 1; /* always mono */
/* set full volume as default (= no attenuation) */
master->val = master->info.max_val;
- return 0;
+ if (master->hook)
+ master->hook(master->hook_private_data, master->val);
+ return 1;
}
return -ENOENT;
}
@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
slave_put_val(slave, uval);
}
kfree(uval);
+ if (master->hook && !err)
+ master->hook(master->hook_private_data, master->val);
return 1;
}
@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
return kctl;
}
EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+
+/**
+ * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
+ * @kcontrol: vmaster kctl element
+ * @hook: the hook function
+ *
+ * Adds the given hook to the vmaster control element so that it's called
+ * at each time when the value is changed.
+ */
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
+ void (*hook)(void *private_data, int),
+ void *private_data)
+{
+ struct link_master *master = snd_kcontrol_chip(kcontrol);
+ master->hook = hook;
+ master->hook_private_data = private_data;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
+
+/**
+ * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
+ * @kcontrol: vmaster kctl element
+ *
+ * Call the hook function to synchronize with the current value of the given
+ * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't
+ * exist.
+ */
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
+{
+ struct link_master *master;
+ if (!kcontrol)
+ return;
+ master = snd_kcontrol_chip(kcontrol);
+ if (master->hook)
+ master->hook(master->hook_private_data, master->val);
+}
+EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index e09f144177f5..c99c6078be33 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -22,7 +22,6 @@
#include "emu8000_local.h"
#include <asm/uaccess.h>
#include <linux/moduleparam.h>
-#include <linux/moduleparam.h>
static int emu8000_reset_addr;
module_param(emu8000_reset_addr, int, 0444);
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index bb938153a964..466a5c8e8354 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -26,7 +26,7 @@
#include <sound/mpu401.h>
#include <sound/hwdep.h>
#include <sound/ac97_codec.h>
-
+#include <sound/tlv.h>
#endif
#ifndef CHIP_AU8820
@@ -107,6 +107,14 @@
#define NR_WTPB 0x20 /* WT channels per each bank. */
#define NR_PCM 0x10
+struct pcm_vol {
+ struct snd_kcontrol *kctl;
+ int active;
+ int dma;
+ int mixin[4];
+ int vol[4];
+};
+
/* Structs */
typedef struct {
//int this_08; /* Still unknown */
@@ -168,6 +176,7 @@ struct snd_vortex {
/* Xtalk canceler */
int xt_mode; /* 1: speakers, 0:headphones. */
#endif
+ struct pcm_vol pcm_vol[NR_PCM];
int isquad; /* cache of extended ID codec flag. */
@@ -239,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt);
/* Connection stuff. */
static void vortex_connect_default(vortex_t * vortex, int en);
static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch,
- int dir, int type);
+ int dir, int type, int subdev);
static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out,
int restype);
#ifndef CHIP_AU8810
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 6933a27a5d76..525f881f0409 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2050,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
}
/* Default Connections */
-static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type);
static void vortex_connect_default(vortex_t * vortex, int en)
{
@@ -2111,15 +2109,13 @@ static void vortex_connect_default(vortex_t * vortex, int en)
Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0.
*/
static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
+vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir,
+ int type, int subdev)
{
stream_t *stream;
int i, en;
+ struct pcm_vol *p;
- if ((nr_ch == 3)
- || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2)))
- return -EBUSY;
-
if (dma >= 0) {
en = 0;
vortex_adb_checkinout(vortex,
@@ -2250,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
MIX_DEFIGAIN);
#endif
}
+ if (stream->type == VORTEX_PCM_ADB && en) {
+ p = &vortex->pcm_vol[subdev];
+ p->dma = dma;
+ for (i = 0; i < nr_ch; i++)
+ p->mixin[i] = mix[i];
+ for (i = 0; i < ch_top; i++)
+ p->vol[i] = 0;
+ }
}
#ifndef CHIP_AU8820
else {
@@ -2473,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
hwread(vortex->mmio, VORTEX_IRQ_STAT);
handled = 1;
}
- if (source & IRQ_MIDI) {
+ if ((source & IRQ_MIDI) && vortex->rmidi) {
snd_mpu401_uart_interrupt(vortex->irq,
vortex->rmidi->private_data);
handled = 1;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 0ef2f9712208..e59f120742a4 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
.mask = 0,
};
#endif
+
+static void vortex_notify_pcm_vol_change(struct snd_card *card,
+ struct snd_kcontrol *kctl, int activate)
+{
+ if (activate)
+ kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ else
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
+}
+
/* open callback */
static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
{
@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
if (stream != NULL)
vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir,
- stream->type);
+ stream->type,
+ substream->number);
/* Alloc routes. */
dma =
vortex_adb_allocroute(chip, -1,
params_channels(hw_params),
- substream->stream, type);
+ substream->stream, type,
+ substream->number);
if (dma < 0) {
spin_unlock_irq(&chip->lock);
return dma;
@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
vortex_adbdma_setbuffers(chip, dma,
params_period_bytes(hw_params),
params_periods(hw_params));
+ if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+ chip->pcm_vol[substream->number].active = 1;
+ vortex_notify_pcm_vol_change(chip->card,
+ chip->pcm_vol[substream->number].kctl, 1);
+ }
}
#ifndef CHIP_AU8810
else {
@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
spin_lock_irq(&chip->lock);
// Delete audio routes.
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
- if (stream != NULL)
+ if (stream != NULL) {
+ if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+ chip->pcm_vol[substream->number].active = 0;
+ vortex_notify_pcm_vol_change(chip->card,
+ chip->pcm_vol[substream->number].kctl,
+ 0);
+ }
vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir,
- stream->type);
+ stream->type,
+ substream->number);
+ }
}
#ifndef CHIP_AU8810
else {
@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
},
};
+/* subdevice PCM Volume control */
+
+static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ uinfo->value.integer.min = -128;
+ uinfo->value.integer.max = 32;
+ return 0;
+}
+
+static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ int subdev = kcontrol->id.subdevice;
+ struct pcm_vol *p = &vortex->pcm_vol[subdev];
+ int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ for (i = 0; i < max_chn; i++)
+ ucontrol->value.integer.value[i] = p->vol[i];
+ return 0;
+}
+
+static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ int changed = 0;
+ int mixin;
+ unsigned char vol;
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ int subdev = kcontrol->id.subdevice;
+ struct pcm_vol *p = &vortex->pcm_vol[subdev];
+ int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ for (i = 0; i < max_chn; i++) {
+ if (p->vol[i] != ucontrol->value.integer.value[i]) {
+ p->vol[i] = ucontrol->value.integer.value[i];
+ if (p->active) {
+ switch (vortex->dma_adb[p->dma].nr_ch) {
+ case 1:
+ mixin = p->mixin[0];
+ break;
+ case 2:
+ default:
+ mixin = p->mixin[(i < 2) ? i : (i - 2)];
+ break;
+ case 4:
+ mixin = p->mixin[i];
+ break;
+ };
+ vol = p->vol[i];
+ vortex_mix_setinputvolumebyte(vortex,
+ vortex->mixplayb[i], mixin, vol);
+ }
+ changed = 1;
+ }
+ }
+ return changed;
+}
+
+static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
+
+static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "PCM Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .info = snd_vortex_pcm_vol_info,
+ .get = snd_vortex_pcm_vol_get,
+ .put = snd_vortex_pcm_vol_put,
+ .tlv = { .p = vortex_pcm_vol_db_scale },
+};
+
/* create a pcm device */
static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
{
@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
return err;
}
}
+ if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
+ for (i = 0; i < NR_PCM; i++) {
+ chip->pcm_vol[i].active = 0;
+ chip->pcm_vol[i].dma = -1;
+ kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
+ if (!kctl)
+ return -ENOMEM;
+ chip->pcm_vol[i].kctl = kctl;
+ kctl->id.device = 0;
+ kctl->id.subdevice = i;
+ err = snd_ctl_add(chip->card, kctl);
+ if (err < 0)
+ return err;
+ }
+ }
return 0;
}
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 95ffa6a9db6e..496f14c1a731 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2684,10 +2684,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
goto out_err;
+ opl3->private_data = chip;
}
- opl3->private_data = chip;
-
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, chip->ctrl_io, chip->irq);
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c
index b78f3fc3c33c..6109490b83e8 100644
--- a/sound/pci/ctxfi/ctvmem.c
+++ b/sound/pci/ctxfi/ctvmem.c
@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
size = CT_PAGE_ALIGN(size);
if (size > vm->size) {
- printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural "
+ printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual "
"memory space available!\n");
return NULL;
}
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c
deleted file mode 100644
index 3b5170b9700f..000000000000
--- a/sound/pci/hda/alc260_quirks.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * ALC260 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC260 models */
-enum {
- ALC260_AUTO,
- ALC260_BASIC,
- ALC260_FUJITSU_S702X,
- ALC260_ACER,
- ALC260_WILL,
- ALC260_REPLACER_672V,
- ALC260_FAVORIT100,
-#ifdef CONFIG_SND_DEBUG
- ALC260_TEST,
-#endif
- ALC260_MODEL_LAST /* last tag */
-};
-
-static const hda_nid_t alc260_dac_nids[1] = {
- /* front */
- 0x02,
-};
-
-static const hda_nid_t alc260_adc_nids[1] = {
- /* ADC0 */
- 0x04,
-};
-
-static const hda_nid_t alc260_adc_nids_alt[1] = {
- /* ADC1 */
- 0x05,
-};
-
-/* NIDs used when simultaneous access to both ADCs makes sense. Note that
- * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
- */
-static const hda_nid_t alc260_dual_adc_nids[2] = {
- /* ADC0, ADC1 */
- 0x04, 0x05
-};
-
-#define ALC260_DIGOUT_NID 0x03
-#define ALC260_DIGIN_NID 0x06
-
-static const struct hda_input_mux alc260_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines since these are the only pins at
- * which audio can appear. For flexibility, also allow the option of
- * recording the mixer output on the second ADC (ADC0 doesn't have a
- * connection to the mixer output).
- */
-static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
- {
- .num_items = 3,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
- },
- },
- {
- .num_items = 4,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
- { "Mixer", 0x5 },
- },
- },
-
-};
-
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
- * the Fujitsu S702x, but jacks are marked differently.
- */
-static const struct hda_input_mux alc260_acer_capture_sources[2] = {
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Headphone", 0x5 },
- },
- },
- {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Headphone", 0x6 },
- { "Mixer", 0x5 },
- },
- },
-};
-
-/* Maxdata Favorit 100XS */
-static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
- {
- .num_items = 2,
- .items = {
- { "Line/Mic", 0x0 },
- { "CD", 0x4 },
- },
- },
- {
- .num_items = 3,
- .items = {
- { "Line/Mic", 0x0 },
- { "CD", 0x4 },
- { "Mixer", 0x5 },
- },
- },
-};
-
-/*
- * This is just place-holder, so there's something for alc_build_pcms to look
- * at when it calculates the maximum number of channels. ALC260 has no mixer
- * element which allows changing the channel mode, so the verb list is
- * never used.
- */
-static const struct hda_channel_mode alc260_modes[1] = {
- { 2, NULL },
-};
-
-
-/* Mixer combinations
- *
- * basic: base_output + input + pc_beep + capture
- * fujitsu: fujitsu + capture
- * acer: acer + capture
- */
-
-static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc260_input_mixer[] = {
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
- * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
- */
-static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
- { } /* end */
-};
-
-/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
- * versions of the ALC260 don't act on requests to enable mic bias from NID
- * 0x0f (used to drive the headphone jack in these laptops). The ALC260
- * datasheet doesn't mention this restriction. At this stage it's not clear
- * whether this behaviour is intentional or is a hardware bug in chip
- * revisions available in early 2006. Therefore for now allow the
- * "Headphone Jack Mode" control to span all choices, but if it turns out
- * that the lack of mic bias for this NID is intentional we could change the
- * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
- * don't appear to make the mic bias available from the "line" jack, even
- * though the NID used for this jack (0x14) can supply it. The theory is
- * that perhaps Acer have included blocking capacitors between the ALC260
- * and the output jack. If this turns out to be the case for all such
- * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
- * to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * The C20x Tablet series have a mono internal speaker which is controlled
- * via the chip's Mono sum widget and pin complex, so include the necessary
- * controls for such models. On models without a "mono speaker" the control
- * won't do anything.
- */
-static const struct snd_kcontrol_new alc260_acer_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
- HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- { } /* end */
-};
-
-/* Maxdata Favorit 100XS: one output and one input (0x12) jack
- */
-static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- { } /* end */
-};
-
-/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
- * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
- */
-static const struct snd_kcontrol_new alc260_will_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- { } /* end */
-};
-
-/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
- * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
- */
-static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- { } /* end */
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb alc260_init_verbs[] = {
- /* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- /* LINE-2 is used for line-out in rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* select line-out */
- {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LINE-OUT pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* enable HP */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* enable Mono */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* set connection select to line in (default select for this ADC) */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* mute capture amp left and right */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* set connection select to line in (default select for this ADC) */
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* set vol=0 Line-Out mixer amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 HP mixer amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 Mono mixer amp left and right */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* unmute LINE-2 out pin */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
- * Line In 2 = 0x03
- */
- /* mute analog inputs */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* mute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- { }
-};
-
-/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
- * audio = 0x16, internal speaker = 0x10.
- */
-static const struct hda_verb alc260_fujitsu_init_verbs[] = {
- /* Disable all GPIOs */
- {0x01, AC_VERB_SET_GPIO_MASK, 0},
- /* Internal speaker is connected to headphone pin */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Headphone/Line-out jack connects to Line1 pin; make it an output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Ensure all other unused pins are disabled and muted. */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
- * when acting as an output.
- */
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Line1 pin widget output buffer since it starts as an output.
- * If the pin mode is changed by the user the pin mode control will
- * take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute input buffer of pin widget used for Line-in (no equiv
- * mixer ctrl)
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - line
- * in (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do the same for the second ADC: mute capture input amp and
- * set ADC connection to line in (on mic1 pin)
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
- * similar laptops (adapted from Fujitsu init verbs).
- */
-static const struct hda_verb alc260_acer_init_verbs[] = {
- /* On TravelMate laptops, GPIO 0 enables the internal speaker and
- * the headphone jack. Turn this on and rely on the standard mute
- * methods whenever the user wants to turn these outputs off.
- */
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
- /* Internal speaker/Headphone jack is connected to Line-out pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Internal microphone/Mic jack is connected to Mic1 pin */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- /* Line In jack is connected to Line1 pin */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Ensure all other unused pins are disabled and muted. */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
- * bus when acting as outputs.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute Line-out pin widget amp left and right
- * (no equiv mixer ctrl)
- */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Mic1 and Line1 pin widget input buffers since they start as
- * inputs. If the pin mode is changed by the user the pin mode control
- * will take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - mic
- * (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to mic to match ALSA's default state.
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-/* Initialisation sequence for Maxdata Favorit 100XS
- * (adapted from Acer init verbs).
- */
-static const struct hda_verb alc260_favorit100_init_verbs[] = {
- /* GPIO 0 enables the output jack.
- * Turn this on and rely on the standard mute
- * methods whenever the user wants to turn these outputs off.
- */
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
- /* Line/Mic input jack is connected to Mic1 pin */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- /* Ensure all other unused pins are disabled and muted. */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
- * bus when acting as outputs.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute Line-out pin widget amp left and right
- * (no equiv mixer ctrl)
- */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Mic1 and Line1 pin widget input buffers since they start as
- * inputs. If the pin mode is changed by the user the pin mode control
- * will take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - mic
- * (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to mic to match ALSA's default state.
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-static const struct hda_verb alc260_will_verbs[] = {
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
- {}
-};
-
-static const struct hda_verb alc260_replacer_672v_verbs[] = {
- {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
-
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-
- {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc260_replacer_672v_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
- present = snd_hda_jack_detect(codec, 0x0f);
- if (present) {
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 1);
- snd_hda_codec_write_cache(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_HP);
- } else {
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0);
- snd_hda_codec_write_cache(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_OUT);
- }
-}
-
-static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc260_replacer_672v_automute(codec);
-}
-
-static const struct hda_verb alc260_hp_dc7600_verbs[] = {
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/* Test configuration for debugging, modelled after the ALC880 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc260_test_dac_nids[1] = {
- 0x02,
-};
-static const hda_nid_t alc260_test_adc_nids[2] = {
- 0x04, 0x05,
-};
-/* For testing the ALC260, each input MUX needs its own definition since
- * the signal assignments are different. This assumes that the first ADC
- * is NID 0x04.
- */
-static const struct hda_input_mux alc260_test_capture_sources[2] = {
- {
- .num_items = 7,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "LINE-OUT pin", 0x5 },
- { "HP-OUT pin", 0x6 },
- },
- },
- {
- .num_items = 8,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "Mixer", 0x5 },
- { "LINE-OUT pin", 0x6 },
- { "HP-OUT pin", 0x7 },
- },
- },
-};
-static const struct snd_kcontrol_new alc260_test_mixer[] = {
- /* Output driver widgets */
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
-
- /* Modes for retasking pin widgets
- * Note: the ALC260 doesn't seem to act on requests to enable mic
- * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
- * mention this restriction. At this stage it's not clear whether
- * this behaviour is intentional or is a hardware bug in chip
- * revisions available at least up until early 2006. Therefore for
- * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
- * choices, but if it turns out that the lack of mic bias for these
- * NIDs is intentional we could change their modes from
- * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- */
- ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
-
- /* Loopback mixer controls */
- HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
- HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
-
- /* Controls for GPIO pins, assuming they are configured as outputs */
- ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
- ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
- ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
- ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
- /* Switches to allow the digital IO pins to be enabled. The datasheet
- * is ambigious as to which NID is which; testing on laptops which
- * make this output available should provide clarification.
- */
- ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
- ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
-
- /* A switch allowing EAPD to be enabled. Some laptops seem to use
- * this output to turn on an external amplifier.
- */
- ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
- ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
- { } /* end */
-};
-static const struct hda_verb alc260_test_init_verbs[] = {
- /* Enable all GPIOs as outputs with an initial value of 0 */
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
- {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
- /* Enable retasking pins as output, initially without power amp */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* Disable digital (SPDIF) pins initially, but users can enable
- * them via a mixer switch. In the case of SPDIF-out, this initverb
- * payload also sets the generation to 0, output to be in "consumer"
- * PCM format, copyright asserted, no pre-emphasis and no validity
- * control.
- */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
- * OUT1 sum bus when acting as an output.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute retasking pin widget output buffers since the default
- * state appears to be output. As the pin mode is changed by the
- * user the pin mode control will take care of enabling the pin's
- * input/output buffers as needed.
- */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Also unmute the mono-out pin widget */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting (mic1
- * pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do the same for the second ADC: mute capture input amp and
- * set ADC connection to mic1 pin
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-#endif
-
-/*
- * ALC260 configurations
- */
-static const char * const alc260_models[ALC260_MODEL_LAST] = {
- [ALC260_BASIC] = "basic",
- [ALC260_FUJITSU_S702X] = "fujitsu",
- [ALC260_ACER] = "acer",
- [ALC260_WILL] = "will",
- [ALC260_REPLACER_672V] = "replacer",
- [ALC260_FAVORIT100] = "favorit100",
-#ifdef CONFIG_SND_DEBUG
- [ALC260_TEST] = "test",
-#endif
- [ALC260_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc260_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
- SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
- SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
- SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
- SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
- SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
- SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
- SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
- {}
-};
-
-static const struct alc_config_preset alc260_presets[] = {
- [ALC260_BASIC] = {
- .mixers = { alc260_base_output_mixer,
- alc260_input_mixer },
- .init_verbs = { alc260_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- },
- [ALC260_FUJITSU_S702X] = {
- .mixers = { alc260_fujitsu_mixer },
- .init_verbs = { alc260_fujitsu_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
- .input_mux = alc260_fujitsu_capture_sources,
- },
- [ALC260_ACER] = {
- .mixers = { alc260_acer_mixer },
- .init_verbs = { alc260_acer_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
- .input_mux = alc260_acer_capture_sources,
- },
- [ALC260_FAVORIT100] = {
- .mixers = { alc260_favorit100_mixer },
- .init_verbs = { alc260_favorit100_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
- .input_mux = alc260_favorit100_capture_sources,
- },
- [ALC260_WILL] = {
- .mixers = { alc260_will_mixer },
- .init_verbs = { alc260_init_verbs, alc260_will_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
- .adc_nids = alc260_adc_nids,
- .dig_out_nid = ALC260_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- },
- [ALC260_REPLACER_672V] = {
- .mixers = { alc260_replacer_672v_mixer },
- .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
- .adc_nids = alc260_adc_nids,
- .dig_out_nid = ALC260_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- .unsol_event = alc260_replacer_672v_unsol_event,
- .init_hook = alc260_replacer_672v_automute,
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC260_TEST] = {
- .mixers = { alc260_test_mixer },
- .init_verbs = { alc260_test_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
- .dac_nids = alc260_test_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
- .adc_nids = alc260_test_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
- .input_mux = alc260_test_capture_sources,
- },
-#endif
-};
-
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c
deleted file mode 100644
index 501501ef36a9..000000000000
--- a/sound/pci/hda/alc880_quirks.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-/*
- * ALC880 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC880 board config type */
-enum {
- ALC880_AUTO,
- ALC880_3ST,
- ALC880_3ST_DIG,
- ALC880_5ST,
- ALC880_5ST_DIG,
- ALC880_W810,
- ALC880_Z71V,
- ALC880_6ST,
- ALC880_6ST_DIG,
- ALC880_F1734,
- ALC880_ASUS,
- ALC880_ASUS_DIG,
- ALC880_ASUS_W1V,
- ALC880_ASUS_DIG2,
- ALC880_FUJITSU,
- ALC880_UNIWILL_DIG,
- ALC880_UNIWILL,
- ALC880_UNIWILL_P53,
- ALC880_CLEVO,
- ALC880_TCL_S700,
- ALC880_LG,
-#ifdef CONFIG_SND_DEBUG
- ALC880_TEST,
-#endif
- ALC880_MODEL_LAST /* last tag */
-};
-
-/*
- * ALC880 3-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
- * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
- * F-Mic = 0x1b, HP = 0x19
- */
-
-static const hda_nid_t alc880_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x05, 0x04, 0x03
-};
-
-static const hda_nid_t alc880_adc_nids[3] = {
- /* ADC0-2 */
- 0x07, 0x08, 0x09,
-};
-
-/* The datasheet says the node 0x07 is connected from inputs,
- * but it shows zero connection in the real implementation on some devices.
- * Note: this is a 915GAV bug, fixed on 915GLV
- */
-static const hda_nid_t alc880_adc_nids_alt[2] = {
- /* ADC1-2 */
- 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID 0x06
-#define ALC880_DIGIN_NID 0x0a
-#define ALC880_PIN_CD_NID 0x1c
-
-static const struct hda_input_mux alc880_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x3 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* channel source setting (2/6 channel selection for 3-stack) */
-/* 2ch mode */
-static const struct hda_verb alc880_threestack_ch2_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- /* set mic-in to input vref 80%, mute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 6ch mode */
-static const struct hda_verb alc880_threestack_ch6_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- /* set mic-in to output, unmute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc880_threestack_modes[2] = {
- { 2, alc880_threestack_ch2_init },
- { 6, alc880_threestack_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/*
- * ALC880 5-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
- * Side = 0x02 (0xd)
- * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
- * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
- */
-
-/* additional mixers to alc880_three_stack_mixer */
-static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
- { } /* end */
-};
-
-/* channel source setting (6/8 channel selection for 5-stack) */
-/* 6ch mode */
-static const struct hda_verb alc880_fivestack_ch6_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 8ch mode */
-static const struct hda_verb alc880_fivestack_ch8_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc880_fivestack_modes[2] = {
- { 6, alc880_fivestack_ch6_init },
- { 8, alc880_fivestack_ch8_init },
-};
-
-
-/*
- * ALC880 6-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
- * Side = 0x05 (0x0f)
- * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
- * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
- */
-
-static const hda_nid_t alc880_6st_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_6stack_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* fixed 8-channels */
-static const struct hda_channel_mode alc880_sixstack_modes[1] = {
- { 8, NULL },
-};
-
-static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-
-/*
- * ALC880 W810 model
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static const hda_nid_t alc880_w810_dac_nids[3] = {
- /* front, rear/surround, clfe */
- 0x02, 0x03, 0x04
-};
-
-/* fixed 6 channels */
-static const struct hda_channel_mode alc880_w810_modes[1] = {
- { 6, NULL }
-};
-
-/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-
-/*
- * Z710V model
- *
- * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
- * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
- * Line = 0x1a
- */
-
-static const hda_nid_t alc880_z71v_dac_nids[1] = {
- 0x02
-};
-#define ALC880_Z71V_HP_DAC 0x03
-
-/* fixed 2 channels */
-static const struct hda_channel_mode alc880_2_jack_modes[1] = {
- { 2, NULL }
-};
-
-static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-/*
- * ALC880 F1734 model
- *
- * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
- * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
- */
-
-static const hda_nid_t alc880_f1734_dac_nids[1] = {
- 0x03
-};
-#define ALC880_F1734_HP_DAC 0x02
-
-static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_input_mux alc880_f1734_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x1 },
- { "CD", 0x4 },
- },
-};
-
-
-/*
- * ALC880 ASUS model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a
- */
-
-#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
-#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
-
-static const struct snd_kcontrol_new alc880_asus_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/*
- * ALC880 ASUS W1V model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
- */
-
-/* additional mixers to alc880_asus_mixer */
-static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
- HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
- { } /* end */
-};
-
-/* TCL S700 */
-static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-/* Uniwill */
-static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-/*
- * initialize the codec volumes, etc
- */
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc880_volume_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
- * Note: PASD motherboards uses the Line In 2 as the input for front
- * panel mic (mic 2)
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-
- /*
- * Set up output mixers (0x0c - 0x0f)
- */
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- { }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
- /*
- * Set pin mode and muting
- */
- /* set front pin widgets 0x14 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * 5-stack pin configuration:
- * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
- * line-in/side = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
-
- /*
- * Set pin mode and muting
- */
- /* set pin widgets 0x14-0x17 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* unmute pins for output (no gain on this amp) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * W810 pin configuration:
- * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_w810_init_verbs[] = {
- /* hphone/speaker input selector: front DAC */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- { }
-};
-
-/*
- * Z71V pin configuration:
- * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
- */
-static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * 6-stack pin configuration:
- * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
- * f-mic = 0x19, line = 0x1a, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * Uniwill pin configuration:
- * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
- * line = 0x1a
- */
-static const struct hda_verb alc880_uniwill_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
- /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
-
- { }
-};
-
-/*
-* Uniwill P53
-* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
- */
-static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT},
-
- { }
-};
-
-static const struct hda_verb alc880_beep_init_verbs[] = {
- { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
- { }
-};
-
-static void alc880_uniwill_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x16;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc880_uniwill_init_hook(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
- alc88x_simple_mic_automute(codec);
-}
-
-static void alc880_uniwill_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- res >>= 28;
- switch (res) {
- case ALC_MIC_EVENT:
- alc88x_simple_mic_automute(codec);
- break;
- default:
- alc_exec_unsol_event(codec, res);
- break;
- }
-}
-
-static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- alc_exec_unsol_event(codec, res >> 28);
-}
-
-static void alc880_uniwill_p53_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- present = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
- present &= HDA_AMP_VOLMASK;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
- HDA_AMP_VOLMASK, present);
- snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
- HDA_AMP_VOLMASK, present);
-}
-
-static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- res >>= 28;
- if (res == ALC_DCVOL_EVENT)
- alc880_uniwill_p53_dcvol_automute(codec);
- else
- alc_exec_unsol_event(codec, res);
-}
-
-/*
- * F1734 pin configuration:
- * HP = 0x14, speaker-out = 0x15, mic = 0x18
- */
-static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT},
-
- { }
-};
-
-/*
- * ASUS pin configuration:
- * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
- */
-static const struct hda_verb alc880_pin_asus_init_verbs[] = {
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/* Enable GPIO mask and set output */
-#define alc880_gpio1_init_verbs alc_gpio1_init_verbs
-#define alc880_gpio2_init_verbs alc_gpio2_init_verbs
-#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
-
-/* Clevo m520g init */
-static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
- /* headphone output */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* line-out */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line-in */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* CD */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic1 (rear panel) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic2 (front panel) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* headphone */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-
- { }
-};
-
-static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-
- /* Headphone output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Front output*/
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
-
- { }
-};
-
-/*
- * LG m1 express dual
- *
- * Pin assignment:
- * Rear Line-In/Out (blue): 0x14
- * Build-in Mic-In: 0x15
- * Speaker-out: 0x17
- * HP-Out (green): 0x1b
- * Mic-In/Out (red): 0x19
- * SPDIF-Out: 0x1e
- */
-
-/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
-static const hda_nid_t alc880_lg_dac_nids[3] = {
- 0x05, 0x02, 0x03
-};
-
-/* seems analog CD is not working */
-static const struct hda_input_mux alc880_lg_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x5 },
- { "Internal Mic", 0x6 },
- },
-};
-
-/* 2,4,6 channel modes */
-static const struct hda_verb alc880_lg_ch2_init[] = {
- /* set line-in and mic-in to input */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { }
-};
-
-static const struct hda_verb alc880_lg_ch4_init[] = {
- /* set line-in to out and mic-in to input */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { }
-};
-
-static const struct hda_verb alc880_lg_ch6_init[] = {
- /* set line-in and mic-in to output */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { }
-};
-
-static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
- { 2, alc880_lg_ch2_init },
- { 4, alc880_lg_ch4_init },
- { 6, alc880_lg_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_lg_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc880_lg_init_verbs[] = {
- /* set capture source to mic-in */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* mute all amp mixer inputs */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
- /* line-in to input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* built-in mic */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* speaker-out */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* mic-in to input */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* HP-out */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* jack sense */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x17;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_lg_loopbacks[] = {
- { 0x0b, HDA_INPUT, 1 },
- { 0x0b, HDA_INPUT, 6 },
- { 0x0b, HDA_INPUT, 7 },
- { } /* end */
-};
-#endif
-
-/*
- * Test configuration for debugging
- *
- * Almost all inputs/outputs are enabled. I/O pins can be configured via
- * enum controls.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc880_test_dac_nids[4] = {
- 0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_test_capture_source = {
- .num_items = 7,
- .items = {
- { "In-1", 0x0 },
- { "In-2", 0x1 },
- { "In-3", 0x2 },
- { "In-4", 0x3 },
- { "CD", 0x4 },
- { "Front", 0x5 },
- { "Surround", 0x6 },
- },
-};
-
-static const struct hda_channel_mode alc880_test_modes[4] = {
- { 2, NULL },
- { 4, NULL },
- { 6, NULL },
- { 8, NULL },
-};
-
-static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char * const texts[] = {
- "N/A", "Line Out", "HP Out",
- "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item >= 8)
- uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int pin_ctl, item = 0;
-
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pin_ctl & AC_PINCTL_OUT_EN) {
- if (pin_ctl & AC_PINCTL_HP_EN)
- item = 2;
- else
- item = 1;
- } else if (pin_ctl & AC_PINCTL_IN_EN) {
- switch (pin_ctl & AC_PINCTL_VREFEN) {
- case AC_PINCTL_VREF_HIZ: item = 3; break;
- case AC_PINCTL_VREF_50: item = 4; break;
- case AC_PINCTL_VREF_GRD: item = 5; break;
- case AC_PINCTL_VREF_80: item = 6; break;
- case AC_PINCTL_VREF_100: item = 7; break;
- }
- }
- ucontrol->value.enumerated.item[0] = item;
- return 0;
-}
-
-static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- static const unsigned int ctls[] = {
- 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
- };
- unsigned int old_ctl, new_ctl;
-
- old_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- new_ctl = ctls[ucontrol->value.enumerated.item[0]];
- if (old_ctl != new_ctl) {
- int val;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- new_ctl);
- val = ucontrol->value.enumerated.item[0] >= 3 ?
- HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, val);
- return 1;
- }
- return 0;
-}
-
-static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char * const texts[] = {
- "Front", "Surround", "CLFE", "Side"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item >= 4)
- uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
- ucontrol->value.enumerated.item[0] = sel & 3;
- return 0;
-}
-
-static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
- if (ucontrol->value.enumerated.item[0] != sel) {
- sel = ucontrol->value.enumerated.item[0] & 3;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, sel);
- return 1;
- }
- return 0;
-}
-
-#define PIN_CTL_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_test_pin_ctl_info, \
- .get = alc_test_pin_ctl_get, \
- .put = alc_test_pin_ctl_put, \
- .private_value = nid \
- }
-
-#define PIN_SRC_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_test_pin_src_info, \
- .get = alc_test_pin_src_get, \
- .put = alc_test_pin_src_put, \
- .private_value = nid \
- }
-
-static const struct snd_kcontrol_new alc880_test_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- PIN_CTL_TEST("Front Pin Mode", 0x14),
- PIN_CTL_TEST("Surround Pin Mode", 0x15),
- PIN_CTL_TEST("CLFE Pin Mode", 0x16),
- PIN_CTL_TEST("Side Pin Mode", 0x17),
- PIN_CTL_TEST("In-1 Pin Mode", 0x18),
- PIN_CTL_TEST("In-2 Pin Mode", 0x19),
- PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
- PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
- PIN_SRC_TEST("In-1 Pin Source", 0x18),
- PIN_SRC_TEST("In-2 Pin Source", 0x19),
- PIN_SRC_TEST("In-3 Pin Source", 0x1a),
- PIN_SRC_TEST("In-4 Pin Source", 0x1b),
- HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc880_test_init_verbs[] = {
- /* Unmute inputs of 0x0c - 0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Vol output for 0x0c-0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* Set output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* Unmute output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Set input pins 0x18-0x1c */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mute input pins 0x18-0x1b */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* ADC set up */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Analog input/passthru */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- { }
-};
-#endif
-
-/*
- */
-
-static const char * const alc880_models[ALC880_MODEL_LAST] = {
- [ALC880_3ST] = "3stack",
- [ALC880_TCL_S700] = "tcl",
- [ALC880_3ST_DIG] = "3stack-digout",
- [ALC880_CLEVO] = "clevo",
- [ALC880_5ST] = "5stack",
- [ALC880_5ST_DIG] = "5stack-digout",
- [ALC880_W810] = "w810",
- [ALC880_Z71V] = "z71v",
- [ALC880_6ST] = "6stack",
- [ALC880_6ST_DIG] = "6stack-digout",
- [ALC880_ASUS] = "asus",
- [ALC880_ASUS_W1V] = "asus-w1v",
- [ALC880_ASUS_DIG] = "asus-dig",
- [ALC880_ASUS_DIG2] = "asus-dig2",
- [ALC880_UNIWILL_DIG] = "uniwill",
- [ALC880_UNIWILL_P53] = "uniwill-p53",
- [ALC880_FUJITSU] = "fujitsu",
- [ALC880_F1734] = "F1734",
- [ALC880_LG] = "lg",
-#ifdef CONFIG_SND_DEBUG
- [ALC880_TEST] = "test",
-#endif
- [ALC880_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc880_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
- SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
- SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
- SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
- SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
- /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
- SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
- SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
- SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
- SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
- SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
- SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
- SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
- SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
- SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
- SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
- SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
- SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
- SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
- SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
- SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
- SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
- SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
- SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
- SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
- SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
- SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
- SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
- SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
- /* default Intel */
- SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
- SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
- {}
-};
-
-/*
- * ALC880 codec presets
- */
-static const struct alc_config_preset alc880_presets[] = {
- [ALC880_3ST] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_3ST_DIG] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_TCL_S700] = {
- .mixers = { alc880_tcl_s700_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_tcl_S700_init_verbs,
- alc880_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
- .num_adc_nids = 1, /* single ADC */
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST] = {
- .mixers = { alc880_three_stack_mixer,
- alc880_five_stack_mixer},
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST_DIG] = {
- .mixers = { alc880_three_stack_mixer,
- alc880_five_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_6ST] = {
- .mixers = { alc880_six_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
- .dac_nids = alc880_6st_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
- .channel_mode = alc880_sixstack_modes,
- .input_mux = &alc880_6stack_capture_source,
- },
- [ALC880_6ST_DIG] = {
- .mixers = { alc880_six_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
- .dac_nids = alc880_6st_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
- .channel_mode = alc880_sixstack_modes,
- .input_mux = &alc880_6stack_capture_source,
- },
- [ALC880_W810] = {
- .mixers = { alc880_w810_base_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_w810_init_verbs,
- alc880_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
- .dac_nids = alc880_w810_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
- .channel_mode = alc880_w810_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_Z71V] = {
- .mixers = { alc880_z71v_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_z71v_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
- .dac_nids = alc880_z71v_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_F1734] = {
- .mixers = { alc880_f1734_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_f1734_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
- .dac_nids = alc880_f1734_dac_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_f1734_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_ASUS] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_DIG2] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio2_init_verbs }, /* use GPIO2 */
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_W1V] = {
- .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_UNIWILL_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_UNIWILL] = {
- .mixers = { alc880_uniwill_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_unsol_event,
- .setup = alc880_uniwill_setup,
- .init_hook = alc880_uniwill_init_hook,
- },
- [ALC880_UNIWILL_P53] = {
- .mixers = { alc880_uniwill_p53_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_p53_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
- .channel_mode = alc880_threestack_modes,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_FUJITSU] = {
- .mixers = { alc880_fujitsu_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_p53_init_verbs,
- alc880_beep_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_CLEVO] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_clevo_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_LG] = {
- .mixers = { alc880_lg_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_lg_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
- .dac_nids = alc880_lg_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
- .channel_mode = alc880_lg_ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_lg_capture_source,
- .unsol_event = alc880_unsol_event,
- .setup = alc880_lg_setup,
- .init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- .loopbacks = alc880_lg_loopbacks,
-#endif
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC880_TEST] = {
- .mixers = { alc880_test_mixer },
- .init_verbs = { alc880_test_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
- .dac_nids = alc880_test_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
- .channel_mode = alc880_test_modes,
- .input_mux = &alc880_test_capture_source,
- },
-#endif
-};
-
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c
deleted file mode 100644
index bb364a53f546..000000000000
--- a/sound/pci/hda/alc882_quirks.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * ALC882/ALC883/ALC888/ALC889 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC882 models */
-enum {
- ALC882_AUTO,
- ALC885_MBA21,
- ALC885_MBP3,
- ALC885_MB5,
- ALC885_MACMINI3,
- ALC885_IMAC91,
- ALC889A_MB31,
- ALC882_MODEL_LAST,
-};
-
-#define ALC882_DIGOUT_NID 0x06
-#define ALC882_DIGIN_NID 0x0a
-#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
-#define ALC883_DIGIN_NID ALC882_DIGIN_NID
-#define ALC1200_DIGOUT_NID 0x10
-
-
-static const struct hda_channel_mode alc882_ch_modes[1] = {
- { 8, NULL }
-};
-
-/* DACs */
-static const hda_nid_t alc882_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x03, 0x04, 0x05
-};
-#define alc883_dac_nids alc882_dac_nids
-
-/* ADCs */
-#define alc882_adc_nids alc880_adc_nids
-#define alc882_adc_nids_alt alc880_adc_nids_alt
-#define alc883_adc_nids alc882_adc_nids_alt
-
-static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
-#define alc883_capsrc_nids alc882_capsrc_nids_alt
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-
-static const struct hda_input_mux alc882_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-#define alc883_capture_source alc882_capture_source
-
-static const struct hda_input_mux mb5_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x7 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux macmini3_capture_source = {
- .num_items = 2,
- .items = {
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc883_3stack_6ch_intel = {
- .num_items = 4,
- .items = {
- { "Mic", 0x1 },
- { "Front Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc889A_mb31_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- /* Front Mic (0x01) unused */
- { "Line", 0x2 },
- /* Line 2 (0x03) unused */
- /* CD (0x04) unused? */
- },
-};
-
-static const struct hda_input_mux alc889A_imac91_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x01 },
- { "Line", 0x2 }, /* Not sure! */
- },
-};
-
-/* Macbook Air 2,1 */
-
-static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
- { 2, NULL },
-};
-
-/*
- * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
- */
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc885_mbp_ch2_init[] = {
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc885_mbp_ch4_init[] = {
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- { } /* end */
-};
-
-static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
- { 2, alc885_mbp_ch2_init },
- { 4, alc885_mbp_ch4_init },
-};
-
-/*
- * 2ch
- * Speakers/Woofer/HP = Front
- * LineIn = Input
- */
-static const struct hda_verb alc885_mb5_ch2_init[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- { } /* end */
-};
-
-/*
- * 6ch mode
- * Speakers/HP = Front
- * Woofer = LFE
- * LineIn = Surround
- */
-static const struct hda_verb alc885_mb5_ch6_init[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- { } /* end */
-};
-
-static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
- { 2, alc885_mb5_ch2_init },
- { 6, alc885_mb5_ch6_init },
-};
-
-#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
-
-/* Macbook Air 2,1 same control for HP and internal Speaker */
-
-static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
- { }
-};
-
-
-static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
- { } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc882_base_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* CLFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Side mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Rear Pin: output 1 (0x0d) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin: output 3 (0x0f) */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- { }
-};
-
-#define alc883_init_verbs alc882_base_init_verbs
-
-/* Macbook 5,1 */
-static const struct hda_verb alc885_mb5_init_verbs[] = {
- /* DACs */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Front mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Surround mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* LFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LFE Pin (0x0e) */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* HP Pin (0x0f) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
- { }
-};
-
-/* Macmini 3,1 */
-static const struct hda_verb alc885_macmini3_init_verbs[] = {
- /* DACs */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Front mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Surround mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* LFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LFE Pin (0x0e) */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* HP Pin (0x0f) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Line In pin */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- { }
-};
-
-
-static const struct hda_verb alc885_mba21_init_verbs[] = {
- /*Internal and HP Speaker Mixer*/
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /*Internal Speaker Pin (0x0c)*/
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0e) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
- /* Line in (is hp when jack connected)*/
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- { }
- };
-
-
-/* Macbook Pro rev3 */
-static const struct hda_verb alc885_mbp3_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0e) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: use output 1 when in LineOut mode */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* ADC1: mute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- { }
-};
-
-/* iMac 9,1 */
-static const struct hda_verb alc885_imac91_init_verbs[] = {
- /* Internal Speaker Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: Rear */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
- /* Line in Rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- { }
-};
-
-/* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- spec->autocfg.speaker_pins[1] = 0x1a;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-#define alc885_mb5_setup alc885_imac24_setup
-#define alc885_macmini3_setup alc885_imac24_setup
-
-/* Macbook Air 2,1 */
-static void alc885_mba21_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-
-
-static void alc885_mbp3_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc885_imac91_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- spec->autocfg.speaker_pins[1] = 0x1a;
- alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch2_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
- { } /* end */
-};
-
-/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch4_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
- { } /* end */
-};
-
-/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
-static const struct hda_verb alc889A_mb31_ch5_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
- { } /* end */
-};
-
-/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
-static const struct hda_verb alc889A_mb31_ch6_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
- { } /* end */
-};
-
-static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
- { 2, alc889A_mb31_ch2_init },
- { 4, alc889A_mb31_ch4_init },
- { 5, alc889A_mb31_ch5_init },
- { 6, alc889A_mb31_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
- /* Output mixers */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
- /* Output switches */
- HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
- HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
- /* Boost mixers */
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
- /* Input mixers */
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc889A_mb31_verbs[] = {
- /* Init rear pin (used as headphone output) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Init line pin (used as output in 4ch and 6ch mode) */
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
- /* Init line 2 pin (used as headphone out by default) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
- { } /* end */
-};
-
-/* Mute speakers according to the headphone jack state */
-static void alc889A_mb31_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- /* Mute only in 2ch or 4ch mode */
- if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
- == 0x00) {
- present = snd_hda_jack_detect(codec, 0x15);
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- }
-}
-
-static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc889A_mb31_automute(codec);
-}
-
-static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- alc_exec_unsol_event(codec, res >> 26);
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc882_models[ALC882_MODEL_LAST] = {
- [ALC885_MB5] = "mb5",
- [ALC885_MACMINI3] = "macmini3",
- [ALC885_MBA21] = "mba21",
- [ALC885_MBP3] = "mbp3",
- [ALC885_IMAC91] = "imac91",
- [ALC889A_MB31] = "mb31",
- [ALC882_AUTO] = "auto",
-};
-
-/* codec SSID table for Intel Mac */
-static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
- SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
- SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
- SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
- SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
- SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
- /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
- * so apparently no perfect solution yet
- */
- SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
- {} /* terminator */
-};
-
-static const struct alc_config_preset alc882_presets[] = {
- [ALC885_MBA21] = {
- .mixers = { alc885_mba21_mixer },
- .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
- .num_dacs = 2,
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mba21_ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
- .input_mux = &alc882_capture_source,
- .unsol_event = alc882_unsol_event,
- .setup = alc885_mba21_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MBP3] = {
- .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_mbp3_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = 2,
- .dac_nids = alc882_dac_nids,
- .hp_nid = 0x04,
- .channel_mode = alc885_mbp_4ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
- .input_mux = &alc882_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc882_unsol_event,
- .setup = alc885_mbp3_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MB5] = {
- .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_mb5_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mb5_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
- .input_mux = &mb5_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc882_unsol_event,
- .setup = alc885_mb5_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MACMINI3] = {
- .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_macmini3_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_macmini3_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
- .input_mux = &macmini3_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc882_unsol_event,
- .setup = alc885_macmini3_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_IMAC91] = {
- .mixers = {alc885_imac91_mixer},
- .init_verbs = { alc885_imac91_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mba21_ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
- .input_mux = &alc889A_imac91_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc882_unsol_event,
- .setup = alc885_imac91_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC889A_MB31] = {
- .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
- .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
- alc880_gpio1_init_verbs },
- .adc_nids = alc883_adc_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
- .capsrc_nids = alc883_capsrc_nids,
- .dac_nids = alc883_dac_nids,
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .channel_mode = alc889A_mb31_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
- .input_mux = &alc889A_mb31_capture_source,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .unsol_event = alc889A_mb31_unsol_event,
- .init_hook = alc889A_mb31_automute,
- },
-};
-
-
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c
deleted file mode 100644
index a18952ed4311..000000000000
--- a/sound/pci/hda/alc_quirks.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Common codes for Realtek codec quirks
- * included by patch_realtek.c
- */
-
-/*
- * configuration template - to be copied to the spec instance
- */
-struct alc_config_preset {
- const struct snd_kcontrol_new *mixers[5]; /* should be identical size
- * with spec
- */
- const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
- const struct hda_verb *init_verbs[5];
- unsigned int num_dacs;
- const hda_nid_t *dac_nids;
- hda_nid_t dig_out_nid; /* optional */
- hda_nid_t hp_nid; /* optional */
- const hda_nid_t *slave_dig_outs;
- unsigned int num_adc_nids;
- const hda_nid_t *adc_nids;
- const hda_nid_t *capsrc_nids;
- hda_nid_t dig_in_nid;
- unsigned int num_channel_mode;
- const struct hda_channel_mode *channel_mode;
- int need_dac_fix;
- int const_channel_count;
- unsigned int num_mux_defs;
- const struct hda_input_mux *input_mux;
- void (*unsol_event)(struct hda_codec *, unsigned int);
- void (*setup)(struct hda_codec *);
- void (*init_hook)(struct hda_codec *);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- const struct hda_amp_list *loopbacks;
- void (*power_hook)(struct hda_codec *codec);
-#endif
-};
-
-/*
- * channel mode setting
- */
-static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
- spec->num_channel_mode);
-}
-
-static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
- spec->num_channel_mode,
- spec->ext_channel_count);
-}
-
-static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
- spec->num_channel_mode,
- &spec->ext_channel_count);
- if (err >= 0 && !spec->const_channel_count) {
- spec->multiout.max_channels = spec->ext_channel_count;
- if (spec->need_dac_fix)
- spec->multiout.num_dacs = spec->multiout.max_channels / 2;
- }
- return err;
-}
-
-/*
- * Control the mode of pin widget settings via the mixer. "pc" is used
- * instead of "%" to avoid consequences of accidentally treating the % as
- * being part of a format specifier. Maximum allowed length of a value is
- * 63 characters plus NULL terminator.
- *
- * Note: some retasking pin complexes seem to ignore requests for input
- * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
- * are requested. Therefore order this list so that this behaviour will not
- * cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
- * March 2006.
- */
-static const char * const alc_pin_mode_names[] = {
- "Mic 50pc bias", "Mic 80pc bias",
- "Line in", "Line out", "Headphone out",
-};
-static const unsigned char alc_pin_mode_values[] = {
- PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
-};
-/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin. In
- * addition, "input" pins may or may not process the mic bias option
- * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
- * accept requests for bias as of chip versions up to March 2006) and/or
- * wiring in the computer.
- */
-#define ALC_PIN_DIR_IN 0x00
-#define ALC_PIN_DIR_OUT 0x01
-#define ALC_PIN_DIR_INOUT 0x02
-#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
-#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-/* Info about the pin modes supported by the different pin direction modes.
- * For each direction the minimum and maximum values are given.
- */
-static const signed char alc_pin_mode_dir_info[5][2] = {
- { 0, 2 }, /* ALC_PIN_DIR_IN */
- { 3, 4 }, /* ALC_PIN_DIR_OUT */
- { 0, 4 }, /* ALC_PIN_DIR_INOUT */
- { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
- { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
-};
-#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
-#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
-#define alc_pin_mode_n_items(_dir) \
- (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
-
-static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int item_num = uinfo->value.enumerated.item;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
-
- if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
- item_num = alc_pin_mode_min(dir);
- strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
- return 0;
-}
-
-static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- unsigned int i;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
-
- /* Find enumerated value for current pinctl setting */
- i = alc_pin_mode_min(dir);
- while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
- i++;
- *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
- return 0;
-}
-
-static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
-
- if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
- val = alc_pin_mode_min(dir);
-
- change = pinctl != alc_pin_mode_values[val];
- if (change) {
- /* Set pin mode to that requested */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- alc_pin_mode_values[val]);
-
- /* Also enable the retasking pin's input/output as required
- * for the requested pin mode. Enum values of 2 or less are
- * input modes.
- *
- * Dynamically switching the input/output buffers probably
- * reduces noise slightly (particularly on input) so we'll
- * do it. However, having both input and output buffers
- * enabled simultaneously doesn't seem to be problematic if
- * this turns out to be necessary in the future.
- */
- if (val <= 2) {
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
- HDA_AMP_MUTE, 0);
- } else {
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, 0);
- }
- }
- return change;
-}
-
-#define ALC_PIN_MODE(xname, nid, dir) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_pin_mode_info, \
- .get = alc_pin_mode_get, \
- .put = alc_pin_mode_put, \
- .private_value = nid | (dir<<16) }
-
-/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
- * together using a mask with more than one bit set. This control is
- * currently used only by the ALC260 test model. At this stage they are not
- * needed for any "production" models.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_gpio_data_info snd_ctl_boolean_mono_info
-
-static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DATA, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DATA,
- 0x00);
-
- /* Set/unset the masked GPIO bit(s) as needed */
- change = (val == 0 ? 0 : mask) != (gpio_data & mask);
- if (val == 0)
- gpio_data &= ~mask;
- else
- gpio_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_GPIO_DATA, gpio_data);
-
- return change;
-}
-#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_gpio_data_info, \
- .get = alc_gpio_data_get, \
- .put = alc_gpio_data_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling of the digital IO pins on the
- * ALC260. This is incredibly simplistic; the intention of this control is
- * to provide something in the test model allowing digital outputs to be
- * identified if present. If models are found which can utilise these
- * outputs a more complete mixer control can be devised for those models if
- * necessary.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
-
-static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1,
- 0x00);
-
- /* Set/unset the masked control bit(s) as needed */
- change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
- if (val==0)
- ctrl_data &= ~mask;
- else
- ctrl_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- ctrl_data);
-
- return change;
-}
-#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_spdif_ctrl_info, \
- .get = alc_spdif_ctrl_get, \
- .put = alc_spdif_ctrl_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
- * Again, this is only used in the ALC26x test models to help identify when
- * the EAPD line must be asserted for features to work.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
-
-static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-
-static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE,
- 0x00);
-
- /* Set/unset the masked control bit(s) as needed */
- change = (!val ? 0 : mask) != (ctrl_data & mask);
- if (!val)
- ctrl_data &= ~mask;
- else
- ctrl_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
- ctrl_data);
-
- return change;
-}
-
-#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_eapd_ctrl_info, \
- .get = alc_eapd_ctrl_get, \
- .put = alc_eapd_ctrl_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-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++;
- }
-}
-
-/*
- * set up from the preset table
- */
-static void setup_preset(struct hda_codec *codec,
- const struct alc_config_preset *preset)
-{
- struct alc_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
- add_mixer(spec, preset->mixers[i]);
- spec->cap_mixer = preset->cap_mixer;
- for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
- i++)
- add_verb(spec, preset->init_verbs[i]);
-
- spec->channel_mode = preset->channel_mode;
- spec->num_channel_mode = preset->num_channel_mode;
- spec->need_dac_fix = preset->need_dac_fix;
- spec->const_channel_count = preset->const_channel_count;
-
- if (preset->const_channel_count)
- spec->multiout.max_channels = preset->const_channel_count;
- else
- spec->multiout.max_channels = spec->channel_mode[0].channels;
- spec->ext_channel_count = spec->channel_mode[0].channels;
-
- spec->multiout.num_dacs = preset->num_dacs;
- spec->multiout.dac_nids = preset->dac_nids;
- spec->multiout.dig_out_nid = preset->dig_out_nid;
- spec->multiout.slave_dig_outs = preset->slave_dig_outs;
- spec->multiout.hp_nid = preset->hp_nid;
-
- spec->num_mux_defs = preset->num_mux_defs;
- if (!spec->num_mux_defs)
- spec->num_mux_defs = 1;
- spec->input_mux = preset->input_mux;
-
- spec->num_adc_nids = preset->num_adc_nids;
- spec->adc_nids = preset->adc_nids;
- spec->capsrc_nids = preset->capsrc_nids;
- spec->dig_in_nid = preset->dig_in_nid;
-
- spec->unsol_event = preset->unsol_event;
- spec->init_hook = preset->init_hook;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- spec->power_hook = preset->power_hook;
- spec->loopback.amplist = preset->loopbacks;
-#endif
-
- if (preset->setup)
- preset->setup(codec);
-
- alc_fixup_autocfg_pin_nums(codec);
-}
-
-static void alc_simple_setup_automute(struct alc_spec *spec, int mode)
-{
- int lo_pin = spec->autocfg.line_out_pins[0];
-
- if (lo_pin == spec->autocfg.speaker_pins[0] ||
- lo_pin == spec->autocfg.hp_pins[0])
- lo_pin = 0;
- spec->automute_mode = mode;
- spec->detect_hp = !!spec->autocfg.hp_pins[0];
- spec->detect_lo = !!lo_pin;
- spec->automute_lo = spec->automute_lo_possible = !!lo_pin;
- spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0];
-}
-
-/* auto-toggle front mic */
-static void alc88x_simple_mic_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x18);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
-}
-
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4df72c0e8c37..7a8fcc4c15f8 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -1447,7 +1448,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
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 &&
- get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+ get_wcaps_type(get_wcaps(c, p->nid)) == type)
p->dirty = 1;
}
}
@@ -1759,7 +1760,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
parm |= index << AC_AMP_SET_INDEX_SHIFT;
- parm |= val;
+ if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) &&
+ (info->amp_caps & AC_AMPCAP_MIN_MUTE))
+ ; /* set the zero value as a fake mute */
+ else
+ parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val;
}
@@ -2026,7 +2031,7 @@ 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)
+ if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
return -EFAULT;
@@ -2300,7 +2305,7 @@ typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
/* apply the function to all matching slave ctls in the mixer list */
static int map_slaves(struct hda_codec *codec, const char * const *slaves,
- map_slave_func_t func, void *data)
+ const char *suffix, map_slave_func_t func, void *data)
{
struct hda_nid_item *items;
const char * const *s;
@@ -2313,7 +2318,14 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
continue;
for (s = slaves; *s; s++) {
- if (!strcmp(sctl->id.name, *s)) {
+ char tmpname[sizeof(sctl->id.name)];
+ const char *name = *s;
+ if (suffix) {
+ snprintf(tmpname, sizeof(tmpname), "%s %s",
+ name, suffix);
+ name = tmpname;
+ }
+ if (!strcmp(sctl->id.name, name)) {
err = func(data, sctl);
if (err)
return err;
@@ -2329,12 +2341,65 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl)
return 1;
}
+/* guess the value corresponding to 0dB */
+static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
+{
+ int _tlv[4];
+ const int *tlv = NULL;
+ int val = -1;
+
+ if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ /* FIXME: set_fs() hack for obtaining user-space TLV data */
+ mm_segment_t fs = get_fs();
+ set_fs(get_ds());
+ if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
+ tlv = _tlv;
+ set_fs(fs);
+ } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
+ tlv = kctl->tlv.p;
+ if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
+ val = -tlv[2] / tlv[3];
+ return val;
+}
+
+/* call kctl->put with the given value(s) */
+static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
+{
+ struct snd_ctl_elem_value *ucontrol;
+ ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
+ if (!ucontrol)
+ return -ENOMEM;
+ ucontrol->value.integer.value[0] = val;
+ ucontrol->value.integer.value[1] = val;
+ kctl->put(kctl, ucontrol);
+ kfree(ucontrol);
+ return 0;
+}
+
+/* initialize the slave volume with 0dB */
+static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+{
+ int offset = get_kctl_0dB_offset(slave);
+ if (offset > 0)
+ put_kctl_with_value(slave, offset);
+ return 0;
+}
+
+/* unmute the slave */
+static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+{
+ return put_kctl_with_value(slave, 1);
+}
+
/**
* snd_hda_add_vmaster - create a virtual master control and add slaves
* @codec: HD-audio codec
* @name: vmaster control name
* @tlv: TLV data (optional)
* @slaves: slave control names (optional)
+ * @suffix: suffix string to each slave name (optional)
+ * @init_slave_vol: initialize slaves to unmute/0dB
+ * @ctl_ret: store the vmaster kcontrol in return
*
* Create a virtual master control with the given name. The TLV data
* must be either NULL or a valid data.
@@ -2345,13 +2410,18 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl)
*
* This function returns zero if successful or a negative error code.
*/
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *slaves)
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ unsigned int *tlv, const char * const *slaves,
+ const char *suffix, bool init_slave_vol,
+ struct snd_kcontrol **ctl_ret)
{
struct snd_kcontrol *kctl;
int err;
- err = map_slaves(codec, slaves, check_slave_present, NULL);
+ if (ctl_ret)
+ *ctl_ret = NULL;
+
+ err = map_slaves(codec, slaves, suffix, check_slave_present, NULL);
if (err != 1) {
snd_printdd("No slave found for %s\n", name);
return 0;
@@ -2363,13 +2433,119 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
if (err < 0)
return err;
- err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave,
- kctl);
+ err = map_slaves(codec, slaves, suffix,
+ (map_slave_func_t)snd_ctl_add_slave, kctl);
if (err < 0)
return err;
+
+ /* init with master mute & zero volume */
+ put_kctl_with_value(kctl, 0);
+ if (init_slave_vol)
+ map_slaves(codec, slaves, suffix,
+ tlv ? init_slave_0dB : init_slave_unmute, kctl);
+
+ if (ctl_ret)
+ *ctl_ret = kctl;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+
+/*
+ * mute-LED control using vmaster
+ */
+static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char * const texts[] = {
+ "Off", "On", "Follow Master"
+ };
+ unsigned int index;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ index = uinfo->value.enumerated.item;
+ if (index >= 3)
+ index = 2;
+ strcpy(uinfo->value.enumerated.name, texts[index]);
+ return 0;
+}
+
+static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = hook->mute_mode;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
+
+static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+ unsigned int old_mode = hook->mute_mode;
+
+ hook->mute_mode = ucontrol->value.enumerated.item[0];
+ if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
+ hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+ if (old_mode == hook->mute_mode)
+ return 0;
+ snd_hda_sync_vmaster_hook(hook);
+ return 1;
+}
+
+static struct snd_kcontrol_new vmaster_mute_mode = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mute-LED Mode",
+ .info = vmaster_mute_mode_info,
+ .get = vmaster_mute_mode_get,
+ .put = vmaster_mute_mode_put,
+};
+
+/*
+ * Add a mute-LED hook with the given vmaster switch kctl
+ * "Mute-LED Mode" control is automatically created and associated with
+ * the given hook.
+ */
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+ struct hda_vmaster_mute_hook *hook,
+ bool expose_enum_ctl)
+{
+ struct snd_kcontrol *kctl;
+
+ if (!hook->hook || !hook->sw_kctl)
+ return 0;
+ snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
+ hook->codec = codec;
+ hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+ if (!expose_enum_ctl)
+ return 0;
+ kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
+ if (!kctl)
+ return -ENOMEM;
+ return snd_hda_ctl_add(codec, 0, kctl);
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+
+/*
+ * Call the hook with the current value for synchronization
+ * Should be called in init callback
+ */
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
+{
+ if (!hook->hook || !hook->codec)
+ return;
+ switch (hook->mute_mode) {
+ case HDA_VMUTE_FOLLOW_MASTER:
+ snd_ctl_sync_vmaster_hook(hook->sw_kctl);
+ break;
+ default:
+ hook->hook(hook->codec, hook->mute_mode);
+ break;
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+
/**
* snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
@@ -5114,7 +5290,7 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
const char *pfx = "", *sfx = "";
/* handle as a speaker if it's a fixed line-out */
- if (!strcmp(name, "Line-Out") && attr == INPUT_PIN_ATTR_INT)
+ if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
name = "Speaker";
/* check the location */
switch (attr) {
@@ -5173,7 +5349,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
switch (get_defcfg_device(def_conf)) {
case AC_JACK_LINE_OUT:
- return fill_audio_out_name(codec, nid, cfg, "Line-Out",
+ return fill_audio_out_name(codec, nid, cfg, "Line Out",
label, maxlen, indexp);
case AC_JACK_SPEAKER:
return fill_audio_out_name(codec, nid, cfg, "Speaker",
@@ -5268,6 +5444,10 @@ int snd_hda_suspend(struct hda_bus *bus)
list_for_each_entry(codec, &bus->codec_list, list) {
if (hda_codec_is_power_on(codec))
hda_call_codec_suspend(codec);
+ else /* forcibly change the power to D3 even if not used */
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D3);
if (codec->patch_ops.post_suspend)
codec->patch_ops.post_suspend(codec);
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index e9f71dc0d464..9a9f372e1be4 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -298,6 +298,9 @@ enum {
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
+/* driver-specific amp-caps: using bits 24-30 */
+#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
+
/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
@@ -852,6 +855,7 @@ struct hda_codec {
unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
+ unsigned int no_jack_detect:1; /* Machine has no jack-detection */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
unsigned int power_transition :1; /* power-state in transition */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index c1da422e085a..b58b4b1687fa 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -385,8 +385,8 @@ error:
static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
{
static unsigned int alsa_rates[] = {
- 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
- 96000, 176400, 192000, 384000
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+ 88200, 96000, 176400, 192000, 384000
};
int i, j;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 95dfb6874941..c19e71a94e1b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -84,7 +84,7 @@ 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, "DMA pointer read method."
- "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
+ "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO).");
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);
@@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
module_param(single_cmd, bool, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only).");
-module_param(enable_msi, int, 0444);
+module_param(enable_msi, bint, 0444);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
#ifdef CONFIG_SND_HDA_PATCH_LOADER
module_param_array(patch, charp, NULL, 0444);
@@ -121,8 +121,8 @@ module_param(power_save_controller, bool, 0644);
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
#endif
-static bool align_buffer_size = 1;
-module_param(align_buffer_size, bool, 0644);
+static int align_buffer_size = -1;
+module_param(align_buffer_size, bint, 0644);
MODULE_PARM_DESC(align_buffer_size,
"Force buffer and period sizes to be multiple of 128 bytes.");
@@ -148,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, PCH},"
"{Intel, CPT},"
"{Intel, PPT},"
+ "{Intel, LPT},"
"{Intel, PBG},"
"{Intel, SCH},"
"{ATI, SB450},"
@@ -329,6 +330,7 @@ enum {
POS_FIX_LPIB,
POS_FIX_POSBUF,
POS_FIX_VIACOMBO,
+ POS_FIX_COMBO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -515,6 +517,7 @@ enum {
#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
+#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -527,7 +530,8 @@ enum {
/* quirks for Nvidia */
#define AZX_DCAPS_PRESET_NVIDIA \
- (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI)
+ (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
+ AZX_DCAPS_ALIGN_BUFSIZE)
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
@@ -2347,17 +2351,6 @@ static void azx_power_notify(struct hda_bus *bus)
* power management
*/
-static int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
- struct hda_codec *codec;
-
- list_for_each_entry(codec, &bus->codec_list, list) {
- if (snd_hda_codec_needs_resume(codec))
- return 1;
- }
- return 0;
-}
-
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
@@ -2404,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci)
return -EIO;
azx_init_pci(chip);
- if (snd_hda_codecs_inuse(chip->bus))
- azx_init_chip(chip, 1);
+ azx_init_chip(chip, 1);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2517,6 +2509,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
case POS_FIX_LPIB:
case POS_FIX_POSBUF:
case POS_FIX_VIACOMBO:
+ case POS_FIX_COMBO:
return fix;
}
@@ -2696,6 +2689,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->position_fix[0] = chip->position_fix[1] =
check_position_fix(chip, position_fix[dev]);
+ /* combo mode uses LPIB for playback */
+ if (chip->position_fix[0] == POS_FIX_COMBO) {
+ chip->position_fix[0] = POS_FIX_LPIB;
+ chip->position_fix[1] = POS_FIX_AUTO;
+ }
+
check_probe_mask(chip, dev);
chip->single_cmd = single_cmd;
@@ -2774,9 +2773,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
}
/* disable buffer size rounding to 128-byte multiples if supported */
- chip->align_buffer_size = align_buffer_size;
- if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
- chip->align_buffer_size = 0;
+ if (align_buffer_size >= 0)
+ chip->align_buffer_size = !!align_buffer_size;
+ else {
+ if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
+ chip->align_buffer_size = 0;
+ else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE)
+ chip->align_buffer_size = 1;
+ else
+ chip->align_buffer_size = 1;
+ }
/* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
@@ -2992,6 +2998,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(0x8086, 0x1e20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
AZX_DCAPS_BUFSIZE},
+ /* Lynx Point */
+ { PCI_DEVICE(0x8086, 0x8c20),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE},
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index d8a35da0803f..d68948499fbc 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -19,6 +19,22 @@
#include "hda_local.h"
#include "hda_jack.h"
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
+{
+ if (codec->no_jack_detect)
+ return false;
+ if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
+ return false;
+ if (!codec->ignore_misc_bit &&
+ (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+ AC_DEFCFG_MISC_NO_PRESENCE))
+ return false;
+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+ return false;
+ return true;
+}
+EXPORT_SYMBOL_HDA(is_jack_detectable);
+
/* execute pin sense measurement */
static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
@@ -282,7 +298,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg)
+ const struct auto_pin_cfg *cfg,
+ char *lastname, int *lastidx)
{
unsigned int def_conf, conn;
char name[44];
@@ -298,6 +315,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
return 0;
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+ if (!strcmp(name, lastname) && idx == *lastidx)
+ idx++;
+ strncpy(lastname, name, 44);
+ *lastidx = idx;
err = snd_hda_jack_add_kctl(codec, nid, name, idx);
if (err < 0)
return err;
@@ -311,41 +332,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
const hda_nid_t *p;
- int i, err;
+ int i, err, lastidx = 0;
+ char lastname[44] = "";
for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */
break;
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */
break;
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0; i < cfg->num_inputs; i++) {
- err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
+ err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
- err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
+ err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
- err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
+ err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
return 0;
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index f8f97c71c9c1..c66655cf413a 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -62,18 +62,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
-static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
-{
- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
- return false;
- if (!codec->ignore_misc_bit &&
- (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
- AC_DEFCFG_MISC_NO_PRESENCE))
- return false;
- if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
- return false;
- return true;
-}
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
const char *name, int idx);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index aca8d3193b95..0ec9248165bc 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -139,10 +139,36 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv);
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *slaves);
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ unsigned int *tlv, const char * const *slaves,
+ const char *suffix, bool init_slave_vol,
+ struct snd_kcontrol **ctl_ret);
+#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \
+ __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL)
int snd_hda_codec_reset(struct hda_codec *codec);
+enum {
+ HDA_VMUTE_OFF,
+ HDA_VMUTE_ON,
+ HDA_VMUTE_FOLLOW_MASTER,
+};
+
+struct hda_vmaster_mute_hook {
+ /* below two fields must be filled by the caller of
+ * snd_hda_add_vmaster_hook() beforehand
+ */
+ struct snd_kcontrol *sw_kctl;
+ void (*hook)(void *, int);
+ /* below are initialized automatically */
+ unsigned int mute_mode; /* HDA_VMUTE_XXX */
+ struct hda_codec *codec;
+};
+
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+ struct hda_vmaster_mute_hook *hook,
+ bool expose_enum_ctl);
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
+
/* amp value bits */
#define HDA_AMP_MUTE 0x80
#define HDA_AMP_UNMUTE 0x00
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 9cb14b42dfff..7143393927da 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -82,6 +82,7 @@ struct ad198x_spec {
unsigned int inv_jack_detect: 1;/* inverted jack-detection */
unsigned int inv_eapd: 1; /* inverted EAPD implementation */
unsigned int analog_beep: 1; /* analog beep input present */
+ unsigned int avoid_init_slave_vol:1;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
@@ -137,51 +138,17 @@ static int ad198x_init(struct hda_codec *codec)
return 0;
}
-static const char * const ad_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Mono Playback Volume",
- "Speaker Playback Volume",
- "IEC958 Playback Volume",
+static const char * const ad_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Mono", "Speaker", "IEC958",
NULL
};
-static const char * const ad_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Mono Playback Switch",
- "Speaker Playback Switch",
- "IEC958 Playback Switch",
+static const char * const ad1988_6stack_fp_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side", "IEC958",
NULL
};
-static const char * const ad1988_6stack_fp_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "IEC958 Playback Volume",
- NULL
-};
-
-static const char * const ad1988_6stack_fp_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "IEC958 Playback Switch",
- NULL
-};
static void ad198x_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -257,10 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec)
unsigned int vmaster_tlv[4];
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
- err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+ err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
vmaster_tlv,
(spec->slave_vols ?
- spec->slave_vols : ad_slave_vols));
+ spec->slave_vols : ad_slave_pfxs),
+ "Playback Volume",
+ !spec->avoid_init_slave_vol, NULL);
if (err < 0)
return err;
}
@@ -268,7 +237,8 @@ static int ad198x_build_controls(struct hda_codec *codec)
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL,
(spec->slave_sws ?
- spec->slave_sws : ad_slave_sws));
+ spec->slave_sws : ad_slave_pfxs),
+ "Playback Switch");
if (err < 0)
return err;
}
@@ -3385,8 +3355,8 @@ static int patch_ad1988(struct hda_codec *codec)
if (spec->autocfg.hp_pins[0]) {
spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
- spec->slave_vols = ad1988_6stack_fp_slave_vols;
- spec->slave_sws = ad1988_6stack_fp_slave_sws;
+ spec->slave_vols = ad1988_6stack_fp_slave_pfxs;
+ spec->slave_sws = ad1988_6stack_fp_slave_pfxs;
spec->alt_dac_nid = ad1988_alt_dac_nid;
spec->stream_analog_alt_playback =
&ad198x_pcm_analog_alt_playback;
@@ -3594,16 +3564,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = {
#endif
static const char * const ad1884_slave_vols[] = {
- "PCM Playback Volume",
- "Mic Playback Volume",
- "Mono Playback Volume",
- "Front Mic Playback Volume",
- "Mic Playback Volume",
- "CD Playback Volume",
- "Internal Mic Playback Volume",
- "Docking Mic Playback Volume",
- /* "Beep Playback Volume", */
- "IEC958 Playback Volume",
+ "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
+ "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958",
NULL
};
@@ -3644,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec)
spec->vmaster_nid = 0x04;
/* we need to cover all playback volumes */
spec->slave_vols = ad1884_slave_vols;
+ /* slaves may contain input volumes, so we can't raise to 0dB blindly */
+ spec->avoid_init_slave_vol = 1;
codec->patch_ops = ad198x_patch_ops;
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 35abe3c62908..21d91d580da8 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_MUTE, &data);
if (err < 0)
- return err;
+ goto exit;
/* *valp 0 is mute, 1 is unmute */
data = (data & 0x7f) | (*valp ? 0 : 0x80);
- chipio_write(codec, REG_CODEC_MUTE, data);
+ err = chipio_write(codec, REG_CODEC_MUTE, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_hp_switch = *valp;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol,
@@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_MUTE, &data);
if (err < 0)
- return err;
+ goto exit;
/* *valp 0 is mute, 1 is unmute */
data = (data & 0xef) | (*valp ? 0 : 0x10);
- chipio_write(codec, REG_CODEC_MUTE, data);
+ err = chipio_write(codec, REG_CODEC_MUTE, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_speaker_switch = *valp;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol,
@@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);
if (err < 0)
- return err;
+ goto exit;
val = 31 - left_vol;
data = (data & 0xe0) | val;
- chipio_write(codec, REG_CODEC_HP_VOL_L, data);
+ err = chipio_write(codec, REG_CODEC_HP_VOL_L, data);
if (err < 0)
- return err;
+ goto exit;
val = 31 - right_vol;
data = (data & 0xe0) | val;
- chipio_write(codec, REG_CODEC_HP_VOL_R, data);
+ err = chipio_write(codec, REG_CODEC_HP_VOL_R, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_hp_volume[0] = left_vol;
spec->curr_hp_volume[1] = right_vol;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid)
@@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
err = add_in_volume(codec, spec->dig_in, "IEC958");
+ if (err < 0)
+ return err;
}
return 0;
}
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 0e99357e822c..c83ccdba1e5a 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -609,7 +609,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
"Front Speaker", "Surround Speaker", "Bass Speaker"
};
static const char * const line_outs[] = {
- "Front Line-Out", "Surround Line-Out", "Bass Line-Out"
+ "Front Line Out", "Surround Line Out", "Bass Line Out"
};
fix_volume_caps(codec, dac);
@@ -635,7 +635,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
if (num_ctls > 1)
name = line_outs[idx];
else
- name = "Line-Out";
+ name = "Line Out";
break;
}
@@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec)
change_cur_input(codec, !spec->automic_idx, 0);
} else {
if (present) {
- spec->last_input = spec->cur_input;
- spec->cur_input = spec->automic_idx;
+ if (spec->cur_input != spec->automic_idx) {
+ spec->last_input = spec->cur_input;
+ spec->cur_input = spec->automic_idx;
+ }
} else {
spec->cur_input = spec->last_input;
}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index a7a5733aa4d2..e6eafb18c8f5 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -70,6 +70,8 @@ struct conexant_spec {
const struct snd_kcontrol_new *mixers[5];
int num_mixers;
hda_nid_t vmaster_nid;
+ struct hda_vmaster_mute_hook vmaster_mute;
+ bool vmaster_mute_led;
const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
@@ -465,21 +467,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = {
};
#endif
-static const char * const slave_vols[] = {
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- "Front Playback Volume",
- "Surround Playback Volume",
- "CLFE Playback Volume",
- NULL
-};
-
-static const char * const slave_sws[] = {
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "Front Playback Switch",
- "Surround Playback Switch",
- "CLFE Playback Switch",
+static const char * const slave_pfxs[] = {
+ "Headphone", "Speaker", "Front", "Surround", "CLFE",
NULL
};
@@ -519,14 +508,17 @@ static int conexant_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, slave_vols);
+ vmaster_tlv, slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (spec->vmaster_nid &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, slave_sws);
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, slave_pfxs,
+ "Playback Switch", true,
+ &spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
@@ -3034,7 +3026,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO),
{}
};
@@ -3482,7 +3473,7 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
"Disabled", "Enabled"
};
static const char * const texts3[] = {
- "Disabled", "Speaker Only", "Line-Out+Speaker"
+ "Disabled", "Speaker Only", "Line Out+Speaker"
};
const char * const *texts;
@@ -3943,6 +3934,63 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
snd_hda_jack_detect_enable(codec, pins[i], action);
}
+static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+ int i;
+ for (i = 0; i < nums; i++)
+ if (list[i] == nid)
+ return true;
+ return false;
+}
+
+/* is the given NID found in any of autocfg items? */
+static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid)
+{
+ int i;
+
+ if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
+ found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
+ found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) ||
+ found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs))
+ return true;
+ for (i = 0; i < cfg->num_inputs; i++)
+ if (cfg->inputs[i].pin == nid)
+ return true;
+ if (cfg->dig_in_pin == nid)
+ return true;
+ return false;
+}
+
+/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
+ * invalid unsol tags by some reason
+ */
+static void clear_unsol_on_unused_pins(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i;
+
+ for (i = 0; i < codec->init_pins.used; i++) {
+ struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+ if (!found_in_autocfg(cfg, pin->nid))
+ snd_hda_codec_write(codec, pin->nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE, 0);
+ }
+}
+
+/* turn on/off EAPD according to Master switch */
+static void cx_auto_vmaster_hook(void *private_data, int enabled)
+{
+ struct hda_codec *codec = private_data;
+ struct conexant_spec *spec = codec->spec;
+
+ if (enabled && spec->pin_eapd_ctrls) {
+ cx_auto_update_speakers(codec);
+ return;
+ }
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
+}
+
static void cx_auto_init_output(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -3983,6 +4031,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
/* turn on all EAPDs if no individual EAPD control is available */
if (!spec->pin_eapd_ctrls)
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+ clear_unsol_on_unused_pins(codec);
}
static void cx_auto_init_input(struct hda_codec *codec)
@@ -4046,11 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec)
static int cx_auto_init(struct hda_codec *codec)
{
+ struct conexant_spec *spec = codec->spec;
/*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
cx_auto_init_output(codec);
cx_auto_init_input(codec);
cx_auto_init_digital(codec);
snd_hda_jack_report_sync(codec);
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
return 0;
}
@@ -4079,7 +4130,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
err = snd_hda_ctl_add(codec, nid, kctl);
if (err < 0)
return err;
- if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
+ if (!(query_amp_caps(codec, nid, hda_dir) &
+ (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)))
break;
}
return 0;
@@ -4295,6 +4347,13 @@ static int cx_auto_build_controls(struct hda_codec *codec)
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
if (err < 0)
return err;
+ if (spec->vmaster_mute.sw_kctl) {
+ spec->vmaster_mute.hook = cx_auto_vmaster_hook;
+ err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
+ spec->vmaster_mute_led);
+ if (err < 0)
+ return err;
+ }
return 0;
}
@@ -4319,7 +4378,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec)
return 0;
}
-
static const struct hda_codec_ops cx_auto_patch_ops = {
.build_controls = cx_auto_build_controls,
.build_pcms = conexant_build_pcms,
@@ -4367,6 +4425,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
{ 0x17, 0x21a11000 }, /* dock-mic */
{ 0x19, 0x2121103f }, /* dock-HP */
+ { 0x1c, 0x21440100 }, /* dock SPDIF out */
{}
};
@@ -4379,6 +4438,22 @@ static const struct snd_pci_quirk cxt_fixups[] = {
{}
};
+/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
+ * can be created (bko#42825)
+ */
+static void add_cx5051_fake_mutes(struct hda_codec *codec)
+{
+ static hda_nid_t out_nids[] = {
+ 0x10, 0x11, 0
+ };
+ hda_nid_t *p;
+
+ for (p = out_nids; *p; p++)
+ snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
+ AC_AMPCAP_MIN_MUTE |
+ query_amp_caps(codec, *p, HDA_OUTPUT));
+}
+
static int patch_conexant_auto(struct hda_codec *codec)
{
struct conexant_spec *spec;
@@ -4397,10 +4472,25 @@ static int patch_conexant_auto(struct hda_codec *codec)
case 0x14f15045:
spec->single_adc_amp = 1;
break;
+ case 0x14f15051:
+ add_cx5051_fake_mutes(codec);
+ break;
}
apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
+ /* Show mute-led control only on HP laptops
+ * This is a sort of white-list: on HP laptops, EAPD corresponds
+ * only to the mute-LED without actualy amp function. Meanwhile,
+ * others may use EAPD really as an amp switch, so it might be
+ * not good to expose it blindly.
+ */
+ switch (codec->subsystem_id >> 16) {
+ case 0x103c:
+ spec->vmaster_mute_led = 1;
+ break;
+ }
+
err = cx_auto_search_adcs(codec);
if (err < 0)
return err;
@@ -4414,6 +4504,18 @@ static int patch_conexant_auto(struct hda_codec *codec)
codec->patch_ops = cx_auto_patch_ops;
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
+
+ /* Some laptops with Conexant chips show stalls in S3 resume,
+ * which falls into the single-cmd mode.
+ * Better to make reset, then.
+ */
+ if (!codec->bus->sync_write) {
+ snd_printd("hda_codec: "
+ "Enable sync_write for stable communication\n");
+ codec->bus->sync_write = 1;
+ codec->bus->allow_bus_reset = 1;
+ }
+
return 0;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 1168ebd3fb5c..540cd13f7f15 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1912,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
+{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi },
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
{} /* terminator */
};
@@ -1958,6 +1959,7 @@ 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:80862806");
+MODULE_ALIAS("snd-hda-codec-id:80862880");
MODULE_ALIAS("snd-hda-codec-id:808629fb");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0db1dc49382b..8ea2fd654327 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -80,6 +80,8 @@ enum {
ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
};
+#define MAX_VOL_NIDS 0x40
+
struct alc_spec {
/* codec parameterization */
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -118,8 +120,8 @@ struct alc_spec {
const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
hda_nid_t mixer_nid; /* analog-mixer NID */
- DECLARE_BITMAP(vol_ctls, 0x20 << 1);
- DECLARE_BITMAP(sw_ctls, 0x20 << 1);
+ DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
+ DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
/* capture setup for dynamic dual-adc switch */
hda_nid_t cur_adc;
@@ -177,6 +179,7 @@ struct alc_spec {
unsigned int detect_lo:1; /* Line-out detection enabled */
unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
unsigned int automute_lo_possible:1; /* there are line outs and HP */
+ unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
@@ -195,8 +198,11 @@ struct alc_spec {
/* for virtual master */
hda_nid_t vmaster_nid;
+ struct hda_vmaster_mute_hook vmaster_mute;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
+ int num_loopbacks;
+ struct hda_amp_list loopback_list[8];
#endif
/* for PLL fix */
@@ -217,8 +223,6 @@ struct alc_spec {
struct snd_array bind_ctls;
};
-#define ALC_MODEL_AUTO 0 /* common for all chips */
-
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
int dir, unsigned int bits)
{
@@ -297,6 +301,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
int i, type, num_conns;
hda_nid_t nid;
+ if (!spec->input_mux)
+ return 0;
+
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
imux = &spec->input_mux[mux_idx];
if (!imux->num_items && mux_idx > 0)
@@ -495,13 +502,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
for (i = 0; i < num_pins; i++) {
hda_nid_t nid = pins[i];
+ unsigned int val;
if (!nid)
break;
switch (spec->automute_mode) {
case ALC_AUTOMUTE_PIN:
+ /* don't reset VREF value in case it's controlling
+ * the amp (see alc861_fixup_asus_amp_vref_0f())
+ */
+ if (spec->keep_vref_in_automute) {
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val &= ~PIN_HP;
+ } else
+ val = 0;
+ val |= pin_bits;
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_bits);
+ val);
break;
case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -637,15 +655,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action)
snd_hda_jack_report_sync(codec);
}
+/* update the master volume per volume-knob's unsol event */
+static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int val;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_value *uctl;
+
+ kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
+ if (!kctl)
+ return;
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return;
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ val &= HDA_AMP_VOLMASK;
+ uctl->value.integer.value[0] = val;
+ uctl->value.integer.value[1] = val;
+ kctl->put(kctl, uctl);
+ kfree(uctl);
+}
+
/* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
{
+ int action;
+
if (codec->vendor_id == 0x10ec0880)
res >>= 28;
else
res >>= 26;
- res = snd_hda_jack_get_action(codec, res);
- alc_exec_unsol_event(codec, res);
+ action = snd_hda_jack_get_action(codec, res);
+ if (action == ALC_DCVOL_EVENT) {
+ /* Execute the dc-vol event here as it requires the NID
+ * but we don't pass NID to alc_exec_unsol_event().
+ * Once when we convert all static quirks to the auto-parser,
+ * this can be integerated into there.
+ */
+ struct hda_jack_tbl *jack;
+ jack = snd_hda_jack_tbl_get_from_tag(codec, res);
+ if (jack)
+ alc_update_knob_master(codec, jack->nid);
+ return;
+ }
+ alc_exec_unsol_event(codec, action);
}
/* call init functions of standard auto-mute helpers */
@@ -788,7 +842,7 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
"Disabled", "Enabled"
};
static const char * const texts3[] = {
- "Disabled", "Speaker Only", "Line-Out+Speaker"
+ "Disabled", "Speaker Only", "Line Out+Speaker"
};
const char * const *texts;
@@ -1019,45 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
return true;
}
-/* rebuild imux for matching with the given auto-mic pins (if not yet) */
-static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- struct hda_input_mux *imux;
- static char * const texts[3] = {
- "Mic", "Internal Mic", "Dock Mic"
- };
- int i;
-
- if (!spec->auto_mic)
- return false;
- imux = &spec->private_imux[0];
- if (spec->input_mux == imux)
- return true;
- spec->imux_pins[0] = spec->ext_mic_pin;
- spec->imux_pins[1] = spec->int_mic_pin;
- spec->imux_pins[2] = spec->dock_mic_pin;
- for (i = 0; i < 3; i++) {
- strcpy(imux->items[i].label, texts[i]);
- if (spec->imux_pins[i]) {
- hda_nid_t pin = spec->imux_pins[i];
- int c;
- for (c = 0; c < spec->num_adc_nids; c++) {
- hda_nid_t cap = get_capsrc(spec, c);
- int idx = get_connection_index(codec, cap, pin);
- if (idx >= 0) {
- imux->items[i].index = idx;
- break;
- }
- }
- imux->num_items = i + 1;
- }
- }
- spec->num_mux_defs = 1;
- spec->input_mux = imux;
- return true;
-}
-
/* check whether all auto-mic pins are valid; setup indices if OK */
static bool alc_auto_mic_check_imux(struct hda_codec *codec)
{
@@ -1427,6 +1442,7 @@ enum {
ALC_FIXUP_ACT_PRE_PROBE,
ALC_FIXUP_ACT_PROBE,
ALC_FIXUP_ACT_INIT,
+ ALC_FIXUP_ACT_BUILD,
};
static void alc_apply_fixup(struct hda_codec *codec, int action)
@@ -1506,6 +1522,13 @@ static void alc_pick_fixup(struct hda_codec *codec,
int id = -1;
const char *name = NULL;
+ /* when model=nofixup is given, don't pick up any fixups */
+ if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
+ spec->fixup_list = NULL;
+ spec->fixup_id = -1;
+ return;
+ }
+
if (codec->modelname && models) {
while (models->name) {
if (!strcmp(codec->modelname, models->name)) {
@@ -1833,32 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3);
/*
* slave controls for virtual master
*/
-static const char * const alc_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- "Mono Playback Volume",
- "Line-Out Playback Volume",
- "PCM Playback Volume",
- NULL,
-};
-
-static const char * const alc_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "Mono Playback Switch",
- "IEC958 Playback Switch",
- "Line-Out Playback Switch",
- "PCM Playback Switch",
+static const char * const alc_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker", "Mono", "Line Out",
+ "CLFE", "Bass Speaker", "PCM",
NULL,
};
@@ -1949,14 +1950,17 @@ static int __alc_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, alc_slave_vols);
+ vmaster_tlv, alc_slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (!spec->no_analog &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, alc_slave_sws);
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, alc_slave_pfxs,
+ "Playback Switch",
+ true, &spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
@@ -2041,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec)
int err = __alc_build_controls(codec);
if (err < 0)
return err;
- return snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD);
+ return 0;
}
@@ -2050,21 +2058,23 @@ static int alc_build_controls(struct hda_codec *codec)
*/
static void alc_init_special_input_src(struct hda_codec *codec);
+static void alc_auto_init_std(struct hda_codec *codec);
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int i;
+ if (spec->init_hook)
+ spec->init_hook(codec);
+
alc_fix_pll(codec);
alc_auto_init_amp(codec, spec->init_amp);
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
alc_init_special_input_src(codec);
-
- if (spec->init_hook)
- spec->init_hook(codec);
+ alc_auto_init_std(codec);
alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
@@ -2306,7 +2316,7 @@ static int alc_build_pcms(struct hda_codec *codec)
"%s Analog", codec->chip_name);
info->name = spec->stream_name_analog;
- if (spec->multiout.dac_nids > 0) {
+ if (spec->multiout.num_dacs > 0) {
p = spec->stream_analog_playback;
if (!p)
p = &alc_pcm_analog_playback;
@@ -2653,6 +2663,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
return channel_name[ch];
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* add the powersave loopback-list entry */
+static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
+{
+ struct hda_amp_list *list;
+
+ if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
+ return;
+ list = spec->loopback_list + spec->num_loopbacks;
+ list->nid = mix;
+ list->dir = HDA_INPUT;
+ list->idx = idx;
+ spec->num_loopbacks++;
+ spec->loopback.amplist = spec->loopback_list;
+}
+#else
+#define add_loopback_list(spec, mix, idx) /* NOP */
+#endif
+
/* 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, int ctlidx,
@@ -2668,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0)
return err;
+ add_loopback_list(spec, mix_nid, idx);
return 0;
}
@@ -2932,10 +2962,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
return 0;
}
+static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+ if (found_in_nid_list(nid, spec->multiout.dac_nids,
+ ARRAY_SIZE(spec->private_dac_nids)) ||
+ found_in_nid_list(nid, spec->multiout.hp_out_nid,
+ ARRAY_SIZE(spec->multiout.hp_out_nid)) ||
+ found_in_nid_list(nid, spec->multiout.extra_out_nid,
+ ARRAY_SIZE(spec->multiout.extra_out_nid)))
+ return true;
+ for (i = 0; i < spec->multi_ios; i++) {
+ if (spec->multi_io[i].dac == nid)
+ return true;
+ }
+ return false;
+}
+
/* look for an empty DAC slot */
static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
{
- struct alc_spec *spec = codec->spec;
hda_nid_t srcs[5];
int i, num;
@@ -2945,16 +2992,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
if (!nid)
continue;
- if (found_in_nid_list(nid, spec->multiout.dac_nids,
- ARRAY_SIZE(spec->private_dac_nids)))
- continue;
- if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
- ARRAY_SIZE(spec->multiout.hp_out_nid)))
- continue;
- if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
- ARRAY_SIZE(spec->multiout.extra_out_nid)))
- continue;
- return nid;
+ if (!alc_is_dac_already_used(codec, nid))
+ return nid;
}
return 0;
}
@@ -2966,6 +3005,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
hda_nid_t srcs[5];
int i, num;
+ if (!pin || !dac)
+ return false;
pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
for (i = 0; i < num; i++) {
@@ -2978,83 +3019,260 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
{
+ struct alc_spec *spec = codec->spec;
hda_nid_t sel = alc_go_down_to_selector(codec, pin);
- if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
+ hda_nid_t nid, nid_found, srcs[5];
+ int i, num = snd_hda_get_connections(codec, sel, srcs,
+ ARRAY_SIZE(srcs));
+ if (num == 1)
return alc_auto_look_for_dac(codec, pin);
- return 0;
+ nid_found = 0;
+ for (i = 0; i < num; i++) {
+ if (srcs[i] == spec->mixer_nid)
+ continue;
+ nid = alc_auto_mix_to_dac(codec, srcs[i]);
+ if (nid && !alc_is_dac_already_used(codec, nid)) {
+ if (nid_found)
+ return 0;
+ nid_found = nid;
+ }
+ }
+ return nid_found;
}
-/* return 0 if no possible DAC is found, 1 if one or more found */
-static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
- const hda_nid_t *pins, hda_nid_t *dacs)
+/* mark up volume and mute control NIDs: used during badness parsing and
+ * at creating actual controls
+ */
+static inline unsigned int get_ctl_pos(unsigned int data)
{
- int i;
+ hda_nid_t nid = get_amp_nid_(data);
+ unsigned int dir;
+ if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+ return 0;
+ dir = get_amp_direction_(data);
+ return (nid << 1) | dir;
+}
- if (num_outs && !dacs[0]) {
- dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
- if (!dacs[0])
- return 0;
- }
+#define is_ctl_used(bits, data) \
+ test_bit(get_ctl_pos(data), bits)
+#define mark_ctl_usage(bits, data) \
+ set_bit(get_ctl_pos(data), bits)
- for (i = 1; i < num_outs; i++)
- dacs[i] = get_dac_if_single(codec, pins[i]);
- for (i = 1; i < num_outs; i++) {
+static void clear_vol_marks(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls));
+ memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
+}
+
+/* badness definition */
+enum {
+ /* No primary DAC is found for the main output */
+ BAD_NO_PRIMARY_DAC = 0x10000,
+ /* No DAC is found for the extra output */
+ BAD_NO_DAC = 0x4000,
+ /* No possible multi-ios */
+ BAD_MULTI_IO = 0x103,
+ /* No individual DAC for extra output */
+ BAD_NO_EXTRA_DAC = 0x102,
+ /* No individual DAC for extra surrounds */
+ BAD_NO_EXTRA_SURR_DAC = 0x101,
+ /* Primary DAC shared with main surrounds */
+ BAD_SHARED_SURROUND = 0x100,
+ /* Primary DAC shared with main CLFE */
+ BAD_SHARED_CLFE = 0x10,
+ /* Primary DAC shared with extra surrounds */
+ BAD_SHARED_EXTRA_SURROUND = 0x10,
+ /* Volume widget is shared */
+ BAD_SHARED_VOL = 0x10,
+};
+
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
+ hda_nid_t pin, hda_nid_t dac);
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
+ hda_nid_t pin, hda_nid_t dac);
+
+static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
+ hda_nid_t dac)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t nid;
+ unsigned int val;
+ int badness = 0;
+
+ nid = alc_look_for_out_vol_nid(codec, pin, dac);
+ if (nid) {
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ if (is_ctl_used(spec->vol_ctls, nid))
+ badness += BAD_SHARED_VOL;
+ else
+ mark_ctl_usage(spec->vol_ctls, val);
+ } else
+ badness += BAD_SHARED_VOL;
+ nid = alc_look_for_out_mute_nid(codec, pin, dac);
+ if (nid) {
+ unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
+ if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ else
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
+ if (is_ctl_used(spec->sw_ctls, val))
+ badness += BAD_SHARED_VOL;
+ else
+ mark_ctl_usage(spec->sw_ctls, val);
+ } else
+ badness += BAD_SHARED_VOL;
+ return badness;
+}
+
+struct badness_table {
+ int no_primary_dac; /* no primary DAC */
+ int no_dac; /* no secondary DACs */
+ int shared_primary; /* primary DAC is shared with main output */
+ int shared_surr; /* secondary DAC shared with main or primary */
+ int shared_clfe; /* third DAC shared with main or primary */
+ int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
+};
+
+static struct badness_table main_out_badness = {
+ .no_primary_dac = BAD_NO_PRIMARY_DAC,
+ .no_dac = BAD_NO_DAC,
+ .shared_primary = BAD_NO_PRIMARY_DAC,
+ .shared_surr = BAD_SHARED_SURROUND,
+ .shared_clfe = BAD_SHARED_CLFE,
+ .shared_surr_main = BAD_SHARED_SURROUND,
+};
+
+static struct badness_table extra_out_badness = {
+ .no_primary_dac = BAD_NO_DAC,
+ .no_dac = BAD_NO_DAC,
+ .shared_primary = BAD_NO_EXTRA_DAC,
+ .shared_surr = BAD_SHARED_EXTRA_SURROUND,
+ .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
+ .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
+};
+
+/* try to assign DACs to pins and return the resultant badness */
+static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
+ const hda_nid_t *pins, hda_nid_t *dacs,
+ const struct badness_table *bad)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i, j;
+ int badness = 0;
+ hda_nid_t dac;
+
+ if (!num_outs)
+ return 0;
+
+ for (i = 0; i < num_outs; i++) {
+ hda_nid_t pin = pins[i];
if (!dacs[i])
- dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
+ dacs[i] = alc_auto_look_for_dac(codec, pin);
+ if (!dacs[i] && !i) {
+ for (j = 1; j < num_outs; j++) {
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
+ dacs[0] = dacs[j];
+ dacs[j] = 0;
+ break;
+ }
+ }
+ }
+ dac = dacs[i];
+ if (!dac) {
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[0]))
+ dac = dacs[0];
+ else if (cfg->line_outs > i &&
+ alc_auto_is_dac_reachable(codec, pin,
+ spec->private_dac_nids[i]))
+ dac = spec->private_dac_nids[i];
+ if (dac) {
+ if (!i)
+ badness += bad->shared_primary;
+ else if (i == 1)
+ badness += bad->shared_surr;
+ else
+ badness += bad->shared_clfe;
+ } else if (alc_auto_is_dac_reachable(codec, pin,
+ spec->private_dac_nids[0])) {
+ dac = spec->private_dac_nids[0];
+ badness += bad->shared_surr_main;
+ } else if (!i)
+ badness += bad->no_primary_dac;
+ else
+ badness += bad->no_dac;
+ }
+ if (dac)
+ badness += eval_shared_vol_badness(codec, pin, dac);
}
- return 1;
+
+ return badness;
}
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
- unsigned int location, int offset);
-static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
- hda_nid_t pin, hda_nid_t dac);
+ hda_nid_t reference_pin,
+ bool hardwired, int offset);
+
+static bool alc_map_singles(struct hda_codec *codec, int outs,
+ const hda_nid_t *pins, hda_nid_t *dacs)
+{
+ int i;
+ bool found = false;
+ for (i = 0; i < outs; i++) {
+ if (dacs[i])
+ continue;
+ dacs[i] = get_dac_if_single(codec, pins[i]);
+ if (dacs[i])
+ found = true;
+ }
+ return found;
+}
/* fill in the dac_nids table from the parsed pin configuration */
-static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+static int fill_and_eval_dacs(struct hda_codec *codec,
+ bool fill_hardwired,
+ bool fill_mio_first)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int location, defcfg;
- int num_pins;
- bool redone = false;
- int i;
+ int i, err, badness;
- again:
/* set num_dacs once to full for alc_auto_look_for_dac() */
spec->multiout.num_dacs = cfg->line_outs;
- spec->multiout.hp_out_nid[0] = 0;
- spec->multiout.extra_out_nid[0] = 0;
- memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
spec->multiout.dac_nids = spec->private_dac_nids;
+ memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
+ memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
+ memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
spec->multi_ios = 0;
+ clear_vol_marks(codec);
+ badness = 0;
/* fill hard-wired DACs first */
- if (!redone) {
- for (i = 0; i < cfg->line_outs; i++)
- spec->private_dac_nids[i] =
- get_dac_if_single(codec, cfg->line_out_pins[i]);
- if (cfg->hp_outs)
- spec->multiout.hp_out_nid[0] =
- get_dac_if_single(codec, cfg->hp_pins[0]);
- if (cfg->speaker_outs)
- spec->multiout.extra_out_nid[0] =
- get_dac_if_single(codec, cfg->speaker_pins[0]);
+ if (fill_hardwired) {
+ bool mapped;
+ do {
+ mapped = alc_map_singles(codec, cfg->line_outs,
+ cfg->line_out_pins,
+ spec->private_dac_nids);
+ mapped |= alc_map_singles(codec, cfg->hp_outs,
+ cfg->hp_pins,
+ spec->multiout.hp_out_nid);
+ mapped |= alc_map_singles(codec, cfg->speaker_outs,
+ cfg->speaker_pins,
+ spec->multiout.extra_out_nid);
+ if (fill_mio_first && cfg->line_outs == 1 &&
+ cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
+ if (!err)
+ mapped = true;
+ }
+ } while (mapped);
}
- for (i = 0; i < cfg->line_outs; i++) {
- hda_nid_t pin = cfg->line_out_pins[i];
- if (spec->private_dac_nids[i])
- continue;
- spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
- if (!spec->private_dac_nids[i] && !redone) {
- /* if we can't find primary DACs, re-probe without
- * checking the hard-wired DACs
- */
- redone = true;
- goto again;
- }
- }
+ badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
+ spec->private_dac_nids,
+ &main_out_badness);
/* re-count num_dacs and squash invalid entries */
spec->multiout.num_dacs = 0;
@@ -3069,30 +3287,144 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
}
}
- if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ if (fill_mio_first &&
+ cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
/* try to fill multi-io first */
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
- location = get_defcfg_location(defcfg);
-
- num_pins = alc_auto_fill_multi_ios(codec, location, 0);
- if (num_pins > 0) {
- spec->multi_ios = num_pins;
- spec->ext_channel_count = 2;
- spec->multiout.num_dacs = num_pins + 1;
- }
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+ if (err < 0)
+ return err;
+ /* we don't count badness at this stage yet */
}
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
- spec->multiout.hp_out_nid);
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+ err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
+ spec->multiout.hp_out_nid,
+ &extra_out_badness);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
- cfg->speaker_pins,
- spec->multiout.extra_out_nid);
- /* if no speaker volume is assigned, try again as the primary
- * output
- */
- if (!err && cfg->speaker_outs > 0 &&
+ err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
+ cfg->speaker_pins,
+ spec->multiout.extra_out_nid,
+ &extra_out_badness);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+ if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+ if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+ /* try multi-ios with HP + inputs */
+ int offset = 0;
+ if (cfg->line_outs >= 3)
+ offset = 1;
+ err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false,
+ offset);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+
+ if (spec->multi_ios == 2) {
+ for (i = 0; i < 2; i++)
+ spec->private_dac_nids[spec->multiout.num_dacs++] =
+ spec->multi_io[i].dac;
+ spec->ext_channel_count = 2;
+ } else if (spec->multi_ios) {
+ spec->multi_ios = 0;
+ badness += BAD_MULTI_IO;
+ }
+
+ return badness;
+}
+
+#define DEBUG_BADNESS
+
+#ifdef DEBUG_BADNESS
+#define debug_badness snd_printdd
+#else
+#define debug_badness(...)
+#endif
+
+static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg)
+{
+ debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->line_out_pins[0], cfg->line_out_pins[1],
+ cfg->line_out_pins[2], cfg->line_out_pins[2],
+ spec->multiout.dac_nids[0],
+ spec->multiout.dac_nids[1],
+ spec->multiout.dac_nids[2],
+ spec->multiout.dac_nids[3]);
+ if (spec->multi_ios > 0)
+ debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
+ spec->multi_ios,
+ spec->multi_io[0].pin, spec->multi_io[1].pin,
+ spec->multi_io[0].dac, spec->multi_io[1].dac);
+ debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->hp_pins[0], cfg->hp_pins[1],
+ cfg->hp_pins[2], cfg->hp_pins[2],
+ spec->multiout.hp_out_nid[0],
+ spec->multiout.hp_out_nid[1],
+ spec->multiout.hp_out_nid[2],
+ spec->multiout.hp_out_nid[3]);
+ debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->speaker_pins[0], cfg->speaker_pins[1],
+ cfg->speaker_pins[2], cfg->speaker_pins[3],
+ spec->multiout.extra_out_nid[0],
+ spec->multiout.extra_out_nid[1],
+ spec->multiout.extra_out_nid[2],
+ spec->multiout.extra_out_nid[3]);
+}
+
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ struct auto_pin_cfg *best_cfg;
+ int best_badness = INT_MAX;
+ int badness;
+ bool fill_hardwired = true, fill_mio_first = true;
+ bool best_wired = true, best_mio = true;
+ bool hp_spk_swapped = false;
+
+ best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
+ if (!best_cfg)
+ return -ENOMEM;
+ *best_cfg = *cfg;
+
+ for (;;) {
+ badness = fill_and_eval_dacs(codec, fill_hardwired,
+ fill_mio_first);
+ if (badness < 0)
+ return badness;
+ debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
+ cfg->line_out_type, fill_hardwired, fill_mio_first,
+ badness);
+ debug_show_configs(spec, cfg);
+ if (badness < best_badness) {
+ best_badness = badness;
+ *best_cfg = *cfg;
+ best_wired = fill_hardwired;
+ best_mio = fill_mio_first;
+ }
+ if (!badness)
+ break;
+ fill_mio_first = !fill_mio_first;
+ if (!fill_mio_first)
+ continue;
+ fill_hardwired = !fill_hardwired;
+ if (!fill_hardwired)
+ continue;
+ if (hp_spk_swapped)
+ break;
+ hp_spk_swapped = true;
+ if (cfg->speaker_outs > 0 &&
cfg->line_out_type == AUTO_PIN_HP_OUT) {
cfg->hp_outs = cfg->line_outs;
memcpy(cfg->hp_pins, cfg->line_out_pins,
@@ -3103,45 +3435,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
cfg->speaker_outs = 0;
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
- redone = false;
- goto again;
- }
+ fill_hardwired = true;
+ continue;
+ }
+ if (cfg->hp_outs > 0 &&
+ cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+ cfg->speaker_outs = cfg->line_outs;
+ memcpy(cfg->speaker_pins, cfg->line_out_pins,
+ sizeof(cfg->speaker_pins));
+ cfg->line_outs = cfg->hp_outs;
+ memcpy(cfg->line_out_pins, cfg->hp_pins,
+ sizeof(cfg->hp_pins));
+ cfg->hp_outs = 0;
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
+ fill_hardwired = true;
+ continue;
+ }
+ break;
}
- if (!spec->multi_ios &&
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
- cfg->hp_outs) {
- /* try multi-ios with HP + inputs */
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
- location = get_defcfg_location(defcfg);
-
- num_pins = alc_auto_fill_multi_ios(codec, location, 1);
- if (num_pins > 0) {
- spec->multi_ios = num_pins;
- spec->ext_channel_count = 2;
- spec->multiout.num_dacs = num_pins + 1;
- }
+ if (badness) {
+ *cfg = *best_cfg;
+ fill_and_eval_dacs(codec, best_wired, best_mio);
}
+ debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
+ cfg->line_out_type, best_wired, best_mio);
+ debug_show_configs(spec, cfg);
if (cfg->line_out_pins[0])
spec->vmaster_nid =
alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
spec->multiout.dac_nids[0]);
- return 0;
-}
-static inline unsigned int get_ctl_pos(unsigned int data)
-{
- hda_nid_t nid = get_amp_nid_(data);
- unsigned int dir = get_amp_direction_(data);
- return (nid << 1) | dir;
+ /* clear the bitmap flags for creating controls */
+ clear_vol_marks(codec);
+ kfree(best_cfg);
+ return 0;
}
-#define is_ctl_used(bits, data) \
- test_bit(get_ctl_pos(data), bits)
-#define mark_ctl_usage(bits, data) \
- set_bit(get_ctl_pos(data), bits)
-
static int alc_auto_add_vol_ctl(struct hda_codec *codec,
const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs)
@@ -3253,14 +3585,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
dac = spec->multiout.dac_nids[i];
if (!dac)
continue;
- if (i >= cfg->line_outs)
+ if (i >= cfg->line_outs) {
pin = spec->multi_io[i - 1].pin;
- else
+ index = 0;
+ name = channel_name[i];
+ } else {
pin = cfg->line_out_pins[i];
+ name = alc_get_line_out_pfx(spec, i, true, &index);
+ }
sw = alc_look_for_out_mute_nid(codec, pin, dac);
vol = alc_look_for_out_vol_nid(codec, pin, dac);
- name = alc_get_line_out_pfx(spec, i, true, &index);
if (!name || !strcmp(name, "CLFE")) {
/* Center/LFE */
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
@@ -3357,41 +3692,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
}
- if (dacs[num_pins - 1]) {
- /* OK, we have a multi-output system with individual volumes */
- for (i = 0; i < num_pins; i++) {
- if (num_pins >= 3) {
- snprintf(name, sizeof(name), "%s %s",
- pfx, channel_name[i]);
- err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
- name, 0);
- } else {
- err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
- pfx, i);
- }
- if (err < 0)
- return err;
- }
- return 0;
- }
-
- /* Let's create a bind-controls */
- ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
- if (!ctl)
- return -ENOMEM;
- n = 0;
for (i = 0; i < num_pins; i++) {
- if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
- ctl->values[n++] =
- HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
- }
- if (n) {
- snprintf(name, sizeof(name), "%s Playback Switch", pfx);
- err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
+ hda_nid_t dac;
+ if (dacs[num_pins - 1])
+ dac = dacs[i]; /* with individual volumes */
+ else
+ dac = 0;
+ if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ "Bass Speaker", 0);
+ } else if (num_pins >= 3) {
+ snprintf(name, sizeof(name), "%s %s",
+ pfx, channel_name[i]);
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ name, 0);
+ } else {
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ pfx, i);
+ }
if (err < 0)
return err;
}
+ if (dacs[num_pins - 1])
+ return 0;
+ /* Let's create a bind-controls for volumes */
ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
if (!ctl)
return -ENOMEM;
@@ -3527,58 +3852,111 @@ static void alc_auto_init_extra_out(struct hda_codec *codec)
}
}
+/* check whether the given pin can be a multi-io pin */
+static bool can_be_multiio_pin(struct hda_codec *codec,
+ unsigned int location, hda_nid_t nid)
+{
+ unsigned int defcfg, caps;
+
+ defcfg = snd_hda_codec_get_pincfg(codec, nid);
+ if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+ return false;
+ if (location && get_defcfg_location(defcfg) != location)
+ return false;
+ caps = snd_hda_query_pin_caps(codec, nid);
+ if (!(caps & AC_PINCAP_OUT))
+ return false;
+ return true;
+}
+
/*
* multi-io helper
+ *
+ * When hardwired is set, try to fill ony hardwired pins, and returns
+ * zero if any pins are filled, non-zero if nothing found.
+ * When hardwired is off, try to fill possible input pins, and returns
+ * the badness value.
*/
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
- unsigned int location,
- int offset)
+ hda_nid_t reference_pin,
+ bool hardwired, int offset)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t prime_dac = spec->private_dac_nids[0];
- int type, i, dacs, num_pins = 0;
+ int type, i, j, dacs, num_pins, old_pins;
+ unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
+ unsigned int location = get_defcfg_location(defcfg);
+ int badness = 0;
+
+ old_pins = spec->multi_ios;
+ if (old_pins >= 2)
+ goto end_fill;
+
+ num_pins = 0;
+ for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ if (cfg->inputs[i].type != type)
+ continue;
+ if (can_be_multiio_pin(codec, location,
+ cfg->inputs[i].pin))
+ num_pins++;
+ }
+ }
+ if (num_pins < 2)
+ goto end_fill;
dacs = spec->multiout.num_dacs;
for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
hda_nid_t dac = 0;
- unsigned int defcfg, caps;
+
if (cfg->inputs[i].type != type)
continue;
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
- if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
- continue;
- if (location && get_defcfg_location(defcfg) != location)
+ if (!can_be_multiio_pin(codec, location, nid))
continue;
- caps = snd_hda_query_pin_caps(codec, nid);
- if (!(caps & AC_PINCAP_OUT))
+ for (j = 0; j < spec->multi_ios; j++) {
+ if (nid == spec->multi_io[j].pin)
+ break;
+ }
+ if (j < spec->multi_ios)
continue;
- if (offset && offset + num_pins < dacs) {
- dac = spec->private_dac_nids[offset + num_pins];
+
+ if (offset && offset + spec->multi_ios < dacs) {
+ dac = spec->private_dac_nids[offset + spec->multi_ios];
if (!alc_auto_is_dac_reachable(codec, nid, dac))
dac = 0;
}
- if (!dac)
+ if (hardwired)
+ dac = get_dac_if_single(codec, nid);
+ else if (!dac)
dac = alc_auto_look_for_dac(codec, nid);
- if (!dac)
+ if (!dac) {
+ badness++;
continue;
- spec->multi_io[num_pins].pin = nid;
- spec->multi_io[num_pins].dac = dac;
- num_pins++;
- spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+ }
+ spec->multi_io[spec->multi_ios].pin = nid;
+ spec->multi_io[spec->multi_ios].dac = dac;
+ spec->multi_ios++;
+ if (spec->multi_ios >= 2)
+ break;
}
}
- spec->multiout.num_dacs = dacs;
- if (num_pins < 2) {
- /* clear up again */
- memset(spec->private_dac_nids + dacs, 0,
- sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
- spec->private_dac_nids[0] = prime_dac;
- return 0;
+ end_fill:
+ if (badness)
+ badness = BAD_MULTI_IO;
+ if (old_pins == spec->multi_ios) {
+ if (hardwired)
+ return 1; /* nothing found */
+ else
+ return badness; /* no badness if nothing found */
+ }
+ if (!hardwired && spec->multi_ios < 2) {
+ spec->multi_ios = old_pins;
+ return badness;
}
- return num_pins;
+
+ return 0;
}
static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
@@ -3776,7 +4154,7 @@ static void alc_auto_init_input_src(struct hda_codec *codec)
else
nums = spec->num_adc_nids;
for (c = 0; c < nums; c++)
- alc_mux_select(codec, 0, spec->cur_mux[c], true);
+ alc_mux_select(codec, c, spec->cur_mux[c], true);
}
/* add mic boosts if needed */
@@ -3933,6 +4311,7 @@ static const struct snd_pci_quirk beep_white_list[] = {
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
+ SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
{}
};
@@ -4032,6 +4411,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
if (spec->kctls.list)
add_mixer(spec, spec->kctls.list);
+ if (!spec->no_analog && !spec->cap_mixer)
+ set_capture_mixer(codec);
+
return 1;
}
@@ -4042,26 +4424,47 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_loopbacks[] = {
- { 0x0b, HDA_INPUT, 0 },
- { 0x0b, HDA_INPUT, 1 },
- { 0x0b, HDA_INPUT, 2 },
- { 0x0b, HDA_INPUT, 3 },
- { 0x0b, HDA_INPUT, 4 },
- { } /* end */
-};
-#endif
-
/*
* ALC880 fix-ups
*/
enum {
+ ALC880_FIXUP_GPIO1,
ALC880_FIXUP_GPIO2,
ALC880_FIXUP_MEDION_RIM,
+ ALC880_FIXUP_LG,
+ ALC880_FIXUP_W810,
+ ALC880_FIXUP_EAPD_COEF,
+ ALC880_FIXUP_TCL_S700,
+ ALC880_FIXUP_VOL_KNOB,
+ ALC880_FIXUP_FUJITSU,
+ ALC880_FIXUP_F1734,
+ ALC880_FIXUP_UNIWILL,
+ ALC880_FIXUP_UNIWILL_DIG,
+ ALC880_FIXUP_Z71V,
+ ALC880_FIXUP_3ST_BASE,
+ ALC880_FIXUP_3ST,
+ ALC880_FIXUP_3ST_DIG,
+ ALC880_FIXUP_5ST_BASE,
+ ALC880_FIXUP_5ST,
+ ALC880_FIXUP_5ST_DIG,
+ ALC880_FIXUP_6ST_BASE,
+ ALC880_FIXUP_6ST,
+ ALC880_FIXUP_6ST_DIG,
};
+/* enable the volume-knob widget support on NID 0x21 */
+static void alc880_fixup_vol_knob(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PROBE)
+ snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT);
+}
+
static const struct alc_fixup alc880_fixups[] = {
+ [ALC880_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
[ALC880_FIXUP_GPIO2] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = alc_gpio2_init_verbs,
@@ -4076,40 +4479,323 @@ static const struct alc_fixup alc880_fixups[] = {
.chained = true,
.chain_id = ALC880_FIXUP_GPIO2,
},
+ [ALC880_FIXUP_LG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x16, 0x411111f0 },
+ { 0x18, 0x411111f0 },
+ { 0x1a, 0x411111f0 },
+ { }
+ }
+ },
+ [ALC880_FIXUP_W810] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x17, 0x411111f0 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_GPIO2,
+ },
+ [ALC880_FIXUP_EAPD_COEF] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
+ {}
+ },
+ },
+ [ALC880_FIXUP_TCL_S700] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_GPIO2,
+ },
+ [ALC880_FIXUP_VOL_KNOB] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc880_fixup_vol_knob,
+ },
+ [ALC880_FIXUP_FUJITSU] = {
+ /* override all pins as BIOS on old Amilo is broken */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x99030130 }, /* bass speaker */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x411111f0 }, /* N/A */
+ { 0x19, 0x01a19950 }, /* mic-in */
+ { 0x1a, 0x411111f0 }, /* N/A */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x01454140 }, /* SPDIF out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
+ },
+ [ALC880_FIXUP_F1734] = {
+ /* almost compatible with FUJITSU, but no bass and SPDIF */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x411111f0 }, /* N/A */
+ { 0x19, 0x01a19950 }, /* mic-in */
+ { 0x1a, 0x411111f0 }, /* N/A */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
+ },
+ [ALC880_FIXUP_UNIWILL] = {
+ /* need to fix HP and speaker pins to be parsed correctly */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x99030130 }, /* bass speaker */
+ { }
+ },
+ },
+ [ALC880_FIXUP_UNIWILL_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x17, 0x411111f0 },
+ { 0x19, 0x411111f0 },
+ { 0x1b, 0x411111f0 },
+ { 0x1f, 0x411111f0 },
+ { }
+ }
+ },
+ [ALC880_FIXUP_Z71V] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* set up the whole pins as BIOS is utterly broken */
+ { 0x14, 0x99030120 }, /* speaker */
+ { 0x15, 0x0121411f }, /* HP */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x01a19950 }, /* mic-in */
+ { 0x19, 0x411111f0 }, /* N/A */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ }
+ },
+ [ALC880_FIXUP_3ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* line-out */
+ { 0x15, 0x411111f0 }, /* N/A */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x0121411f }, /* HP */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x02a19c40 }, /* front-mic */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_3ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_3ST_BASE,
+ },
+ [ALC880_FIXUP_3ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_3ST_BASE,
+ },
+ [ALC880_FIXUP_5ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* front */
+ { 0x15, 0x411111f0 }, /* N/A */
+ { 0x16, 0x01011411 }, /* CLFE */
+ { 0x17, 0x01016412 }, /* surr */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x0121411f }, /* HP */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x02a19c40 }, /* front-mic */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_5ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_5ST_BASE,
+ },
+ [ALC880_FIXUP_5ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_5ST_BASE,
+ },
+ [ALC880_FIXUP_6ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* front */
+ { 0x15, 0x01016412 }, /* surr */
+ { 0x16, 0x01011411 }, /* CLFE */
+ { 0x17, 0x01012414 }, /* side */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x02a19c40 }, /* front-mic */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x0121411f }, /* HP */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_6ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_6ST_BASE,
+ },
+ [ALC880_FIXUP_6ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_6ST_BASE,
+ },
};
static const struct snd_pci_quirk alc880_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
+ SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
+ SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
+ SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
+ SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
+ SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+ SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
+ SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
+ SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
+
+ /* Below is the copied entries from alc880_quirks.c.
+ * It's not quite sure whether BIOS sets the correct pin-config table
+ * on these machines, thus they are kept to be compatible with
+ * the old static quirks. Once when it's confirmed to work without
+ * these overrides, it'd be better to remove.
+ */
+ SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
+ SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
+ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ /* default Intel */
+ SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
{}
};
+static const struct alc_model_fixup alc880_fixup_models[] = {
+ {.id = ALC880_FIXUP_3ST, .name = "3stack"},
+ {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
+ {.id = ALC880_FIXUP_5ST, .name = "5stack"},
+ {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
+ {.id = ALC880_FIXUP_6ST, .name = "6stack"},
+ {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
+ {}
+};
-/*
- * board setups
- */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#define alc_board_config \
- snd_hda_check_board_config
-#define alc_board_codec_sid_config \
- snd_hda_check_board_codec_sid_config
-#include "alc_quirks.c"
-#else
-#define alc_board_config(codec, nums, models, tbl) -1
-#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
-#define setup_preset(codec, x) /* NOP */
-#endif
/*
* OK, here we have finally the patch for ALC880
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc880_quirks.c"
-#endif
-
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4121,47 +4807,14 @@ static int patch_alc880(struct hda_codec *codec)
spec->mixer_nid = 0x0b;
spec->need_dac_fix = 1;
- board_config = alc_board_config(codec, ALC880_MODEL_LAST,
- alc880_models, alc880_cfg_tbl);
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc880_parse_auto_config(codec);
- if (err < 0)
- goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using 3-stack mode...\n");
- board_config = ALC880_3ST;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO) {
- spec->vmaster_nid = 0x0c;
- setup_preset(codec, &alc880_presets[board_config]);
- }
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
+ alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
+ alc880_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc880_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4170,17 +4823,9 @@ static int patch_alc880(struct hda_codec *codec)
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
- else
- codec->patch_ops.build_controls = __alc_build_controls;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc880_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -4200,49 +4845,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc260_loopbacks[] = {
- { 0x07, HDA_INPUT, 0 },
- { 0x07, HDA_INPUT, 1 },
- { 0x07, HDA_INPUT, 2 },
- { 0x07, HDA_INPUT, 3 },
- { 0x07, HDA_INPUT, 4 },
- { } /* end */
-};
-#endif
-
/*
* Pin config fixes
*/
enum {
- PINFIX_HP_DC5750,
+ ALC260_FIXUP_HP_DC5750,
+ ALC260_FIXUP_HP_PIN_0F,
+ ALC260_FIXUP_COEF,
+ ALC260_FIXUP_GPIO1,
+ ALC260_FIXUP_GPIO1_TOGGLE,
+ ALC260_FIXUP_REPLACER,
+ ALC260_FIXUP_HP_B1900,
};
+static void alc260_gpio1_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+ spec->hp_jack_present);
+}
+
+static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action == ALC_FIXUP_ACT_PROBE) {
+ /* although the machine has only one output pin, we need to
+ * toggle GPIO1 according to the jack state
+ */
+ spec->automute_hook = alc260_gpio1_automute;
+ spec->detect_hp = 1;
+ spec->automute_speaker = 1;
+ spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
+ snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
+ spec->unsol_event = alc_sku_unsol_event;
+ add_verb(codec->spec, alc_gpio1_init_verbs);
+ }
+}
+
static const struct alc_fixup alc260_fixups[] = {
- [PINFIX_HP_DC5750] = {
+ [ALC260_FIXUP_HP_DC5750] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x11, 0x90130110 }, /* speaker */
{ }
}
},
+ [ALC260_FIXUP_HP_PIN_0F] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x0f, 0x01214000 }, /* HP */
+ { }
+ }
+ },
+ [ALC260_FIXUP_COEF] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
+ },
+ [ALC260_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
+ [ALC260_FIXUP_GPIO1_TOGGLE] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc260_fixup_gpio1_toggle,
+ .chained = true,
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
+ },
+ [ALC260_FIXUP_REPLACER] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
+ },
+ [ALC260_FIXUP_HP_B1900] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc260_fixup_gpio1_toggle,
+ .chained = true,
+ .chain_id = ALC260_FIXUP_COEF,
+ }
};
static const struct snd_pci_quirk alc260_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
+ SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
+ SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
+ SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
+ SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
+ SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
{}
};
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc260_quirks.c"
-#endif
-
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -4252,47 +4963,13 @@ static int patch_alc260(struct hda_codec *codec)
spec->mixer_nid = 0x07;
- board_config = alc_board_config(codec, ALC260_MODEL_LAST,
- alc260_models, alc260_cfg_tbl);
- if (board_config < 0) {
- snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc260_parse_auto_config(codec);
- if (err < 0)
- goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC260_BASIC;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO) {
- setup_preset(codec, &alc260_presets[board_config]);
- spec->vmaster_nid = 0x08;
- }
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
+ alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc260_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4301,18 +4978,10 @@ static int patch_alc260(struct hda_codec *codec)
set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
- else
- codec->patch_ops.build_controls = __alc_build_controls;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc260_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -4333,9 +5002,6 @@ static int patch_alc260(struct hda_codec *codec)
* In addition, an independent DAC for the multi-playback (not used in this
* driver yet).
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc882_loopbacks alc880_loopbacks
-#endif
/*
* Pin config fixes
@@ -4346,11 +5012,14 @@ enum {
ALC882_FIXUP_PB_M5210,
ALC882_FIXUP_ACER_ASPIRE_7736,
ALC882_FIXUP_ASUS_W90V,
+ ALC889_FIXUP_CD,
ALC889_FIXUP_VAIO_TT,
ALC888_FIXUP_EEE1601,
ALC882_FIXUP_EAPD,
ALC883_FIXUP_EAPD,
ALC883_FIXUP_ACER_EAPD,
+ ALC882_FIXUP_GPIO1,
+ ALC882_FIXUP_GPIO2,
ALC882_FIXUP_GPIO3,
ALC889_FIXUP_COEF,
ALC882_FIXUP_ASUS_W2JC,
@@ -4358,6 +5027,9 @@ enum {
ALC882_FIXUP_ACER_ASPIRE_8930G,
ALC882_FIXUP_ASPIRE_8930G_VERBS,
ALC885_FIXUP_MACPRO_GPIO,
+ ALC889_FIXUP_DAC_ROUTE,
+ ALC889_FIXUP_MBP_VREF,
+ ALC889_FIXUP_IMAC91_VREF,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -4411,6 +5083,76 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
alc882_gpio_mute(codec, 1, 0);
}
+/* Fix the connection of some pins for ALC889:
+ * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
+ * work correctly (bko#42740)
+ */
+static void alc889_fixup_dac_route(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PRE_PROBE) {
+ /* fake the connections during parsing the tree */
+ hda_nid_t conn1[2] = { 0x0c, 0x0d };
+ hda_nid_t conn2[2] = { 0x0e, 0x0f };
+ snd_hda_override_conn_list(codec, 0x14, 2, conn1);
+ snd_hda_override_conn_list(codec, 0x15, 2, conn1);
+ snd_hda_override_conn_list(codec, 0x18, 2, conn2);
+ snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
+ } else if (action == ALC_FIXUP_ACT_PROBE) {
+ /* restore the connections */
+ hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
+ snd_hda_override_conn_list(codec, 0x14, 5, conn);
+ snd_hda_override_conn_list(codec, 0x15, 5, conn);
+ snd_hda_override_conn_list(codec, 0x18, 5, conn);
+ snd_hda_override_conn_list(codec, 0x1a, 5, conn);
+ }
+}
+
+/* Set VREF on HP pin */
+static void alc889_fixup_mbp_vref(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ static hda_nid_t nids[2] = { 0x14, 0x15 };
+ int i;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
+ unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
+ if (get_defcfg_device(val) != AC_JACK_HP_OUT)
+ continue;
+ val = snd_hda_codec_read(codec, nids[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val |= AC_PINCTL_VREF_80;
+ snd_hda_codec_write(codec, nids[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ spec->keep_vref_in_automute = 1;
+ break;
+ }
+}
+
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ static hda_nid_t nids[2] = { 0x18, 0x1a };
+ int i;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
+ unsigned int val;
+ val = snd_hda_codec_read(codec, nids[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val |= AC_PINCTL_VREF_50;
+ snd_hda_codec_write(codec, nids[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ }
+ spec->keep_vref_in_automute = 1;
+}
+
static const struct alc_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = ALC_FIXUP_PINS,
@@ -4447,6 +5189,13 @@ static const struct alc_fixup alc882_fixups[] = {
{ }
}
},
+ [ALC889_FIXUP_CD] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1c, 0x993301f0 }, /* CD */
+ { }
+ }
+ },
[ALC889_FIXUP_VAIO_TT] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
@@ -4489,6 +5238,14 @@ static const struct alc_fixup alc882_fixups[] = {
{ }
}
},
+ [ALC882_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
+ [ALC882_FIXUP_GPIO2] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio2_init_verbs,
+ },
[ALC882_FIXUP_GPIO3] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = alc_gpio3_init_verbs,
@@ -4558,6 +5315,22 @@ static const struct alc_fixup alc882_fixups[] = {
.type = ALC_FIXUP_FUNC,
.v.func = alc885_fixup_macpro_gpio,
},
+ [ALC889_FIXUP_DAC_ROUTE] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_dac_route,
+ },
+ [ALC889_FIXUP_MBP_VREF] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_mbp_vref,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_GPIO1,
+ },
+ [ALC889_FIXUP_IMAC91_VREF] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_imac91_vref,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_GPIO1,
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -4582,6 +5355,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
ALC882_FIXUP_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
+ SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
@@ -4590,14 +5364,30 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
/* All Apple entries are in codec SSIDs */
+ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -4619,14 +5409,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc882_quirks.c"
-#endif
-
static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -4650,45 +5436,15 @@ static int patch_alc882(struct hda_codec *codec)
if (err < 0)
goto error;
- board_config = alc_board_config(codec, ALC882_MODEL_LAST,
- alc882_models, NULL);
- if (board_config < 0)
- board_config = alc_board_codec_sid_config(codec,
- ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
+ alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
alc_auto_parse_customize_define(codec);
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc882_parse_auto_config(codec);
- if (err < 0)
- goto error;
- }
-
- if (board_config != ALC_MODEL_AUTO) {
- setup_preset(codec, &alc882_presets[board_config]);
- spec->vmaster_nid = 0x0c;
- }
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc882_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4697,18 +5453,9 @@ static int patch_alc882(struct hda_codec *codec)
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
- else
- codec->patch_ops.build_controls = __alc_build_controls;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc882_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -4735,7 +5482,6 @@ enum {
ALC262_FIXUP_FSC_H270,
ALC262_FIXUP_HP_Z200,
ALC262_FIXUP_TYAN,
- ALC262_FIXUP_TOSHIBA_RX1,
ALC262_FIXUP_LENOVO_3000,
ALC262_FIXUP_BENQ,
ALC262_FIXUP_BENQ_T31,
@@ -4765,16 +5511,6 @@ static const struct alc_fixup alc262_fixups[] = {
{ }
}
},
- [ALC262_FIXUP_TOSHIBA_RX1] = {
- .type = ALC_FIXUP_PINS,
- .v.pins = (const struct alc_pincfg[]) {
- { 0x14, 0x90170110 }, /* speaker */
- { 0x15, 0x0421101f }, /* HP */
- { 0x1a, 0x40f000f0 }, /* N/A */
- { 0x1b, 0x40f000f0 }, /* N/A */
- { 0x1e, 0x40f000f0 }, /* N/A */
- }
- },
[ALC262_FIXUP_LENOVO_3000] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -4807,8 +5543,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
- SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
- ALC262_FIXUP_TOSHIBA_RX1),
SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
@@ -4817,10 +5551,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
};
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc262_loopbacks alc880_loopbacks
-#endif
-
/*
*/
static int patch_alc262(struct hda_codec *codec)
@@ -4860,15 +5590,6 @@ static int patch_alc262(struct hda_codec *codec)
if (err < 0)
goto error;
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
if (err < 0)
@@ -4876,16 +5597,10 @@ static int patch_alc262(struct hda_codec *codec)
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc262_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -4979,17 +5694,7 @@ static int patch_alc268(struct hda_codec *codec)
(0 << AC_AMPCAP_MUTE_SHIFT));
}
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
return 0;
@@ -5002,10 +5707,6 @@ static int patch_alc268(struct hda_codec *codec)
/*
* ALC269
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc269_loopbacks alc880_loopbacks
-#endif
-
static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
@@ -5027,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
/* NID is set in alc_build_pcms */
};
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
-{
- switch (codec->subsystem_id) {
- case 0x103c1586:
- return 1;
- }
- return 0;
-}
-
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
-{
- /* update mute-LED according to the speaker mute state */
- if (nid == 0x01 || nid == 0x14) {
- int pinval;
- if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)
- pinval = 0x24;
- else
- pinval = 0x20;
- /* mic2 vref pin is used for mute LED control */
- snd_hda_codec_update_cache(codec, 0x19, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinval);
- }
- return alc_check_power_status(codec, nid);
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-
/* different alc269-variants */
enum {
ALC269_TYPE_ALC269VA,
@@ -5206,6 +5878,31 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec,
spec->automute_hook = alc269_quanta_automute;
}
+/* update mute-LED according to the speaker mute state via mic2 VREF pin */
+static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
+{
+ struct hda_codec *codec = private_data;
+ unsigned int pinval = enabled ? 0x20 : 0x24;
+ snd_hda_codec_update_cache(codec, 0x19, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pinval);
+}
+
+static void alc269_fixup_mic2_mute(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ switch (action) {
+ case ALC_FIXUP_ACT_BUILD:
+ spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook;
+ snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
+ /* fallthru */
+ case ALC_FIXUP_ACT_INIT:
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+ break;
+ }
+}
+
enum {
ALC269_FIXUP_SONY_VAIO,
ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -5223,6 +5920,7 @@ enum {
ALC269_FIXUP_DMIC,
ALC269VB_FIXUP_AMIC,
ALC269VB_FIXUP_DMIC,
+ ALC269_FIXUP_MIC2_MUTE_LED,
};
static const struct alc_fixup alc269_fixups[] = {
@@ -5343,9 +6041,14 @@ static const struct alc_fixup alc269_fixups[] = {
{ }
},
},
+ [ALC269_FIXUP_MIC2_MUTE_LED] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc269_fixup_mic2_mute,
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
@@ -5368,7 +6071,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
-#if 1
+#if 0
/* Below is a quirk table taken from the old code.
* Basically the device should work as is without the fixup table.
* If BIOS doesn't give a proper info, enable the corresponding
@@ -5377,7 +6080,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
@@ -5427,10 +6129,14 @@ static const struct alc_model_fixup alc269_fixup_models[] = {
};
-static int alc269_fill_coef(struct hda_codec *codec)
+static void alc269_fill_coef(struct hda_codec *codec)
{
+ struct alc_spec *spec = codec->spec;
int val;
+ if (spec->codec_variant != ALC269_TYPE_ALC269VB)
+ return;
+
if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
alc_write_coef_idx(codec, 0xf, 0x960b);
alc_write_coef_idx(codec, 0xe, 0x8817);
@@ -5465,8 +6171,6 @@ static int alc269_fill_coef(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0x4); /* HP */
alc_write_coef_idx(codec, 0x4, val | (1<<11));
-
- return 0;
}
/*
@@ -5510,6 +6214,7 @@ static int patch_alc269(struct hda_codec *codec)
}
if (err < 0)
goto error;
+ spec->init_hook = alc269_fill_coef;
alc269_fill_coef(codec);
}
@@ -5522,15 +6227,6 @@ static int patch_alc269(struct hda_codec *codec)
if (err < 0)
goto error;
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
if (err < 0)
@@ -5538,21 +6234,13 @@ static int patch_alc269(struct hda_codec *codec)
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
#ifdef CONFIG_PM
codec->patch_ops.resume = alc269_resume;
#endif
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc269_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc269_loopbacks;
- if (alc269_mic2_for_mute_led(codec))
- codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -5572,25 +6260,43 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc861_loopbacks[] = {
- { 0x15, HDA_INPUT, 0 },
- { 0x15, HDA_INPUT, 1 },
- { 0x15, HDA_INPUT, 2 },
- { 0x15, HDA_INPUT, 3 },
- { } /* end */
-};
-#endif
-
-
/* Pin config fixes */
enum {
- PINFIX_FSC_AMILO_PI1505,
- PINFIX_ASUS_A6RP,
+ ALC861_FIXUP_FSC_AMILO_PI1505,
+ ALC861_FIXUP_AMP_VREF_0F,
+ ALC861_FIXUP_NO_JACK_DETECT,
+ ALC861_FIXUP_ASUS_A6RP,
};
+/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
+static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ val = snd_hda_codec_read(codec, 0x0f, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
+ val |= AC_PINCTL_IN_EN;
+ val |= AC_PINCTL_VREF_50;
+ snd_hda_codec_write(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ spec->keep_vref_in_automute = 1;
+}
+
+/* suppress the jack-detection */
+static void alc_fixup_no_jack_detect(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PRE_PROBE)
+ codec->no_jack_detect = 1;
+}
+
static const struct alc_fixup alc861_fixups[] = {
- [PINFIX_FSC_AMILO_PI1505] = {
+ [ALC861_FIXUP_FSC_AMILO_PI1505] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x0b, 0x0221101f }, /* HP */
@@ -5598,20 +6304,29 @@ static const struct alc_fixup alc861_fixups[] = {
{ }
}
},
- [PINFIX_ASUS_A6RP] = {
- .type = ALC_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* node 0x0f VREF seems controlling the master output */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
- { }
- },
+ [ALC861_FIXUP_AMP_VREF_0F] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861_fixup_asus_amp_vref_0f,
+ },
+ [ALC861_FIXUP_NO_JACK_DETECT] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_no_jack_detect,
},
+ [ALC861_FIXUP_ASUS_A6RP] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861_fixup_asus_amp_vref_0f,
+ .chained = true,
+ .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+ }
};
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP),
- SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
- SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
+ SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
{}
};
@@ -5638,15 +6353,6 @@ static int patch_alc861(struct hda_codec *codec)
if (err < 0)
goto error;
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x23);
if (err < 0)
@@ -5654,16 +6360,13 @@ static int patch_alc861(struct hda_codec *codec)
set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->power_hook = alc_power_eapd;
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc861_loopbacks;
#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
return 0;
error:
@@ -5678,10 +6381,6 @@ static int patch_alc861(struct hda_codec *codec)
*
* In addition, an independent DAC
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc861vd_loopbacks alc880_loopbacks
-#endif
-
static int alc861vd_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
@@ -5762,15 +6461,6 @@ static int patch_alc861vd(struct hda_codec *codec)
add_verb(spec, alc660vd_eapd_verbs);
}
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x23);
if (err < 0)
@@ -5778,16 +6468,11 @@ static int patch_alc861vd(struct hda_codec *codec)
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc861vd_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -5807,9 +6492,6 @@ static int patch_alc861vd(struct hda_codec *codec)
* In addition, an independent DAC for the multi-playback (not used in this
* driver yet).
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc662_loopbacks alc880_loopbacks
-#endif
/*
* BIOS auto configuration
@@ -5859,6 +6541,7 @@ enum {
ALC662_FIXUP_ASUS_MODE6,
ALC662_FIXUP_ASUS_MODE7,
ALC662_FIXUP_ASUS_MODE8,
+ ALC662_FIXUP_NO_JACK_DETECT,
};
static const struct alc_fixup alc662_fixups[] = {
@@ -6004,6 +6687,10 @@ static const struct alc_fixup alc662_fixups[] = {
.chained = true,
.chain_id = ALC662_FIXUP_SKU_IGNORE
},
+ [ALC662_FIXUP_NO_JACK_DETECT] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_no_jack_detect,
+ },
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6012,6 +6699,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+ SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
@@ -6133,15 +6821,6 @@ static int patch_alc662(struct hda_codec *codec)
if (err < 0)
goto error;
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
if (err < 0)
@@ -6161,16 +6840,10 @@ static int patch_alc662(struct hda_codec *codec)
}
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc662_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
@@ -6210,11 +6883,7 @@ static int patch_alc680(struct hda_codec *codec)
return err;
}
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
codec->patch_ops = alc_patch_ops;
- spec->init_hook = alc_auto_init_std;
return 0;
}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 948f0be2f4f3..33a9946b492c 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -99,6 +99,7 @@ enum {
STAC_DELL_VOSTRO_3500,
STAC_92HD83XXX_HP_cNB11_INTQUAD,
STAC_HP_DV7_4000,
+ STAC_HP_ZEPHYR,
STAC_92HD83XXX_MODELS
};
@@ -309,6 +310,8 @@ struct sigmatel_spec {
unsigned long auto_capvols[MAX_ADCS_NUM];
unsigned auto_dmic_cnt;
hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
+
+ struct hda_vmaster_mute_hook vmaster_mute;
};
static const hda_nid_t stac9200_adc_nids[1] = {
@@ -662,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
static int stac_vrefout_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
{
@@ -686,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec,
return 1;
}
-#endif
static unsigned int stac92xx_vref_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
@@ -894,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = {
{}
};
+static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = {
+ { 0x22, 0x785, 0x43 },
+ { 0x22, 0x782, 0xe0 },
+ { 0x22, 0x795, 0x00 },
+ {}
+};
+
static const struct hda_verb stac92hd71bxx_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -999,8 +1007,8 @@ static const struct hda_verb stac9205_core_init[] = {
}
static const struct snd_kcontrol_new stac9200_mixer[] = {
- 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_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
{ } /* end */
@@ -1027,8 +1035,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
};
static const struct snd_kcontrol_new stac925x_mixer[] = {
- HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT),
{ } /* end */
};
@@ -1060,34 +1068,25 @@ static struct snd_kcontrol_new stac_smux_mixer = {
.put = stac92xx_smux_enum_put,
};
-static const char * const slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
+static const char * const slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker", "IEC958",
NULL
};
-static const char * const slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "IEC958 Playback Switch",
- NULL
-};
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled);
+
+static void stac92xx_vmaster_hook(void *private_data, int val)
+{
+ stac92xx_update_led_status(private_data, val);
+}
static void stac92xx_free_kctls(struct hda_codec *codec);
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
+ unsigned int vmaster_tlv[4];
int err;
int i;
@@ -1144,22 +1143,28 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
/* if we have no master control, let's create it */
- if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
- unsigned int vmaster_tlv[4];
- snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
- 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)
- return err;
- }
- if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, slave_sws);
+ snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+ 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_pfxs,
+ "Playback Volume");
+ if (err < 0)
+ return err;
+
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, slave_pfxs,
+ "Playback Switch", true,
+ &spec->vmaster_mute.sw_kctl);
+ if (err < 0)
+ return err;
+
+ if (spec->gpio_led) {
+ spec->vmaster_mute.hook = stac92xx_vmaster_hook;
+ err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
if (err < 0)
return err;
}
@@ -1636,6 +1641,12 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = {
0x40f000f0, 0x40f000f0,
};
+static const unsigned int hp_zephyr_pin_configs[10] = {
+ 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310,
+ 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130,
+ 0, 0,
+};
+
static const unsigned int hp_cNB11_intquad_pin_configs[10] = {
0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110,
0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130,
@@ -1649,6 +1660,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
[STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs,
[STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
[STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
+ [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs,
};
static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
@@ -1659,6 +1671,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
[STAC_DELL_VOSTRO_3500] = "dell-vostro-3500",
[STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
[STAC_HP_DV7_4000] = "hp-dv7-4000",
+ [STAC_HP_ZEPHYR] = "hp-zephyr",
};
static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1711,6 +1724,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+ "HP", STAC_HP_ZEPHYR),
+ {} /* terminator */
+};
+
+static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = {
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+ "HP", STAC_HP_ZEPHYR),
{} /* terminator */
};
@@ -4410,8 +4431,7 @@ static int stac92xx_init(struct hda_codec *codec)
snd_hda_jack_report_sync(codec);
/* sync mute LED */
- if (spec->gpio_led)
- hda_call_check_power_status(codec, 0x01);
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
@@ -4629,7 +4649,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
if (no_hp_sensing(spec, i))
continue;
- if (presence)
+ if (1 /*presence*/)
stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
#if 0 /* FIXME */
/* Resetting the pinctl like below may lead to (a sort of) regressions
@@ -4989,7 +5009,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
static int stac92xx_pre_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -5024,83 +5043,41 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
afg_power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
}
+#else
+#define stac92xx_suspend NULL
+#define stac92xx_resume NULL
+#define stac92xx_pre_resume NULL
+#define stac92xx_set_power_state NULL
+#endif /* CONFIG_PM */
-/*
- * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
- * as mute LED state is updated in check_power_status hook
- */
-static int stac92xx_update_led_status(struct hda_codec *codec)
+/* update mute-LED accoring to the master switch */
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled)
{
struct sigmatel_spec *spec = codec->spec;
- int i, num_ext_dacs, muted = 1;
- unsigned int muted_lvl, notmtd_lvl;
- hda_nid_t nid;
+ int muted = !enabled;
if (!spec->gpio_led)
- return 0;
+ return;
+
+ /* LED state is inverted on these systems */
+ if (spec->gpio_led_polarity)
+ muted = !muted;
- for (i = 0; i < spec->multiout.num_dacs; i++) {
- nid = spec->multiout.dac_nids[i];
- if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* something heard */
- break;
- }
- }
- if (muted && spec->multiout.hp_nid)
- if (!(snd_hda_codec_amp_read(codec,
- spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* HP is not muted */
- }
- num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
- for (i = 0; muted && i < num_ext_dacs; i++) {
- nid = spec->multiout.extra_out_nid[i];
- if (nid == 0)
- break;
- if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* extra output is not muted */
- }
- }
/*polarity defines *not* muted state level*/
if (!spec->vref_mute_led_nid) {
if (muted)
spec->gpio_data &= ~spec->gpio_led; /* orange */
else
spec->gpio_data |= spec->gpio_led; /* white */
-
- if (!spec->gpio_led_polarity) {
- /* LED state is inverted on these systems */
- spec->gpio_data ^= spec->gpio_led;
- }
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data);
} else {
- notmtd_lvl = spec->gpio_led_polarity ?
- AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
- muted_lvl = spec->gpio_led_polarity ?
- AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
- spec->vref_led = muted ? muted_lvl : notmtd_lvl;
+ spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
stac_vrefout_set(codec, spec->vref_mute_led_nid,
spec->vref_led);
}
- return 0;
}
-/*
- * use power check for controlling mute led of HP notebooks
- */
-static int stac92xx_check_power_status(struct hda_codec *codec,
- hda_nid_t nid)
-{
- stac92xx_update_led_status(codec);
-
- return 0;
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-#endif /* CONFIG_PM */
-
static const struct hda_codec_ops stac92xx_patch_ops = {
.build_controls = stac92xx_build_controls,
.build_pcms = stac92xx_build_pcms,
@@ -5580,6 +5557,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
STAC_92HD83XXX_MODELS,
stac92hd83xxx_models,
stac92hd83xxx_cfg_tbl);
+ /* check codec subsystem id if not found */
+ if (spec->board_config < 0)
+ spec->board_config =
+ snd_hda_check_board_codec_sid_config(codec,
+ STAC_92HD83XXX_MODELS, stac92hd83xxx_models,
+ stac92hd83xxx_codec_id_cfg_tbl);
again:
if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
@@ -5590,12 +5573,17 @@ again:
codec->patch_ops = stac92xx_patch_ops;
+ switch (spec->board_config) {
+ case STAC_HP_ZEPHYR:
+ spec->init = stac92hd83xxx_hp_zephyr_init;
+ break;
+ }
+
if (find_mute_led_cfg(codec, -1/*no default cfg*/))
snd_printd("mute LED gpio %d polarity %d\n",
spec->gpio_led,
spec->gpio_led_polarity);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) {
if (!spec->vref_mute_led_nid) {
spec->gpio_mask |= spec->gpio_led;
@@ -5605,11 +5593,10 @@ again:
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
}
+#ifdef CONFIG_PM
codec->patch_ops.pre_resume = stac92xx_pre_resume;
- codec->patch_ops.check_power_status =
- stac92xx_check_power_status;
+#endif
}
-#endif
err = stac92xx_parse_auto_config(codec);
if (!err) {
@@ -5906,7 +5893,6 @@ again:
spec->gpio_led,
spec->gpio_led_polarity);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) {
if (!spec->vref_mute_led_nid) {
spec->gpio_mask |= spec->gpio_led;
@@ -5916,11 +5902,10 @@ again:
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
}
+#ifdef CONFIG_PM
codec->patch_ops.pre_resume = stac92xx_pre_resume;
- codec->patch_ops.check_power_status =
- stac92xx_check_power_status;
+#endif
}
-#endif
spec->multiout.dac_nids = spec->dac_nids;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 03e63fed9caf..06214fdc9486 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -199,6 +199,9 @@ struct via_spec {
unsigned int no_pin_power_ctl;
enum VIA_HDA_CODEC codec_type;
+ /* analog low-power control */
+ bool alc_mode;
+
/* smart51 setup */
unsigned int smart51_nums;
hda_nid_t smart51_pins[2];
@@ -547,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec,
pin = path->path[path->depth - 1];
init_output_pin(codec, pin, pin_type);
- caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+ if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
+ caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+ else
+ caps = 0;
if (caps & AC_AMPCAP_MUTE) {
unsigned int val;
val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
@@ -642,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
/* init ADCs */
for (i = 0; i < spec->num_adc_nids; i++) {
+ hda_nid_t nid = spec->adc_nids[i];
+ if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) ||
+ !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE))
+ continue;
snd_hda_codec_write(codec, spec->adc_nids[i], 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_UNMUTE(0));
@@ -663,6 +673,9 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
/* init input-src */
for (i = 0; i < spec->num_adc_nids; i++) {
int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx;
+ /* secondary ADCs must have the unique MUX */
+ if (i > 0 && !spec->mux_nids[i])
+ break;
if (spec->mux_nids[adc_idx]) {
int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;
snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
@@ -687,6 +700,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
}
}
+static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int parm)
+{
+ if (snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_POWER_STATE, 0) == parm)
+ return;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int *affected_parm)
{
@@ -709,7 +731,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
} else
parm = AC_PWRST_D3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, nid, parm);
}
static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
@@ -749,6 +771,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
return 0;
spec->no_pin_power_ctl = val;
set_widgets_power_state(codec);
+ analog_low_current_mode(codec);
return 1;
}
@@ -1036,13 +1059,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)
}
/* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
{
struct via_spec *spec = codec->spec;
bool enable;
unsigned int verb, parm;
- enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+ if (spec->no_pin_power_ctl)
+ enable = false;
+ else
+ enable = is_aa_path_mute(codec) && !spec->opened_streams;
+ if (enable == spec->alc_mode && !force)
+ return;
+ spec->alc_mode = enable;
/* decide low current mode's verb & parameter */
switch (spec->codec_type) {
@@ -1074,6 +1103,11 @@ static void analog_low_current_mode(struct hda_codec *codec)
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
}
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+ return __analog_low_current_mode(codec, false);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -1418,25 +1452,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = {
/*
* slave controls for virtual master
*/
-static const char * const via_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- NULL,
-};
-
-static const char * const via_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
+static const char * const via_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker",
NULL,
};
@@ -1446,6 +1464,7 @@ static int via_build_controls(struct hda_codec *codec)
struct snd_kcontrol *kctl;
int err, i;
+ spec->no_pin_power_ctl = 1;
if (spec->set_widgets_power_state)
if (!via_clone_control(spec, &via_pin_power_ctl_enum))
return -ENOMEM;
@@ -1480,13 +1499,15 @@ static int via_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, via_slave_vols);
+ vmaster_tlv, via_slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, via_slave_sws);
+ NULL, via_slave_pfxs,
+ "Playback Switch");
if (err < 0)
return err;
}
@@ -1494,15 +1515,13 @@ static int via_build_controls(struct hda_codec *codec)
/* assign Capture Source enums to NID */
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
+ if (!spec->mux_nids[i])
+ continue;
err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]);
if (err < 0)
return err;
}
- /* init power states */
- set_widgets_power_state(codec);
- analog_low_current_mode(codec);
-
via_free_kctls(codec); /* no longer needed */
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
@@ -2295,10 +2314,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
if (mux) {
/* switch to D0 beofre change index */
- if (snd_hda_codec_read(codec, mux, 0,
- AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
- snd_hda_codec_write(codec, mux, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, mux, AC_PWRST_D0);
snd_hda_codec_write(codec, mux, 0,
AC_VERB_SET_CONNECT_SEL,
spec->inputs[cur].mux_idx);
@@ -2467,6 +2483,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
+ const char *prev_label = NULL;
+ int type_idx = 0;
int i, err;
for (i = 0; i < cfg->num_inputs; i++) {
@@ -2481,8 +2499,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS))
continue;
label = hda_get_autocfg_input_label(codec, cfg, i);
+ if (prev_label && !strcmp(label, prev_label))
+ type_idx++;
+ else
+ type_idx = 0;
+ prev_label = label;
snprintf(name, sizeof(name), "%s Boost Volume", label);
- 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(pin, 3, 0, HDA_INPUT));
if (err < 0)
return err;
@@ -2776,6 +2799,10 @@ static int via_init(struct hda_codec *codec)
for (i = 0; i < spec->num_iverbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ /* init power states */
+ set_widgets_power_state(codec);
+ __analog_low_current_mode(codec, true);
+
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_speaker_out(codec);
@@ -2922,9 +2949,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW 0/1 (13h/14h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -2932,8 +2959,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x19, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW6 (22h), SW2 (26h), AOW2 (24h) */
if (is_8ch) {
@@ -2941,20 +2968,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x22, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x24, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x24, parm);
} else if (codec->vendor_id == 0x11064397) {
/* PW7(23h), SW2(27h), AOW2(25h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x23, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
+ update_power_state(codec, 0x25, parm);
}
/* PW 3/4/7 (1ch/1dh/23h) */
@@ -2966,17 +2989,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x23, &parm);
/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
if (is_8ch) {
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
+ update_power_state(codec, 0x27, parm);
} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
}
static int patch_vt1708S(struct hda_codec *codec);
@@ -3149,10 +3168,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x12, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x20, parm);
/* outputs */
/* PW 3/4 (16h/17h) */
@@ -3160,10 +3179,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
set_pin_power_state(codec, 0x17, &parm);
set_pin_power_state(codec, 0x16, &parm);
/* MW0 (1ah), AOW 0/1 (10h/1dh) */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x1d, parm);
}
static int patch_vt1702(struct hda_codec *codec)
@@ -3228,52 +3246,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x27, &parm);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, parm);
+ update_power_state(codec, 0xb, parm);
/* PW2 (26h), AOW2 (ah) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2b, &parm);
- snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0xa, parm);
/* PW0 (24h), AOW0 (8h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (!spec->hp_independent_mode) /* check for redirected HP */
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
/* PW1 (25h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2a, &parm);
- snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x9, parm);
if (spec->hp_independent_mode) {
/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1b, parm);
+ update_power_state(codec, 0x34, parm);
+ update_power_state(codec, 0xc, parm);
}
}
@@ -3433,8 +3447,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW0(13h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x1e, &parm);
@@ -3442,12 +3456,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
if (spec->dmic_enabled)
set_pin_power_state(codec, 0x22, &parm);
else
- snd_hda_codec_write(codec, 0x22, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x22, AC_PWRST_D3);
/* SW2(26h), AIW1(14h) */
- snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -3456,8 +3469,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
/* Smart 5.1 PW2(1bh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW7 (23h), SW3 (27h), AOW3 (25h) */
parm = AC_PWRST_D3;
@@ -3465,12 +3478,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
/* Smart 5.1 PW1(1ah) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
/* Smart 5.1 PW5(1eh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1e, &parm);
- snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* Mono out */
/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
@@ -3486,9 +3499,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
mono_out = 1;
}
parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
- snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x28, parm);
+ update_power_state(codec, 0x29, parm);
+ update_power_state(codec, 0x2a, parm);
/* PW 3/4 (1ch/1dh) */
parm = AC_PWRST_D3;
@@ -3496,15 +3509,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
set_pin_power_state(codec, 0x1d, &parm);
/* HP Independent Mode, power on AOW3 */
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* force to D0 for internal Speaker */
/* MW0 (16h), AOW0 (10h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- mono_out ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
}
static int patch_vt1716S(struct hda_codec *codec)
@@ -3580,54 +3590,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
if (spec->codec_type == VT1802) {
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
} else {
/* PW4 (26h), MW4 (1ch), MUX4(37h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x37, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x37, parm);
}
if (spec->codec_type == VT1802) {
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
} else {
/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x19, parm);
+ update_power_state(codec, 0x35, parm);
}
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Class-D */
/* PW0 (24h), MW0(18h/14h), MUX0(34h) */
@@ -3637,12 +3638,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
set_pin_power_state(codec, 0x24, &parm);
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x14, parm);
else
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x34, parm);
/* Mono Out */
present = snd_hda_jack_detect(codec, 0x26);
@@ -3650,28 +3649,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802) {
/* PW15 (33h), MW8(1ch), MUX8(3ch) */
- snd_hda_codec_write(codec, 0x33, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x33, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x3c, parm);
} else {
/* PW15 (31h), MW8(17h), MUX8(3bh) */
- snd_hda_codec_write(codec, 0x31, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x31, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x3b, parm);
}
/* MW9 (21h) */
if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x21, AC_PWRST_D0);
else
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x21, AC_PWRST_D3);
}
/* patch for vt2002P */
@@ -3731,30 +3722,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x8, AC_PWRST_D0);
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Internal Speaker */
/* PW0 (24h), MW0(14h), MUX0(34h) */
@@ -3763,15 +3752,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x14, AC_PWRST_D3);
+ update_power_state(codec, 0x34, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x14, AC_PWRST_D0);
+ update_power_state(codec, 0x34, AC_PWRST_D0);
}
@@ -3782,26 +3767,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x31, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x1c, AC_PWRST_D3);
+ update_power_state(codec, 0x3c, AC_PWRST_D3);
+ update_power_state(codec, 0x3e, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x1c, AC_PWRST_D0);
+ update_power_state(codec, 0x3c, AC_PWRST_D0);
+ update_power_state(codec, 0x3e, AC_PWRST_D0);
}
/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x33, &parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1d, parm);
+ update_power_state(codec, 0x3d, parm);
}
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 92362973764d..812d10e43ae0 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice,
ice->hw_rates);
}
+/* if the card has the internal rate locked (is_pro_locked), limit runtime
+ hw rates to the current internal rate only.
+*/
+static void constrain_rate_if_locked(struct snd_pcm_substream *substream)
+{
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int rate;
+ if (is_pro_rate_locked(ice)) {
+ rate = ice->get_rate(ice);
+ if (rate >= runtime->hw.rate_min
+ && rate <= runtime->hw.rate_max) {
+ runtime->hw.rate_min = rate;
+ runtime->hw.rate_max = rate;
+ }
+ }
+}
+
+
/* multi-channel playback needs alignment 8x32bit regardless of the channels
* actually used
*/
@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->pro_open)
ice->pro_open(ice, substream);
return 0;
@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->pro_open)
ice->pro_open(ice, substream);
return 0;
@@ -1215,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream);
return 0;
@@ -1251,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream);
return 0;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 9f3b01bb72c8..e0a4263baa20 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2102,6 +2102,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x161f,
+ .subdevice = 0x202f,
+ .name = "Gateway M520",
+ .type = AC97_TUNE_INV_EAPD
+ },
+ {
+ .subvendor = 0x161f,
.subdevice = 0x203a,
.name = "Gateway 4525GZ", /* AD1981B */
.type = AC97_TUNE_INV_EAPD
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 26c7e8bcb229..c0dbb52d45be 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
mutex_lock(&chip->mutex);
reg = oxygen_read_ac97(chip, codec, index);
mutex_unlock(&chip->mutex);
- value->value.integer.value[0] = 31 - (reg & 0x1f);
- if (stereo)
- value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
+ if (!stereo) {
+ value->value.integer.value[0] = 31 - (reg & 0x1f);
+ } else {
+ value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f);
+ value->value.integer.value[1] = 31 - (reg & 0x1f);
+ }
return 0;
}
@@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
mutex_lock(&chip->mutex);
oldreg = oxygen_read_ac97(chip, codec, index);
- newreg = oldreg;
- newreg = (newreg & ~0x1f) |
- (31 - (value->value.integer.value[0] & 0x1f));
- if (stereo)
- newreg = (newreg & ~0x1f00) |
- ((31 - (value->value.integer.value[1] & 0x1f)) << 8);
- else
- newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8);
+ if (!stereo) {
+ newreg = oldreg & ~0x1f;
+ newreg |= 31 - (value->value.integer.value[0] & 0x1f);
+ } else {
+ newreg = oldreg & ~0x1f1f;
+ newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8;
+ newreg |= 31 - (value->value.integer.value[1] & 0x1f);
+ }
change = newreg != oldreg;
if (change)
oxygen_write_ac97(chip, codec, index, newreg);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index cc9f6c83d661..bc030a2088da 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6333,6 +6333,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
hw->ops.open = snd_hdspm_hwdep_dummy_op;
hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+ hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
hw->ops.release = snd_hdspm_hwdep_dummy_op;
return 0;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 12a9a2b03387..a8159b81e9c4 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2317,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++)
chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
+ pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY,
+ &chip->saved_dsxg_legacy);
+ pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+ &chip->saved_dsxg_elegacy);
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
snd_ymfpci_disable_dsp(chip);
@@ -2351,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci)
snd_ac97_resume(chip->ac97);
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY,
+ chip->saved_dsxg_legacy);
+ pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+ chip->saved_dsxg_elegacy);
+
/* start hw again */
if (chip->start_count > 0) {
spin_lock_irq(&chip->reg_lock);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 35e662d270e6..91c985599d32 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -25,6 +25,9 @@ if SND_SOC
config SND_SOC_AC97_BUS
bool
+config SND_SOC_DMAENGINE_PCM
+ bool
+
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9ea8ac827adc..2feaf376e94b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,9 @@
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
snd-soc-core-objs += soc-pcm.o soc-io.o
+snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
+obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += atmel/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index a21ff459e5d3..9b84f985770e 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -362,7 +362,7 @@ static struct snd_pcm_ops atmel_pcm_ops = {
/*--------------------------------------------------------------------------*\
* ASoC platform driver
\*--------------------------------------------------------------------------*/
-static u64 atmel_pcm_dmamask = 0xffffffff;
+static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
@@ -373,7 +373,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &atmel_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = atmel_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 4ca667d477f9..f65f08beac31 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -46,29 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S|
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return err;
- }
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return err;
- }
-
/* Set the codec system clock for DAC and ADC */
err =
snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -91,7 +70,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route afeb9260_audio_map[] = {
{"Headphone Jack", NULL, "LHPOUT"},
{"Headphone Jack", NULL, "RHPOUT"},
@@ -106,13 +85,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- /* Add afeb9260 specific widgets */
- snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
- ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
- /* Set up afeb9260 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
@@ -129,6 +101,8 @@ static struct snd_soc_dai_link afeb9260_dai = {
.platform_name = "atmel_pcm-audio",
.codec_name = "tlv320aic23-codec.0-001a",
.init = afeb9260_tlv320aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &afeb9260_ops,
};
@@ -138,6 +112,11 @@ static struct snd_soc_card snd_soc_machine_afeb9260 = {
.owner = THIS_MODULE,
.dai_link = &afeb9260_dai,
.num_links = 1,
+
+ .dapm_widgets = tlv320aic23_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+ .dapm_routes = afeb9260_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map),
};
static struct platform_device *afeb9260_snd_device;
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 60962ce6cd4d..d542d4063771 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -40,20 +40,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
int ret = 0;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
/* set cpu DAI channel mapping */
ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
@@ -68,6 +56,9 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
.hw_params = bf5xx_ad1836_hw_params,
};
+#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
{
.name = "ad1836",
@@ -77,6 +68,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
{
.name = "ad1836",
@@ -86,6 +78,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 2d8d82dbc159..0e55e9f2a514 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -60,18 +60,6 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
SND_SOC_CLOCK_IN);
@@ -92,6 +80,9 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_ops bf5xx_ad193x_ops = {
.hw_params = bf5xx_ad193x_hw_params,
};
@@ -105,6 +96,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
{
.name = "ad193x",
@@ -114,6 +106,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 8e49508596da..61cc91d4a028 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -145,29 +145,8 @@ static int bf5xx_probe(struct snd_soc_card *card)
return 0;
}
-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->cpu_dai;
- int ret = 0;
-
- pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
- params_format(params));
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-
-static struct snd_soc_ops bf5xx_ad73311_ops = {
- .hw_params = bf5xx_ad73311_hw_params,
-};
+#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
{
@@ -177,7 +156,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
{
.name = "ad73311",
@@ -186,7 +165,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 030303238042..df3ac73f8778 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -49,7 +49,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int clk = 0;
int ret = 0;
@@ -75,21 +74,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
break;
}
- /*
- * CODEC is master for BCLK and LRC in this configuration.
- */
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
@@ -102,6 +86,10 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
.hw_params = bf5xx_ssm2602_hw_params,
};
+/* CODEC is master for BCLK and LRC in this configuration. */
+#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
{
.name = "ssm2602",
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
index 26b271c62efa..f3adbdbdd5e1 100644
--- a/sound/soc/blackfin/bfin-eval-adau1373.c
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -67,21 +67,10 @@ static int bfin_eval_adau1373_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 ret;
int pll_rate;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- 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)
- return ret;
-
switch (params_rate(params)) {
case 48000:
case 8000:
@@ -143,6 +132,8 @@ static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
.codec_name = "adau1373.0-001a",
.ops = &bfin_eval_adau1373_ops,
.init = bfin_eval_adau1373_codec_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
};
static struct snd_soc_card bfin_eval_adau1373 = {
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index c0064fa1dca6..b0531fc9d814 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -37,20 +37,9 @@ static int bfin_eval_adau1701_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 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)
- 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)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
SND_SOC_CLOCK_IN);
@@ -61,6 +50,9 @@ static struct snd_soc_ops bfin_eval_adau1701_ops = {
.hw_params = bfin_eval_adau1701_hw_params,
};
+#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
{
.name = "adau1701",
@@ -70,6 +62,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
{
.name = "adau1701",
@@ -79,6 +72,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
};
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 4ef079f95e2e..84b09987b7f3 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -34,20 +34,9 @@ static int bfin_eval_adav80x_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 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)
- 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)
- return ret;
-
ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
27000000, params_rate(params) * 256);
if (ret)
@@ -88,6 +77,8 @@ static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
.platform_name = "bfin-i2s-pcm-audio",
.init = bfin_eval_adav80x_codec_init,
.ops = &bfin_eval_adav80x_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
},
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7c205e77d83a..6508e8b790bb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
+ select SND_SOC_MAX9768 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
@@ -62,6 +63,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WL1273 if MFD_WL1273_CORE
select SND_SOC_WM1250_EV1 if I2C
select SND_SOC_WM2000 if I2C
+ select SND_SOC_WM2200 if I2C
select SND_SOC_WM5100 if I2C
select SND_SOC_WM8350 if MFD_WM8350
select SND_SOC_WM8400 if MFD_WM8400
@@ -292,6 +294,9 @@ config SND_SOC_WM1250_EV1
config SND_SOC_WM2000
tristate
+config SND_SOC_WM2200
+ tristate
+
config SND_SOC_WM5100
tristate
@@ -425,6 +430,9 @@ config SND_SOC_WM9713
config SND_SOC_LM4857
tristate
+config SND_SOC_MAX9768
+ tristate
+
config SND_SOC_MAX9877
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index de8078178f86..6662eb0cdcc0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -25,6 +25,7 @@ snd-soc-dmic-objs := dmic.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
+snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
@@ -51,6 +52,7 @@ snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
+snd-soc-wm2200-objs := wm2200.o
snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8400-objs := wm8400.o
@@ -129,6 +131,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
@@ -153,6 +156,7 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
+obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o
obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 982d201c2e86..12e3b4118557 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -277,7 +277,7 @@ static int ad1836_probe(struct snd_soc_codec *codec)
if (ad1836->type == AD1836) {
/* left/right diff:PGA/MUX */
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
- ret = snd_soc_add_controls(codec, ad1836_controls,
+ ret = snd_soc_add_codec_controls(codec, ad1836_controls,
ARRAY_SIZE(ad1836_controls));
if (ret)
return ret;
@@ -285,11 +285,11 @@ static int ad1836_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
}
- ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+ ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+ ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
if (ret)
return ret;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 9bba7f849464..8c39dddd7d00 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -228,7 +228,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
- snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls,
ARRAY_SIZE(ad1980_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 971ba4529171..44f59064d8de 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1244,8 +1244,6 @@ static int adau1373_probe(struct snd_soc_codec *codec)
return ret;
}
- codec->dapm.idle_bias_off = true;
-
if (pdata) {
if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
return -EINVAL;
@@ -1259,7 +1257,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
pdata->drc_setting[i]);
}
- snd_soc_add_controls(codec, adau1373_drc_controls,
+ snd_soc_add_codec_controls(codec, adau1373_drc_controls,
pdata->num_drc);
val = 0;
@@ -1284,7 +1282,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
}
if (!lineout_differential) {
- snd_soc_add_controls(codec, adau1373_lineout2_controls,
+ snd_soc_add_codec_controls(codec, adau1373_lineout2_controls,
ARRAY_SIZE(adau1373_lineout2_controls));
}
@@ -1340,6 +1338,7 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
.suspend = adau1373_suspend,
.resume = adau1373_resume,
.set_bias_level = adau1373_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
.reg_cache_default = adau1373_default_regs,
.reg_word_size = sizeof(uint8_t),
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 6b325ea03869..78e9ce48bb99 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -457,7 +457,6 @@ static int adau1701_probe(struct snd_soc_codec *codec)
{
int ret;
- codec->dapm.idle_bias_off = 1;
codec->control_data = to_i2c_client(codec->dev);
ret = adau1701_load_firmware(codec);
@@ -473,6 +472,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver adau1701_codec_drv = {
.probe = adau1701_probe,
.set_bias_level = adau1701_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ADAU1701_NUM_REGS,
.reg_word_size = sizeof(u16),
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index d27b5e4cce99..ceb96ecf5588 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -46,75 +46,15 @@
#define DRV_NAME "ak4104-codec"
struct ak4104_private {
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct regmap *regmap;
};
-static int ak4104_fill_cache(struct snd_soc_codec *codec)
-{
- int i;
- u8 *reg_cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- int ret = spi_w8r8(spi, i | AK4104_READ);
- if (ret < 0) {
- dev_err(&spi->dev, "SPI write failure\n");
- return ret;
- }
-
- reg_cache[i] = ret;
- }
-
- return 0;
-}
-
-static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *reg_cache = codec->reg_cache;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- return reg_cache[reg];
-}
-
-static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 *cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- /* only write to the hardware if value has changed */
- if (cache[reg] != value) {
- u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
-
- if (spi_write(spi, tmp, sizeof(tmp))) {
- dev_err(&spi->dev, "SPI write failed\n");
- return -EIO;
- }
-
- cache[reg] = value;
- }
-
- return 0;
-}
-
static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
struct snd_soc_codec *codec = codec_dai->codec;
int val = 0;
-
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- if (val < 0)
- return val;
-
- val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1);
+ int ret;
/* set DAI format */
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -135,7 +75,13 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
return -EINVAL;
- return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
+ val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int ak4104_hw_params(struct snd_pcm_substream *substream,
@@ -148,7 +94,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
/* set the IEC958 bits: consumer mode, no copyright bit */
val |= IEC958_AES0_CON_NOT_COPYRIGHT;
- ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val);
+ snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
val = 0;
@@ -167,7 +113,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
+ return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
}
static const struct snd_soc_dai_ops ak4101_dai_ops = {
@@ -192,67 +138,57 @@ static struct snd_soc_dai_driver ak4104_dai = {
static int ak4104_probe(struct snd_soc_codec *codec)
{
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
- int ret, val;
-
- codec->control_data = ak4104->control_data;
+ int ret;
- /* read all regs and fill the cache */
- ret = ak4104_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
+ codec->control_data = ak4104->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret != 0)
return ret;
- }
-
- /* read the 'reserved' register - according to the datasheet, it
- * 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)
- 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);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
if (ret < 0)
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);
+ ret = snd_soc_update_bits(codec, AK4104_REG_TX,
+ AK4104_TX_TXE, AK4104_TX_TXE);
if (ret < 0)
return ret;
- dev_info(codec->dev, "SPI device initialized\n");
return 0;
}
static int ak4104_remove(struct snd_soc_codec *codec)
{
- int val, ret;
-
- 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(codec, AK4104_REG_CONTROL1, val);
+ snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
- return ret;
+ return 0;
}
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(u8),
+};
+
+static const struct regmap_config ak4104_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4104_NUM_REGS - 1,
+ .read_flag_mask = AK4104_READ,
+ .write_flag_mask = AK4104_WRITE,
+
+ .cache_type = REGCACHE_RBTREE,
};
static int ak4104_spi_probe(struct spi_device *spi)
{
struct ak4104_private *ak4104;
+ unsigned int val;
int ret;
spi->bits_per_word = 8;
@@ -266,17 +202,41 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ak4104 == NULL)
return -ENOMEM;
- ak4104->control_data = spi;
- ak4104->control_type = SND_SOC_SPI;
+ ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+ if (IS_ERR(ak4104->regmap)) {
+ ret = PTR_ERR(ak4104->regmap);
+ return ret;
+ }
+
+ /* read the 'reserved' register - according to the datasheet, it
+ * should contain 0x5b. Not a good way to verify the presence of
+ * the device, but there is no hardware ID register. */
+ ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
+ if (ret != 0)
+ goto err;
+ if (val != AK4104_RESERVED_VAL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
spi_set_drvdata(spi, ak4104);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_device_ak4104, &ak4104_dai, 1);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(ak4104->regmap);
return ret;
}
static int __devexit ak4104_spi_remove(struct spi_device *spi)
{
+ struct ak4104_private *ak4101 = spi_get_drvdata(spi);
+ regmap_exit(ak4101->regmap);
snd_soc_unregister_codec(&spi->dev);
return 0;
}
@@ -290,17 +250,7 @@ static struct spi_driver ak4104_spi_driver = {
.remove = __devexit_p(ak4104_spi_remove),
};
-static int __init ak4104_init(void)
-{
- return spi_register_driver(&ak4104_spi_driver);
-}
-module_init(ak4104_init);
-
-static void __exit ak4104_exit(void)
-{
- spi_unregister_driver(&ak4104_spi_driver);
-}
-module_exit(ak4104_exit);
+module_spi_driver(ak4104_spi_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 9e809e05d066..838ae8b22b50 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -27,24 +28,43 @@
#include "ak4535.h"
-#define AK4535_VERSION "0.3"
-
/* codec private data */
struct ak4535_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
};
/*
* ak4535 register cache
*/
-static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
- 0x00, 0x80, 0x00, 0x03,
- 0x02, 0x00, 0x11, 0x01,
- 0x00, 0x40, 0x36, 0x10,
- 0x00, 0x00, 0x57, 0x00,
+static const struct reg_default ak4535_reg_defaults[] = {
+ { 0, 0x00 },
+ { 1, 0x80 },
+ { 2, 0x00 },
+ { 3, 0x03 },
+ { 4, 0x02 },
+ { 5, 0x00 },
+ { 6, 0x11 },
+ { 7, 0x01 },
+ { 8, 0x00 },
+ { 9, 0x40 },
+ { 10, 0x36 },
+ { 11, 0x10 },
+ { 12, 0x00 },
+ { 13, 0x00 },
+ { 14, 0x57 },
};
+static bool ak4535_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AK4535_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
@@ -372,9 +392,8 @@ static int ak4535_probe(struct snd_soc_codec *codec)
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
int ret;
- printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+ codec->control_data = ak4535->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -382,7 +401,7 @@ static int ak4535_probe(struct snd_soc_codec *codec)
/* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, ak4535_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4535_snd_controls,
ARRAY_SIZE(ak4535_snd_controls));
return 0;
}
@@ -394,22 +413,30 @@ static int ak4535_remove(struct snd_soc_codec *codec)
return 0;
}
+static const struct regmap_config ak4535_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4535_STATUS,
+ .volatile_reg = ak4535_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = ak4535_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
+};
+
static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.probe = ak4535_probe,
.remove = ak4535_remove,
.suspend = ak4535_suspend,
.resume = ak4535_resume,
.set_bias_level = ak4535_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(ak4535_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = ak4535_reg,
.dapm_widgets = ak4535_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets),
.dapm_routes = ak4535_audio_map,
.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -421,17 +448,29 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
if (ak4535 == NULL)
return -ENOMEM;
+ ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+ if (IS_ERR(ak4535->regmap)) {
+ ret = PTR_ERR(ak4535->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, ak4535);
- ak4535->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ak4535, &ak4535_dai, 1);
+ if (ret != 0)
+ regmap_exit(ak4535->regmap);
+
return ret;
}
static __devexit int ak4535_i2c_remove(struct i2c_client *client)
{
+ struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
+ regmap_exit(ak4535->regmap);
return 0;
}
@@ -443,36 +482,15 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = {
.driver = {
- .name = "ak4535-codec",
+ .name = "ak4535",
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
.remove = __devexit_p(ak4535_i2c_remove),
.id_table = ak4535_i2c_id,
};
-#endif
-static int __init ak4535_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&ak4535_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&ak4535_i2c_driver);
-#endif
-}
-module_exit(ak4535_exit);
+module_i2c_driver(ak4535_i2c_driver);
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index 0431e5f634a2..402de1d274bf 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -34,6 +34,4 @@
#define AK4535_VOL 0xe
#define AK4535_STATUS 0xf
-#define AK4535_CACHEREGNUM 0x10
-
#endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 5ef70b5d27e4..f8e10ced244a 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -146,13 +146,10 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
0, 0xFF, 1, out_tlv),
-
- SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0),
};
-static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = {
- SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0),
-};
+static const struct snd_kcontrol_new ak4642_headphone_control =
+ SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0);
static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
@@ -165,13 +162,12 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HPOUTR"),
SND_SOC_DAPM_OUTPUT("LINEOUT"),
- SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0,
- &ak4642_hpout_mixer_controls[0],
- ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+ SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0,
+ &ak4642_headphone_control),
- SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0,
- &ak4642_hpout_mixer_controls[0],
- ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+ SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
&ak4642_lout_mixer_controls[0],
@@ -184,12 +180,17 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
static const struct snd_soc_dapm_route ak4642_intercon[] = {
/* Outputs */
- {"HPOUTL", NULL, "HPOUTL Mixer"},
- {"HPOUTR", NULL, "HPOUTR Mixer"},
+ {"HPOUTL", NULL, "HPL Out"},
+ {"HPOUTR", NULL, "HPR Out"},
{"LINEOUT", NULL, "LINEOUT Mixer"},
- {"HPOUTL Mixer", "DACH", "DAC"},
- {"HPOUTR Mixer", "DACH", "DAC"},
+ {"HPL Out", NULL, "Headphone Enable"},
+ {"HPR Out", NULL, "Headphone Enable"},
+
+ {"Headphone Enable", "Switch", "DACH"},
+
+ {"DACH", NULL, "DAC"},
+
{"LINEOUT Mixer", "DACL", "DAC"},
};
@@ -476,7 +477,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
return ret;
}
- snd_soc_add_controls(codec, ak4642_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4642_snd_controls,
ARRAY_SIZE(ak4642_snd_controls));
ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index a53b152e6a07..5fb7c2a80e6d 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -628,7 +628,7 @@ static int ak4671_probe(struct snd_soc_codec *codec)
return ret;
}
- snd_soc_add_controls(codec, ak4671_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4671_snd_controls,
ARRAY_SIZE(ak4671_snd_controls));
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 3feee569ceea..d47b62ddb210 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -925,22 +925,22 @@ static int alc5623_probe(struct snd_soc_codec *codec)
switch (alc5623->id) {
case 0x21:
- snd_soc_add_controls(codec, alc5621_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
ARRAY_SIZE(alc5621_vol_snd_controls));
break;
case 0x22:
- snd_soc_add_controls(codec, alc5622_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
ARRAY_SIZE(alc5622_vol_snd_controls));
break;
case 0x23:
- snd_soc_add_controls(codec, alc5623_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
ARRAY_SIZE(alc5623_vol_snd_controls));
break;
default:
return -EINVAL;
}
- snd_soc_add_controls(codec, alc5623_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_snd_controls,
ARRAY_SIZE(alc5623_snd_controls));
snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
@@ -992,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
* low = 0x1a
* high = 0x1b
*/
-static int alc5623_i2c_probe(struct i2c_client *client,
+static __devinit int alc5623_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct alc5623_platform_data *pdata;
@@ -1059,7 +1059,7 @@ static int alc5623_i2c_probe(struct i2c_client *client,
return ret;
}
-static int alc5623_i2c_remove(struct i2c_client *client)
+static __devexit int alc5623_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 390e437d7c5e..e2111e0ccad7 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -145,15 +145,14 @@ static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
/* -16.5db min scale, 1.5db steps, no mute */
static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
static const unsigned int boost_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
- 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
- 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+ 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
};
/* 0db min scale, 6 db steps, no mute */
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
/* 0db min scalem 0.75db steps, no mute */
-static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 075, 0);
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0);
static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
/* left starts at bit 8, right at bit 0 */
@@ -176,26 +175,32 @@ static const struct snd_kcontrol_new alc5632_snd_controls[] = {
ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
SOC_SINGLE_TLV("Voice DAC Playback Volume",
ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
- SOC_SINGLE_TLV("Phone Capture Volume",
+ SOC_SINGLE("Voice DAC Playback Switch",
+ ALC5632_VOICE_DAC_VOL, 12, 1, 1),
+ SOC_SINGLE_TLV("Phone Playback Volume",
ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
- SOC_DOUBLE_TLV("LineIn Capture Volume",
+ SOC_DOUBLE_TLV("LineIn Playback Volume",
ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
SOC_DOUBLE_TLV("Master Playback Volume",
ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
SOC_DOUBLE("Master Playback Switch",
ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
- SOC_SINGLE_TLV("Mic1 Capture Volume",
+ SOC_SINGLE_TLV("Mic1 Playback Volume",
ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
- SOC_SINGLE_TLV("Mic2 Capture Volume",
+ SOC_SINGLE_TLV("Mic2 Playback Volume",
ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
SOC_DOUBLE_TLV("Rec Capture Volume",
ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
SOC_SINGLE_TLV("Mic 1 Boost Volume",
- ALC5632_MIC_CTRL, 10, 2, 0, boost_tlv),
+ ALC5632_MIC_CTRL, 10, 3, 0, boost_tlv),
SOC_SINGLE_TLV("Mic 2 Boost Volume",
- ALC5632_MIC_CTRL, 8, 2, 0, boost_tlv),
- SOC_SINGLE_TLV("Digital Boost Volume",
+ ALC5632_MIC_CTRL, 8, 3, 0, boost_tlv),
+ SOC_SINGLE_TLV("DMIC Boost Capture Volume",
ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+ SOC_SINGLE("DMIC En Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 15, 1, 0),
+ SOC_SINGLE("DMIC PreFilter Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 12, 1, 0),
};
/*
@@ -244,36 +249,48 @@ SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
/* Left Record Mixer */
static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
-SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
-SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
-SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
};
/* Right Record Mixer */
static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
-SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
-SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
-SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
};
-static const char *alc5632_spk_n_sour_sel[] = {
+/* Dmic Mixer */
+static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1),
+};
+static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1),
+};
+
+static const char * const alc5632_spk_n_sour_sel[] = {
"RN/-R", "RP/+R", "LN/-R", "Mute"};
-static const char *alc5632_hpl_out_input_sel[] = {
+static const char * const alc5632_hpl_out_input_sel[] = {
"Vmid", "HP Left Mix"};
-static const char *alc5632_hpr_out_input_sel[] = {
+static const char * const alc5632_hpr_out_input_sel[] = {
"Vmid", "HP Right Mix"};
-static const char *alc5632_spkout_input_sel[] = {
+static const char * const alc5632_spkout_input_sel[] = {
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
-static const char *alc5632_aux_out_input_sel[] = {
+static const char * const alc5632_aux_out_input_sel[] = {
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_adcr_func_sel[] = {
+ "Stereo ADC", "Voice ADC"};
+static const char * const alc5632_i2s_out_sel[] = {
+ "ADC LR", "Voice Stereo Digital"};
/* auxout output mux */
static const struct soc_enum alc5632_aux_out_input_enum =
@@ -312,6 +329,17 @@ static const struct soc_enum alc5632_amp_enum =
static const struct snd_kcontrol_new alc5632_amp_mux_controls =
SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
+/* ADC output select */
+static const struct soc_enum alc5632_adcr_func_enum =
+ SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static const struct snd_kcontrol_new alc5632_adcr_func_controls =
+ SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
+
+/* I2S out select */
+static const struct soc_enum alc5632_i2s_out_enum =
+ SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static const struct snd_kcontrol_new alc5632_i2s_out_controls =
+ SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
/* Muxes */
@@ -325,6 +353,10 @@ SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
&alc5632_hpr_out_mux_controls),
SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
&alc5632_spkoutn_mux_controls),
+SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_adcr_func_controls),
+SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0,
+ &alc5632_i2s_out_controls),
/* output mixers */
SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
@@ -343,6 +375,12 @@ SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
&alc5632_speaker_mixer_controls[0],
ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicl_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicl_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicr_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicr_mixer_controls)),
/* input mixers */
SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
@@ -352,20 +390,28 @@ SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
&alc5632_captureR_mixer_controls[0],
ARRAY_SIZE(alc5632_captureR_mixer_controls)),
-SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
- ALC5632_PWR_MANAG_ADD2, 9, 0),
-SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
- ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0),
+SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 0),
+
SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
SND_SOC_DAPM_MIXER("DAC Right Channel",
ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
- ALC5632_PWR_MANAG_ADD2, 7, 0),
-SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
- ALC5632_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
@@ -393,10 +439,12 @@ SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
SND_SOC_DAPM_OUTPUT("SPKOUT"),
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+
SND_SOC_DAPM_INPUT("LINEINL"),
SND_SOC_DAPM_INPUT("LINEINR"),
SND_SOC_DAPM_INPUT("PHONEP"),
SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("DMICDAT"),
SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"),
SND_SOC_DAPM_VMID("Vmid"),
@@ -404,6 +452,10 @@ SND_SOC_DAPM_VMID("Vmid"),
static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+ /* Playback streams */
+ {"Left DAC", NULL, "AIFRXL"},
+ {"Right DAC", NULL, "AIFRXR"},
+
/* virtual mixer - mixes left & right channels */
{"I2S Mix", NULL, "Left DAC"},
{"I2S Mix", NULL, "Right DAC"},
@@ -426,9 +478,12 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
{"HP Mix", "PHONE2HP Playback Switch", "Phone Mix"},
{"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
{"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
-
+ {"HP Mix", "VOICE2HP Playback Switch", "Voice Mix"},
{"HPR Mix", "DACR2HP Playback Switch", "DAC Right Channel"},
{"HPL Mix", "DACL2HP Playback Switch", "DAC Left Channel"},
+ {"HPOut Mix", NULL, "HP Mix"},
+ {"HPOut Mix", NULL, "HPR Mix"},
+ {"HPOut Mix", NULL, "HPL Mix"},
/* speaker mixer */
{"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
@@ -436,35 +491,34 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
{"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
{"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
{"Speaker Mix", "DAC2SPK Playback Switch", "DAC Left Channel"},
-
-
+ {"Speaker Mix", "VOICE2SPK Playback Switch", "Voice Mix"},
/* mono mixer */
{"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
{"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
{"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
- {"Mono Mix", "VOICE2MONO Playback Switch", "Phone Mix"},
{"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
{"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
{"Mono Mix", "DAC2MONO Playback Switch", "DAC Left Channel"},
+ {"Mono Mix", "VOICE2MONO Playback Switch", "Voice Mix"},
/* Left record mixer */
- {"Left Capture Mix", "LineInL Capture Switch", "LINEINL"},
- {"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
- {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
- {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
- {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
- {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
- {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+ {"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"},
+ {"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"},
+ {"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"},
+ {"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"},
+ {"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"},
+ {"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"},
+ {"Left Capture Mix", "MONO2REC_L Capture Switch", "Mono Mix"},
/*Right record mixer */
- {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
- {"Right Capture Mix", "Right Phone Capture Switch", "PHONEP"},
- {"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
- {"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
- {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
- {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
- {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+ {"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"},
+ {"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"},
+ {"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"},
+ {"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"},
+ {"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"},
+ {"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"},
+ {"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"},
/* headphone left mux */
{"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
@@ -504,10 +558,30 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
/* left ADC */
{"Left ADC", NULL, "Left Capture Mix"},
+ {"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"},
+ {"Left ADC", NULL, "DMICL Mix"},
+ {"ADCLR", NULL, "Left ADC"},
/* right ADC */
- {"Right ADC", NULL, "Right Capture Mix"},
-
+ {"Right ADC", NULL, "Right Capture Mix"},
+ {"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"},
+ {"Right ADC", NULL, "DMICR Mix"},
+ {"ADCR Mux", "Stereo ADC", "Right ADC"},
+ {"ADCR Mux", "Voice ADC", "Right ADC"},
+ {"ADCLR", NULL, "ADCR Mux"},
+ {"VAIFTX", NULL, "ADCR Mux"},
+
+ /* Digital I2S out */
+ {"I2SOut Mux", "ADC LR", "ADCLR"},
+ {"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"},
+ {"AIFTXL", NULL, "I2SOut Mux"},
+ {"AIFTXR", NULL, "I2SOut Mux"},
+
+ /* Voice Mix */
+ {"Voice DAC", NULL, "VAIFRX"},
+ {"Voice Mix", NULL, "Voice DAC"},
+
+ /* Speaker Output */
{"SpeakerOut N Mux", "RN/-R", "Left Speaker"},
{"SpeakerOut N Mux", "RP/+R", "Left Speaker"},
{"SpeakerOut N Mux", "LN/-R", "Left Speaker"},
@@ -714,6 +788,7 @@ static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
switch (freq) {
+ case 4096000:
case 8192000:
case 11289600:
case 12288000:
@@ -994,7 +1069,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
switch (alc5632->id) {
case 0x5c:
- snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls,
ARRAY_SIZE(alc5632_vol_snd_controls));
break;
default:
@@ -1109,7 +1184,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
return ret;
}
-static int alc5632_i2c_remove(struct i2c_client *client)
+static __devexit int alc5632_i2c_remove(struct i2c_client *client)
{
struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
index 357651ec074e..1b5bda594ea3 100644
--- a/sound/soc/codecs/alc5632.h
+++ b/sound/soc/codecs/alc5632.h
@@ -51,6 +51,7 @@
#define ALC5632_ADC_REC_MONOMIX (1 << 0)
#define ALC5632_VOICE_DAC_VOL 0x18 /* voice dac vol */
+#define ALC5632_I2S_OUT_CTL 0x1A /* undocumented reg. found in path scheme */
/* ALC5632_OUTPUT_MIXER_CTRL : */
/* same remark as for reg 2 line vs speaker */
#define ALC5632_OUTPUT_MIXER_CTRL 0x1C /* out mix ctrl */
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 4854b472d5fd..064cd6a93516 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -38,8 +38,6 @@
#include <sound/soc.h>
#include <sound/initval.h>
-#include <mach/dm365.h>
-
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
unsigned int reg)
{
@@ -159,7 +157,7 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
codec->control_data = davinci_vc;
/* Set controls */
- snd_soc_add_controls(codec, cq93vc_snd_controls,
+ snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
ARRAY_SIZE(cq93vc_snd_controls));
/* Off, with power on */
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 055536645da9..1d672f528662 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -521,7 +521,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
}
/* Add the non-DAPM controls */
- ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
ARRAY_SIZE(cs4270_snd_controls));
if (ret < 0) {
dev_err(codec->dev, "failed to add controls\n");
@@ -715,7 +715,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
*/
static struct i2c_driver cs4270_i2c_driver = {
.driver = {
- .name = "cs4270-codec",
+ .name = "cs4270",
.owner = THIS_MODULE,
},
.id_table = cs4270_id,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index f6fe846b6a6c..bf7141280a74 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -513,7 +513,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
/* Power-up sequence requires 85 uS */
udelay(85);
- return snd_soc_add_controls(codec, cs4271_snd_controls,
+ return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 9d38db8f1919..78979b3e0e95 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
priv->config[id].mmcc &= 0xC0;
priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
priv->config[id].spc &= 0xFC;
- priv->config[id].spc &= MCK_SCLK_64FS;
+ priv->config[id].spc |= MCK_SCLK_MCLK;
} else {
/* CS42L73 Slave */
priv->config[id].spc &= 0xFC;
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index ab38e93c3543..7843711729bc 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/pcm.h>
@@ -626,41 +627,82 @@ static const struct snd_soc_dapm_route da7210_audio_map[] = {
/* Codec private data */
struct da7210_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
};
-/*
- * Register cache
- */
-static const u8 da7210_reg[] = {
- 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R0 - R7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, /* R8 - RF */
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54, /* R10 - R17 */
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R18 - R1F */
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, /* R20 - R27 */
- 0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00, /* R28 - R2F */
- 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, /* R30 - R37 */
- 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* R38 - R3F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R40 - R4F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R48 - R4F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R50 - R57 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R58 - R5F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R60 - R67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R68 - R6F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R70 - R77 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, /* R78 - R7F */
- 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, /* R80 - R87 */
- 0x00, /* R88 */
+static struct reg_default da7210_reg_defaults[] = {
+ { 0x01, 0x11 },
+ { 0x03, 0x00 },
+ { 0x04, 0x00 },
+ { 0x05, 0x00 },
+ { 0x06, 0x00 },
+ { 0x07, 0x00 },
+ { 0x08, 0x00 },
+ { 0x09, 0x00 },
+ { 0x0a, 0x00 },
+ { 0x0b, 0x00 },
+ { 0x0c, 0x00 },
+ { 0x0d, 0x00 },
+ { 0x0e, 0x00 },
+ { 0x0f, 0x08 },
+ { 0x10, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x13, 0x00 },
+ { 0x14, 0x08 },
+ { 0x15, 0x10 },
+ { 0x16, 0x10 },
+ { 0x17, 0x54 },
+ { 0x18, 0x40 },
+ { 0x19, 0x00 },
+ { 0x1a, 0x00 },
+ { 0x1b, 0x00 },
+ { 0x1c, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1e, 0x00 },
+ { 0x1f, 0x00 },
+ { 0x20, 0x00 },
+ { 0x21, 0x00 },
+ { 0x22, 0x00 },
+ { 0x23, 0x02 },
+ { 0x24, 0x00 },
+ { 0x25, 0x76 },
+ { 0x26, 0x00 },
+ { 0x27, 0x00 },
+ { 0x28, 0x04 },
+ { 0x29, 0x00 },
+ { 0x2a, 0x00 },
+ { 0x2b, 0x30 },
+ { 0x2c, 0x2A },
+ { 0x83, 0x00 },
+ { 0x84, 0x00 },
+ { 0x85, 0x00 },
+ { 0x86, 0x00 },
+ { 0x87, 0x00 },
+ { 0x88, 0x00 },
};
-static int da7210_volatile_register(struct snd_soc_codec *codec,
+static bool da7210_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DA7210_A_HID_UNLOCK:
+ case DA7210_A_TEST_UNLOCK:
+ case DA7210_A_PLL1:
+ case DA7210_A_CP_MODE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static bool da7210_volatile_register(struct device *dev,
unsigned int reg)
{
switch (reg) {
case DA7210_STATUS:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
@@ -866,7 +908,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
+ codec->control_data = da7210->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -983,12 +1026,14 @@ static int da7210_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
/* As suggested by Dialog */
- snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
- snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
- snd_soc_write(codec, DA7210_A_PLL1, 0x01);
- snd_soc_write(codec, DA7210_A_CP_MODE, 0x7C);
- snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
- snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
+ /* unlock */
+ regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B);
+ regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4);
+ regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01);
+ regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C);
+ /* re-lock */
+ regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00);
+ regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00);
/* Activate all enabled subsystem */
snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
@@ -1000,10 +1045,6 @@ static int da7210_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.probe = da7210_probe,
- .reg_cache_size = ARRAY_SIZE(da7210_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = da7210_reg,
- .volatile_register = da7210_volatile_register,
.controls = da7210_snd_controls,
.num_controls = ARRAY_SIZE(da7210_snd_controls),
@@ -1014,6 +1055,17 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
};
+static struct regmap_config da7210_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .reg_defaults = da7210_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
+ .volatile_reg = da7210_volatile_register,
+ .readable_reg = da7210_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
@@ -1027,16 +1079,34 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, da7210);
- da7210->control_type = SND_SOC_I2C;
+
+ da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
+ if (IS_ERR(da7210->regmap)) {
+ ret = PTR_ERR(da7210->regmap);
+ dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+ goto err_regmap;
+ }
+ return ret;
+
+err_regmap:
+ regmap_exit(da7210->regmap);
+
return ret;
}
static int __devexit da7210_i2c_remove(struct i2c_client *client)
{
+ struct da7210_priv *da7210 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
+ regmap_exit(da7210->regmap);
return 0;
}
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 319039240e0f..ba4fafb93e56 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -179,7 +179,7 @@ static int lm4857_probe(struct snd_soc_codec *codec)
codec->control_data = lm4857->i2c;
- ret = snd_soc_add_controls(codec, lm4857_controls,
+ ret = snd_soc_add_codec_controls(codec, lm4857_controls,
ARRAY_SIZE(lm4857_controls));
if (ret)
return ret;
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
new file mode 100644
index 000000000000..17b3ec2d05cb
--- /dev/null
+++ b/sound/soc/codecs/max9768.c
@@ -0,0 +1,247 @@
+/*
+ * MAX9768 AMP driver
+ *
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/max9768.h>
+
+/* "Registers" */
+#define MAX9768_VOL 0
+#define MAX9768_CTRL 3
+
+/* Commands */
+#define MAX9768_CTRL_PWM 0x15
+#define MAX9768_CTRL_FILTERLESS 0x16
+
+struct max9768 {
+ struct regmap *regmap;
+ int mute_gpio;
+ int shdn_gpio;
+ u32 flags;
+};
+
+static struct reg_default max9768_default_regs[] = {
+ { 0, 0 },
+ { 3, MAX9768_CTRL_FILTERLESS},
+};
+
+static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int val = gpio_get_value_cansleep(max9768->mute_gpio);
+
+ ucontrol->value.integer.value[0] = !val;
+
+ return 0;
+}
+
+static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+
+ gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static const unsigned int volume_tlv[] = {
+ TLV_DB_RANGE_HEAD(43),
+ 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0),
+ 9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0),
+ 10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0),
+ 11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0),
+ 12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0),
+ 13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0),
+ 14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0),
+ 15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0),
+ 18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0),
+ 19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0),
+ 20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0),
+ 21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0),
+ 22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0),
+ 23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0),
+ 24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0),
+ 25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0),
+ 26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0),
+ 27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0),
+ 28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0),
+ 31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0),
+ 32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0),
+ 35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0),
+ 38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0),
+ 40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0),
+ 41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0),
+ 42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0),
+ 43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0),
+ 44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0),
+ 45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0),
+ 46, 46, TLV_DB_SCALE_ITEM(50, 0, 0),
+ 47, 50, TLV_DB_SCALE_ITEM(120, 40, 0),
+ 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
+ 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
+ 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
+ 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9768_volume[] = {
+ SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
+};
+
+static const struct snd_kcontrol_new max9768_mute[] = {
+ SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
+};
+
+static int max9768_probe(struct snd_soc_codec *codec)
+{
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = max9768->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
+ if (ret)
+ return ret;
+
+ if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
+ ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+ if (ret)
+ return ret;
+ }
+
+ if (gpio_is_valid(max9768->mute_gpio)) {
+ ret = snd_soc_add_codec_controls(codec, max9768_mute,
+ ARRAY_SIZE(max9768_mute));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver max9768_codec_driver = {
+ .probe = max9768_probe,
+ .controls = max9768_volume,
+ .num_controls = ARRAY_SIZE(max9768_volume),
+};
+
+static const struct regmap_config max9768_i2c_regmap_config = {
+ .reg_bits = 2,
+ .val_bits = 6,
+ .max_register = 3,
+ .reg_defaults = max9768_default_regs,
+ .num_reg_defaults = ARRAY_SIZE(max9768_default_regs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max9768_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max9768 *max9768;
+ struct max9768_pdata *pdata = client->dev.platform_data;
+ int err;
+
+ max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL);
+ if (!max9768)
+ return -ENOMEM;
+
+ if (pdata) {
+ /* Mute on powerup to avoid clicks */
+ err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+ max9768->mute_gpio = err ?: pdata->mute_gpio;
+
+ /* Activate chip by releasing shutdown, enables I2C */
+ err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+ max9768->shdn_gpio = err ?: pdata->shdn_gpio;
+
+ max9768->flags = pdata->flags;
+ } else {
+ max9768->shdn_gpio = -EINVAL;
+ max9768->mute_gpio = -EINVAL;
+ }
+
+ i2c_set_clientdata(client, max9768);
+
+ max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+ if (IS_ERR(max9768->regmap)) {
+ err = PTR_ERR(max9768->regmap);
+ goto err_gpio_free;
+ }
+
+ err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
+ if (err)
+ goto err_regmap_free;
+
+ return 0;
+
+ err_regmap_free:
+ regmap_exit(max9768->regmap);
+ err_gpio_free:
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return err;
+}
+
+static int __devexit max9768_i2c_remove(struct i2c_client *client)
+{
+ struct max9768 *max9768 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(max9768->regmap);
+
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return 0;
+}
+
+static const struct i2c_device_id max9768_i2c_id[] = {
+ { "max9768", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
+
+static struct i2c_driver max9768_i2c_driver = {
+ .driver = {
+ .name = "max9768",
+ .owner = THIS_MODULE,
+ },
+ .probe = max9768_i2c_probe,
+ .remove = __devexit_p(max9768_i2c_remove),
+ .id_table = max9768_i2c_id,
+};
+module_i2c_driver(max9768_i2c_driver);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 006efcfe6dda..af7324b79dd0 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1908,7 +1908,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
max98088->eq_enum.texts = max98088->eq_texts;
max98088->eq_enum.max = max98088->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
@@ -2030,7 +2030,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
max98088_handle_pdata(codec);
- snd_soc_add_controls(codec, max98088_snd_controls,
+ snd_soc_add_codec_controls(codec, max98088_snd_controls,
ARRAY_SIZE(max98088_snd_controls));
err_access:
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index fcfa7497d7b7..0bb511a0388d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1284,7 +1284,7 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
static int max98095_add_widgets(struct snd_soc_codec *codec)
{
- snd_soc_add_controls(codec, max98095_snd_controls,
+ snd_soc_add_codec_controls(codec, max98095_snd_controls,
ARRAY_SIZE(max98095_snd_controls));
return 0;
@@ -1984,7 +1984,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
max98095->eq_enum.texts = max98095->eq_texts;
max98095->eq_enum.max = max98095->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
@@ -2139,7 +2139,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
max98095->bq_enum.texts = max98095->bq_texts;
max98095->bq_enum.max = max98095->bq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret);
}
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index dcf6f2a1600a..3a2ba3d8fd6d 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -253,7 +253,7 @@ static const struct snd_kcontrol_new max9877_controls[] = {
/* This function is called from ASoC machine driver */
int max9877_add_controls(struct snd_soc_codec *codec)
{
- return snd_soc_add_controls(codec, max9877_controls,
+ return snd_soc_add_codec_controls(codec, max9877_controls,
ARRAY_SIZE(max9877_controls));
}
EXPORT_SYMBOL_GPL(max9877_add_controls);
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 7f4ba819a9f6..d1926266fe00 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -227,7 +227,7 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
};
/* routes for sgtl5000 */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
{"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */
{"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */
@@ -1248,7 +1248,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
}
rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
- dev_info(codec->dev, "sgtl5000 revision %d\n", rev);
+ dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev);
/*
* workaround for revision 0x11 and later,
@@ -1353,15 +1353,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
if (ret)
goto err;
- snd_soc_add_controls(codec, sgtl5000_snd_controls,
- ARRAY_SIZE(sgtl5000_snd_controls));
-
- snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets,
- ARRAY_SIZE(sgtl5000_dapm_widgets));
-
- snd_soc_dapm_add_routes(&codec->dapm, audio_map,
- ARRAY_SIZE(audio_map));
-
snd_soc_dapm_new_widgets(&codec->dapm);
return 0;
@@ -1402,6 +1393,12 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
.reg_cache_step = 2,
.reg_cache_default = sgtl5000_regs,
.volatile_register = sgtl5000_volatile_register,
+ .controls = sgtl5000_snd_controls,
+ .num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
+ .dapm_widgets = sgtl5000_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets),
+ .dapm_routes = sgtl5000_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
};
static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index f99baa0b8c39..50dbdb9357ea 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -827,8 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
{
pr_debug("codec_probe called\n");
- codec->dapm.idle_bias_off = 1;
-
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
@@ -871,7 +869,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, SN95031_SSR2, 0x10);
snd_soc_write(codec, SN95031_SSR3, 0x40);
- snd_soc_add_controls(codec, sn95031_snd_controls,
+ snd_soc_add_codec_controls(codec, sn95031_snd_controls,
ARRAY_SIZE(sn95031_snd_controls));
return 0;
@@ -891,6 +889,7 @@ struct snd_soc_codec_driver sn95031_codec = {
.read = sn95031_read,
.write = sn95031_write,
.set_bias_level = sn95031_set_vaud_bias,
+ .idle_bias_off = true,
.dapm_widgets = sn95031_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets),
.dapm_routes = sn95031_audio_map,
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 333dd98af39c..de2b20544ceb 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -548,7 +548,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, SSM2602_ROUT1V,
ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
- ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
ARRAY_SIZE(ssm2602_snd_controls));
if (ret)
return ret;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index cc0566c22ec1..982e437799a8 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -355,7 +355,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
ARRAY_SIZE(stac9766_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index dfa41a96599b..16d55f91a653 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -593,7 +593,7 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
- snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+ snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
ARRAY_SIZE(tlv320aic23_snd_controls));
return 0;
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index a038daec682b..802064b5030d 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -389,7 +389,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
/* register controls */
dev_dbg(codec->dev, "Registering controls\n");
- err = snd_soc_add_controls(codec, aic26_snd_controls,
+ err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
ARRAY_SIZE(aic26_snd_controls));
WARN_ON(err < 0);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 372b0b83bd9f..b0a73d37ed52 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -671,7 +671,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
}
aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, aic32x4_snd_controls,
+ snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
ARRAY_SIZE(aic32x4_snd_controls));
aic32x4_add_widgets(codec);
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 492f22f8a4d7..8d20f6ec20f3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -121,30 +121,6 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
0x00, 0x00, 0x02, /* 100 */
};
-/*
- * 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 int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
- u8 *value)
-{
- u8 *cache = codec->reg_cache;
-
- if (codec->cache_only)
- return -EINVAL;
- if (reg >= AIC3X_CACHEREGNUM)
- return -1;
-
- codec->cache_bypass = 1;
- *value = snd_soc_read(codec, reg);
- codec->cache_bypass = 0;
-
- cache[reg] = *value;
-
- return 0;
-}
-
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
@@ -1185,25 +1161,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-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 = snd_soc_read(codec, reg) & ~(1 << bit);
- snd_soc_write(codec, reg, val | (!!state << bit));
-}
-EXPORT_SYMBOL_GPL(aic3x_set_gpio);
-
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
-{
- u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 val = 0, bit = gpio ? 2 : 1;
-
- aic3x_read(codec, reg, &val);
- return (val >> bit) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-
void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
int headset_debounce, int button_debounce)
{
@@ -1221,23 +1178,6 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
}
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
-int aic3x_headset_detected(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 4) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
@@ -1377,7 +1317,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD(&aic3x->list);
aic3x->codec = codec;
- codec->dapm.idle_bias_off = 1;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
if (ret != 0) {
@@ -1426,10 +1365,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(aic3x->setup->gpio_func[1] & 0xf) << 4);
}
- snd_soc_add_controls(codec, aic3x_snd_controls,
+ snd_soc_add_codec_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);
+ snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
aic3x_add_widgets(codec);
list_add(&aic3x->list, &reset_list);
@@ -1471,6 +1410,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(aic3x_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = aic3x_reg,
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 06a19784b162..6f097fb60683 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -212,9 +212,6 @@
/* Default input volume */
#define DEFAULT_GAIN 0x20
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
/* headset detection / button API */
/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
@@ -252,10 +249,4 @@ enum {
#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
#define AIC3X_BUTTON_DEBOUNCE_MASK 3
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce);
-int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
-
#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index f0aad26cdb31..4587ddd0fbf8 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -806,8 +806,6 @@ static int dac33_startup(struct snd_pcm_substream *substream,
/* Stream started, save the substream pointer */
dac33->substream = substream;
- snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
-
return 0;
}
@@ -1397,7 +1395,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
codec->control_data = dac33->control_data;
codec->hw_write = (hw_write_t) i2c_master_send;
- codec->dapm.idle_bias_off = 1;
dac33->codec = codec;
/* Read the tlv320dac33 ID registers */
@@ -1440,7 +1437,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
/* Only add the FIFO controls, if we have valid IRQ number */
if (dac33->irq >= 0)
- snd_soc_add_controls(codec, dac33_mode_snd_controls,
+ snd_soc_add_codec_controls(codec, dac33_mode_snd_controls,
ARRAY_SIZE(dac33_mode_snd_controls));
err_power:
@@ -1478,6 +1475,7 @@ 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,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(dac33_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = dac33_reg,
@@ -1515,7 +1513,9 @@ static struct snd_soc_dai_driver dac33_dai = {
.channels_min = 2,
.channels_max = 2,
.rates = DAC33_RATES,
- .formats = DAC33_FORMATS,},
+ .formats = DAC33_FORMATS,
+ .sig_bits = 24,
+ },
.ops = &dac33_dai_ops,
};
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 363b99dad8e9..6fe4aa3ac544 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -351,10 +351,10 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
data = i2c_get_clientdata(tpa6130a2_client);
if (data->id == TPA6140A2)
- return snd_soc_add_controls(codec, tpa6140a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
ARRAY_SIZE(tpa6140a2_controls));
else
- return snd_soc_add_controls(codec, tpa6130a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
ARRAY_SIZE(tpa6130a2_controls));
}
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 18e71014cc2e..170cf9a8fc79 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1002,8 +1002,8 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
unsigned short mask, bitmask;
if (twl4030->configured) {
- printk(KERN_ERR "twl4030 operation mode cannot be "
- "changed on-the-fly\n");
+ dev_err(codec->dev,
+ "operation mode cannot be changed on-the-fly\n");
return -EBUSY;
}
@@ -1689,7 +1689,6 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
- snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
if (twl4030->master_substream) {
twl4030->slave_substream = substream;
/* The DAI has one configuration for playback and capture, so
@@ -1801,7 +1800,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_APLL_RATE_96000;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -1818,7 +1817,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
format |= TWL4030_DATA_WIDTH_32S_24W;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+ dev_err(codec->dev, "%s: unknown format %d\n", __func__,
params_format(params));
return -EINVAL;
}
@@ -1868,13 +1867,13 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
case 38400000:
break;
default:
- dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
+ dev_err(codec->dev, "Unsupported HFCLKIN: %u\n", freq);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -1984,9 +1983,9 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
* not available.
*/
if (twl4030->sysclk != 26000) {
- dev_err(codec->dev, "The board is configured for %u Hz, while"
- "the Voice interface needs 26MHz APLL mclk\n",
- twl4030->sysclk * 1000);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, twl4030->sysclk);
return -EINVAL;
}
@@ -1997,8 +1996,8 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
& TWL4030_OPT_MODE;
if (mode != TWL4030_OPTION_2) {
- printk(KERN_ERR "TWL4030 voice startup: "
- "the codec mode is not option2\n");
+ dev_err(codec->dev, "%s: the codec mode is not option2\n",
+ __func__);
return -EINVAL;
}
@@ -2039,7 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_SEL_16K;
break;
default:
- printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -2068,13 +2067,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (freq != 26000000) {
- dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
- "interface needs 26MHz APLL mclk\n", freq);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, freq / 1000);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -2175,13 +2175,15 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
.channels_min = 2,
.channels_max = 4,
.rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
- .formats = TWL4030_FORMATS,},
+ .formats = TWL4030_FORMATS,
+ .sig_bits = 24,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 4,
.rates = TWL4030_RATES,
- .formats = TWL4030_FORMATS,},
+ .formats = TWL4030_FORMATS,
+ .sig_bits = 24,},
.ops = &twl4030_dai_hifi_ops,
},
{
@@ -2220,13 +2222,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
if (twl4030 == NULL) {
- printk("Can not allocate memroy\n");
+ dev_err(codec->dev, "Can not allocate memory\n");
return -ENOMEM;
}
snd_soc_codec_set_drvdata(codec, twl4030);
/* Set the defaults, and power up the codec */
twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
- codec->dapm.idle_bias_off = 1;
twl4030_init_chip(codec);
@@ -2252,6 +2253,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.read = twl4030_read_reg_cache,
.write = twl4030_write,
.set_bias_level = twl4030_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = sizeof(twl4030_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl4030_reg,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 5b9c79b6f65e..2d8c6b825e57 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1052,6 +1052,19 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
}
EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec)
+{
+ struct twl6040 *twl6040 = codec->control_data;
+
+ if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2)
+ /* For ES under ES_1.3 HS step is 2 mV */
+ return 2;
+ else
+ /* For ES_1.3 HS step is 1 mV */
+ return 1;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
+
static const struct snd_kcontrol_new twl6040_snd_controls[] = {
/* Capture gains */
SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1125,14 +1138,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
TWL6040_REG_MICRCTL, 2, 0),
/* Microphone bias */
- SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
- TWL6040_REG_AMICBCTL, 0, 0),
- SND_SOC_DAPM_MICBIAS("Main Mic Bias",
- TWL6040_REG_AMICBCTL, 4, 0),
- SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
- TWL6040_REG_DMICBCTL, 0, 0),
- SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
- TWL6040_REG_DMICBCTL, 4, 0),
+ SND_SOC_DAPM_SUPPLY("Headset Mic Bias",
+ TWL6040_REG_AMICBCTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Main Mic Bias",
+ TWL6040_REG_AMICBCTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
+ TWL6040_REG_DMICBCTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
+ TWL6040_REG_DMICBCTL, 4, 0, NULL, 0),
/* DACs */
SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0),
@@ -1527,7 +1540,6 @@ static int twl6040_probe(struct snd_soc_codec *codec)
priv->codec = codec;
codec->control_data = dev_get_drvdata(codec->dev->parent);
- codec->ignore_pmdown_time = 1;
if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
priv->hs_left_step = pdata->hs_left_step;
@@ -1613,6 +1625,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.reg_cache_size = ARRAY_SIZE(twl6040_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl6040_reg,
+ .ignore_pmdown_time = true,
.controls = twl6040_snd_controls,
.num_controls = ARRAY_SIZE(twl6040_snd_controls),
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index ef273f1fac2f..0611406ca7c0 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -39,5 +39,6 @@ void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report);
int twl6040_get_clk_id(struct snd_soc_codec *codec);
int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec);
#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 8f4f469d6411..797b0dde2c68 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -531,15 +531,15 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
switch (pd->model) {
case UDA134X_UDA1340:
case UDA134X_UDA1344:
- ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
ARRAY_SIZE(uda1340_snd_controls));
break;
case UDA134X_UDA1341:
- ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
ARRAY_SIZE(uda1341_snd_controls));
break;
case UDA134X_UDA1345:
- ret = snd_soc_add_controls(codec, uda1345_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
ARRAY_SIZE(uda1345_snd_controls));
break;
default:
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 44aacf927ba9..3d868dc40092 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -464,7 +464,7 @@ static int wl1273_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_drvdata(codec, wl1273);
- r = snd_soc_add_controls(codec, wl1273_controls,
+ r = snd_soc_add_codec_controls(codec, wl1273_controls,
ARRAY_SIZE(wl1273_controls));
if (r)
kfree(wl1273);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
new file mode 100644
index 000000000000..acbdc5fde923
--- /dev/null
+++ b/sound/soc/codecs/wm2200.c
@@ -0,0 +1,2286 @@
+/*
+ * wm2200.c -- WM2200 ALSA SoC Audio driver
+ *
+ * Copyright 2012 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/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm2200.h>
+
+#include "wm2200.h"
+
+/* The code assumes DCVDD is generated internally */
+#define WM2200_NUM_CORE_SUPPLIES 2
+static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
+ "DBVDD",
+ "LDOVDD",
+};
+
+struct wm2200_fll {
+ int fref;
+ int fout;
+ int src;
+ struct completion lock;
+};
+
+/* codec private data */
+struct wm2200_priv {
+ struct regmap *regmap;
+ struct device *dev;
+ struct snd_soc_codec *codec;
+ struct wm2200_pdata pdata;
+ struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
+
+ struct completion fll_lock;
+ int fll_fout;
+ int fll_fref;
+ int fll_src;
+
+ int rev;
+ int sysclk;
+};
+
+static struct reg_default wm2200_reg_defaults[] = {
+ { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
+ { 0x0102, 0x0000 }, /* R258 - Clocking 3 */
+ { 0x0103, 0x0011 }, /* R259 - Clocking 4 */
+ { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */
+ { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */
+ { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */
+ { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */
+ { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */
+ { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */
+ { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */
+ { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */
+ { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */
+ { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */
+ { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */
+ { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */
+ { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */
+ { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */
+ { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */
+ { 0x0301, 0x0000 }, /* R769 - Input Enables */
+ { 0x0302, 0x2240 }, /* R770 - IN1L Control */
+ { 0x0303, 0x0040 }, /* R771 - IN1R Control */
+ { 0x0304, 0x2240 }, /* R772 - IN2L Control */
+ { 0x0305, 0x0040 }, /* R773 - IN2R Control */
+ { 0x0306, 0x2240 }, /* R774 - IN3L Control */
+ { 0x0307, 0x0040 }, /* R775 - IN3R Control */
+ { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */
+ { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */
+ { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */
+ { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */
+ { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */
+ { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */
+ { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */
+ { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */
+ { 0x0400, 0x0000 }, /* R1024 - Output Enables */
+ { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */
+ { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */
+ { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */
+ { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */
+ { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */
+ { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */
+ { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */
+ { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */
+ { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */
+ { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */
+ { 0x0417, 0x0069 }, /* R1047 - PDM 1 */
+ { 0x0418, 0x0000 }, /* R1048 - PDM 2 */
+ { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */
+ { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */
+ { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */
+ { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */
+ { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */
+ { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */
+ { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */
+ { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */
+ { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */
+ { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */
+ { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */
+ { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */
+ { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */
+ { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */
+ { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */
+ { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */
+ { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */
+ { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */
+ { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */
+ { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */
+ { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */
+ { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */
+ { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */
+ { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */
+ { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */
+ { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */
+ { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */
+ { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */
+ { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */
+ { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */
+ { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */
+ { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */
+ { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */
+ { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */
+ { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */
+ { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */
+ { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */
+ { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */
+ { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */
+ { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */
+ { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */
+ { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */
+ { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */
+ { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */
+ { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */
+ { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */
+ { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */
+ { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */
+ { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */
+ { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */
+ { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */
+ { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */
+ { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */
+ { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */
+ { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */
+ { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */
+ { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */
+ { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */
+ { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */
+ { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */
+ { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */
+ { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */
+ { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */
+ { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */
+ { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */
+ { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */
+ { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */
+ { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */
+ { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */
+ { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */
+ { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */
+ { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */
+ { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */
+ { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */
+ { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */
+ { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */
+ { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */
+ { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */
+ { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */
+ { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */
+ { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */
+ { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */
+ { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */
+ { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */
+ { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */
+ { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */
+ { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */
+ { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */
+ { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */
+ { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */
+ { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */
+ { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */
+ { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */
+ { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */
+ { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */
+ { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */
+ { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */
+ { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */
+ { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */
+ { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */
+ { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */
+ { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */
+ { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */
+ { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */
+ { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */
+ { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */
+ { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */
+ { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */
+ { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */
+ { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */
+ { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */
+ { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */
+ { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */
+ { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */
+ { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */
+ { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */
+ { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */
+ { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */
+ { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */
+ { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */
+ { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */
+ { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */
+ { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */
+ { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */
+ { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */
+ { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */
+ { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */
+ { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */
+ { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */
+ { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */
+ { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */
+ { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */
+ { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */
+ { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */
+ { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */
+ { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */
+ { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */
+ { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */
+ { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */
+ { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */
+ { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */
+ { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */
+ { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */
+ { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */
+ { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */
+ { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */
+ { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */
+ { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */
+ { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */
+ { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */
+ { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */
+ { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */
+ { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */
+ { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */
+ { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */
+ { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */
+ { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */
+ { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */
+ { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */
+ { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */
+ { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */
+ { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */
+ { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */
+ { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */
+ { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */
+ { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */
+ { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */
+ { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */
+ { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */
+ { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */
+ { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */
+ { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */
+ { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */
+ { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */
+ { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */
+ { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */
+ { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */
+ { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */
+ { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */
+ { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */
+ { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */
+ { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */
+ { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */
+ { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */
+ { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */
+ { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */
+ { 0x0900, 0x0000 }, /* R2304 - EQL_1 */
+ { 0x0901, 0x0000 }, /* R2305 - EQL_2 */
+ { 0x0902, 0x0000 }, /* R2306 - EQL_3 */
+ { 0x0903, 0x0000 }, /* R2307 - EQL_4 */
+ { 0x0904, 0x0000 }, /* R2308 - EQL_5 */
+ { 0x0905, 0x0000 }, /* R2309 - EQL_6 */
+ { 0x0906, 0x0000 }, /* R2310 - EQL_7 */
+ { 0x0907, 0x0000 }, /* R2311 - EQL_8 */
+ { 0x0908, 0x0000 }, /* R2312 - EQL_9 */
+ { 0x0909, 0x0000 }, /* R2313 - EQL_10 */
+ { 0x090A, 0x0000 }, /* R2314 - EQL_11 */
+ { 0x090B, 0x0000 }, /* R2315 - EQL_12 */
+ { 0x090C, 0x0000 }, /* R2316 - EQL_13 */
+ { 0x090D, 0x0000 }, /* R2317 - EQL_14 */
+ { 0x090E, 0x0000 }, /* R2318 - EQL_15 */
+ { 0x090F, 0x0000 }, /* R2319 - EQL_16 */
+ { 0x0910, 0x0000 }, /* R2320 - EQL_17 */
+ { 0x0911, 0x0000 }, /* R2321 - EQL_18 */
+ { 0x0912, 0x0000 }, /* R2322 - EQL_19 */
+ { 0x0913, 0x0000 }, /* R2323 - EQL_20 */
+ { 0x0916, 0x0000 }, /* R2326 - EQR_1 */
+ { 0x0917, 0x0000 }, /* R2327 - EQR_2 */
+ { 0x0918, 0x0000 }, /* R2328 - EQR_3 */
+ { 0x0919, 0x0000 }, /* R2329 - EQR_4 */
+ { 0x091A, 0x0000 }, /* R2330 - EQR_5 */
+ { 0x091B, 0x0000 }, /* R2331 - EQR_6 */
+ { 0x091C, 0x0000 }, /* R2332 - EQR_7 */
+ { 0x091D, 0x0000 }, /* R2333 - EQR_8 */
+ { 0x091E, 0x0000 }, /* R2334 - EQR_9 */
+ { 0x091F, 0x0000 }, /* R2335 - EQR_10 */
+ { 0x0920, 0x0000 }, /* R2336 - EQR_11 */
+ { 0x0921, 0x0000 }, /* R2337 - EQR_12 */
+ { 0x0922, 0x0000 }, /* R2338 - EQR_13 */
+ { 0x0923, 0x0000 }, /* R2339 - EQR_14 */
+ { 0x0924, 0x0000 }, /* R2340 - EQR_15 */
+ { 0x0925, 0x0000 }, /* R2341 - EQR_16 */
+ { 0x0926, 0x0000 }, /* R2342 - EQR_17 */
+ { 0x0927, 0x0000 }, /* R2343 - EQR_18 */
+ { 0x0928, 0x0000 }, /* R2344 - EQR_19 */
+ { 0x0929, 0x0000 }, /* R2345 - EQR_20 */
+ { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */
+ { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */
+ { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */
+ { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */
+ { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */
+ { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */
+ { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */
+ { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */
+ { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */
+ { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */
+ { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */
+ { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */
+ { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */
+ { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */
+ { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */
+ { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */
+ { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */
+ { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */
+ { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */
+ { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */
+ { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */
+ { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */
+ { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */
+ { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */
+ { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */
+ { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */
+ { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */
+ { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */
+ { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */
+ { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */
+ { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */
+ { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */
+ { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */
+ { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */
+ { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */
+ { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */
+ { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */
+ { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */
+ { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */
+ { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */
+ { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */
+ { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */
+ { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */
+ { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */
+ { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */
+ { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */
+ { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */
+ { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */
+ { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */
+ { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */
+ { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */
+ { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */
+ { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */
+ { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */
+ { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */
+ { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */
+ { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */
+ { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */
+ { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */
+ { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */
+ { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */
+ { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */
+ { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */
+ { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */
+ { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */
+ { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */
+};
+
+static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm2200_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_TONE_GENERATOR_1:
+ case WM2200_CLOCKING_3:
+ case WM2200_CLOCKING_4:
+ case WM2200_FLL_CONTROL_1:
+ case WM2200_FLL_CONTROL_2:
+ case WM2200_FLL_CONTROL_3:
+ case WM2200_FLL_CONTROL_4:
+ case WM2200_FLL_CONTROL_6:
+ case WM2200_FLL_CONTROL_7:
+ case WM2200_FLL_EFS_1:
+ case WM2200_FLL_EFS_2:
+ case WM2200_MIC_CHARGE_PUMP_1:
+ case WM2200_MIC_CHARGE_PUMP_2:
+ case WM2200_DM_CHARGE_PUMP_1:
+ case WM2200_MIC_BIAS_CTRL_1:
+ case WM2200_MIC_BIAS_CTRL_2:
+ case WM2200_EAR_PIECE_CTRL_1:
+ case WM2200_EAR_PIECE_CTRL_2:
+ case WM2200_INPUT_ENABLES:
+ case WM2200_IN1L_CONTROL:
+ case WM2200_IN1R_CONTROL:
+ case WM2200_IN2L_CONTROL:
+ case WM2200_IN2R_CONTROL:
+ case WM2200_IN3L_CONTROL:
+ case WM2200_IN3R_CONTROL:
+ case WM2200_RXANC_SRC:
+ case WM2200_INPUT_VOLUME_RAMP:
+ case WM2200_ADC_DIGITAL_VOLUME_1L:
+ case WM2200_ADC_DIGITAL_VOLUME_1R:
+ case WM2200_ADC_DIGITAL_VOLUME_2L:
+ case WM2200_ADC_DIGITAL_VOLUME_2R:
+ case WM2200_ADC_DIGITAL_VOLUME_3L:
+ case WM2200_ADC_DIGITAL_VOLUME_3R:
+ case WM2200_OUTPUT_ENABLES:
+ case WM2200_DAC_VOLUME_LIMIT_1L:
+ case WM2200_DAC_VOLUME_LIMIT_1R:
+ case WM2200_DAC_VOLUME_LIMIT_2L:
+ case WM2200_DAC_VOLUME_LIMIT_2R:
+ case WM2200_DAC_AEC_CONTROL_1:
+ case WM2200_OUTPUT_VOLUME_RAMP:
+ case WM2200_DAC_DIGITAL_VOLUME_1L:
+ case WM2200_DAC_DIGITAL_VOLUME_1R:
+ case WM2200_DAC_DIGITAL_VOLUME_2L:
+ case WM2200_DAC_DIGITAL_VOLUME_2R:
+ case WM2200_PDM_1:
+ case WM2200_PDM_2:
+ case WM2200_AUDIO_IF_1_1:
+ case WM2200_AUDIO_IF_1_2:
+ case WM2200_AUDIO_IF_1_3:
+ case WM2200_AUDIO_IF_1_4:
+ case WM2200_AUDIO_IF_1_5:
+ case WM2200_AUDIO_IF_1_6:
+ case WM2200_AUDIO_IF_1_7:
+ case WM2200_AUDIO_IF_1_8:
+ case WM2200_AUDIO_IF_1_9:
+ case WM2200_AUDIO_IF_1_10:
+ case WM2200_AUDIO_IF_1_11:
+ case WM2200_AUDIO_IF_1_12:
+ case WM2200_AUDIO_IF_1_13:
+ case WM2200_AUDIO_IF_1_14:
+ case WM2200_AUDIO_IF_1_15:
+ case WM2200_AUDIO_IF_1_16:
+ case WM2200_AUDIO_IF_1_17:
+ case WM2200_AUDIO_IF_1_18:
+ case WM2200_AUDIO_IF_1_19:
+ case WM2200_AUDIO_IF_1_20:
+ case WM2200_AUDIO_IF_1_21:
+ case WM2200_AUDIO_IF_1_22:
+ case WM2200_OUT1LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
+ case WM2200_EQLMIX_INPUT_1_SOURCE:
+ case WM2200_EQLMIX_INPUT_1_VOLUME:
+ case WM2200_EQLMIX_INPUT_2_SOURCE:
+ case WM2200_EQLMIX_INPUT_2_VOLUME:
+ case WM2200_EQLMIX_INPUT_3_SOURCE:
+ case WM2200_EQLMIX_INPUT_3_VOLUME:
+ case WM2200_EQLMIX_INPUT_4_SOURCE:
+ case WM2200_EQLMIX_INPUT_4_VOLUME:
+ case WM2200_EQRMIX_INPUT_1_SOURCE:
+ case WM2200_EQRMIX_INPUT_1_VOLUME:
+ case WM2200_EQRMIX_INPUT_2_SOURCE:
+ case WM2200_EQRMIX_INPUT_2_VOLUME:
+ case WM2200_EQRMIX_INPUT_3_SOURCE:
+ case WM2200_EQRMIX_INPUT_3_VOLUME:
+ case WM2200_EQRMIX_INPUT_4_SOURCE:
+ case WM2200_EQRMIX_INPUT_4_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_4_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_4_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_GPIO_CTRL_1:
+ case WM2200_GPIO_CTRL_2:
+ case WM2200_GPIO_CTRL_3:
+ case WM2200_GPIO_CTRL_4:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_MISC_PAD_CTRL_1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_1_MASK:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ case WM2200_INTERRUPT_STATUS_2_MASK:
+ case WM2200_INTERRUPT_CONTROL:
+ case WM2200_EQL_1:
+ case WM2200_EQL_2:
+ case WM2200_EQL_3:
+ case WM2200_EQL_4:
+ case WM2200_EQL_5:
+ case WM2200_EQL_6:
+ case WM2200_EQL_7:
+ case WM2200_EQL_8:
+ case WM2200_EQL_9:
+ case WM2200_EQL_10:
+ case WM2200_EQL_11:
+ case WM2200_EQL_12:
+ case WM2200_EQL_13:
+ case WM2200_EQL_14:
+ case WM2200_EQL_15:
+ case WM2200_EQL_16:
+ case WM2200_EQL_17:
+ case WM2200_EQL_18:
+ case WM2200_EQL_19:
+ case WM2200_EQL_20:
+ case WM2200_EQR_1:
+ case WM2200_EQR_2:
+ case WM2200_EQR_3:
+ case WM2200_EQR_4:
+ case WM2200_EQR_5:
+ case WM2200_EQR_6:
+ case WM2200_EQR_7:
+ case WM2200_EQR_8:
+ case WM2200_EQR_9:
+ case WM2200_EQR_10:
+ case WM2200_EQR_11:
+ case WM2200_EQR_12:
+ case WM2200_EQR_13:
+ case WM2200_EQR_14:
+ case WM2200_EQR_15:
+ case WM2200_EQR_16:
+ case WM2200_EQR_17:
+ case WM2200_EQR_18:
+ case WM2200_EQR_19:
+ case WM2200_EQR_20:
+ case WM2200_HPLPF1_1:
+ case WM2200_HPLPF1_2:
+ case WM2200_HPLPF2_1:
+ case WM2200_HPLPF2_2:
+ case WM2200_DSP1_CONTROL_1:
+ case WM2200_DSP1_CONTROL_2:
+ case WM2200_DSP1_CONTROL_3:
+ case WM2200_DSP1_CONTROL_4:
+ case WM2200_DSP1_CONTROL_5:
+ case WM2200_DSP1_CONTROL_6:
+ case WM2200_DSP1_CONTROL_7:
+ case WM2200_DSP1_CONTROL_8:
+ case WM2200_DSP1_CONTROL_9:
+ case WM2200_DSP1_CONTROL_10:
+ case WM2200_DSP1_CONTROL_11:
+ case WM2200_DSP1_CONTROL_12:
+ case WM2200_DSP1_CONTROL_13:
+ case WM2200_DSP1_CONTROL_14:
+ case WM2200_DSP1_CONTROL_15:
+ case WM2200_DSP1_CONTROL_16:
+ case WM2200_DSP1_CONTROL_17:
+ case WM2200_DSP1_CONTROL_18:
+ case WM2200_DSP1_CONTROL_19:
+ case WM2200_DSP1_CONTROL_20:
+ case WM2200_DSP1_CONTROL_21:
+ case WM2200_DSP1_CONTROL_22:
+ case WM2200_DSP1_CONTROL_23:
+ case WM2200_DSP1_CONTROL_24:
+ case WM2200_DSP1_CONTROL_25:
+ case WM2200_DSP1_CONTROL_26:
+ case WM2200_DSP1_CONTROL_27:
+ case WM2200_DSP1_CONTROL_28:
+ case WM2200_DSP1_CONTROL_29:
+ case WM2200_DSP1_CONTROL_30:
+ case WM2200_DSP1_CONTROL_31:
+ case WM2200_DSP2_CONTROL_1:
+ case WM2200_DSP2_CONTROL_2:
+ case WM2200_DSP2_CONTROL_3:
+ case WM2200_DSP2_CONTROL_4:
+ case WM2200_DSP2_CONTROL_5:
+ case WM2200_DSP2_CONTROL_6:
+ case WM2200_DSP2_CONTROL_7:
+ case WM2200_DSP2_CONTROL_8:
+ case WM2200_DSP2_CONTROL_9:
+ case WM2200_DSP2_CONTROL_10:
+ case WM2200_DSP2_CONTROL_11:
+ case WM2200_DSP2_CONTROL_12:
+ case WM2200_DSP2_CONTROL_13:
+ case WM2200_DSP2_CONTROL_14:
+ case WM2200_DSP2_CONTROL_15:
+ case WM2200_DSP2_CONTROL_16:
+ case WM2200_DSP2_CONTROL_17:
+ case WM2200_DSP2_CONTROL_18:
+ case WM2200_DSP2_CONTROL_19:
+ case WM2200_DSP2_CONTROL_20:
+ case WM2200_DSP2_CONTROL_21:
+ case WM2200_DSP2_CONTROL_22:
+ case WM2200_DSP2_CONTROL_23:
+ case WM2200_DSP2_CONTROL_24:
+ case WM2200_DSP2_CONTROL_25:
+ case WM2200_DSP2_CONTROL_26:
+ case WM2200_DSP2_CONTROL_27:
+ case WM2200_DSP2_CONTROL_28:
+ case WM2200_DSP2_CONTROL_29:
+ case WM2200_DSP2_CONTROL_30:
+ case WM2200_DSP2_CONTROL_31:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct reg_default wm2200_reva_patch[] = {
+ { 0x07, 0x0003 },
+ { 0x102, 0x0200 },
+ { 0x203, 0x0084 },
+ { 0x201, 0x83FF },
+ { 0x20C, 0x0062 },
+ { 0x20D, 0x0062 },
+ { 0x207, 0x2002 },
+ { 0x208, 0x20C0 },
+ { 0x21D, 0x01C0 },
+ { 0x50A, 0x0001 },
+ { 0x50B, 0x0002 },
+ { 0x50C, 0x0003 },
+ { 0x50D, 0x0004 },
+ { 0x50E, 0x0005 },
+ { 0x510, 0x0001 },
+ { 0x511, 0x0002 },
+ { 0x512, 0x0003 },
+ { 0x513, 0x0004 },
+ { 0x514, 0x0005 },
+ { 0x515, 0x0000 },
+ { 0x201, 0x8084 },
+ { 0x202, 0xBBDE },
+ { 0x203, 0x00EC },
+ { 0x500, 0x8000 },
+ { 0x507, 0x1820 },
+ { 0x508, 0x1820 },
+ { 0x505, 0x0300 },
+ { 0x506, 0x0300 },
+ { 0x302, 0x2280 },
+ { 0x303, 0x0080 },
+ { 0x304, 0x2280 },
+ { 0x305, 0x0080 },
+ { 0x306, 0x2280 },
+ { 0x307, 0x0080 },
+ { 0x401, 0x0080 },
+ { 0x402, 0x0080 },
+ { 0x417, 0x3069 },
+ { 0x900, 0x6318 },
+ { 0x901, 0x6300 },
+ { 0x902, 0x0FC8 },
+ { 0x903, 0x03FE },
+ { 0x904, 0x00E0 },
+ { 0x905, 0x1EC4 },
+ { 0x906, 0xF136 },
+ { 0x907, 0x0409 },
+ { 0x908, 0x04CC },
+ { 0x909, 0x1C9B },
+ { 0x90A, 0xF337 },
+ { 0x90B, 0x040B },
+ { 0x90C, 0x0CBB },
+ { 0x90D, 0x16F8 },
+ { 0x90E, 0xF7D9 },
+ { 0x90F, 0x040A },
+ { 0x910, 0x1F14 },
+ { 0x911, 0x058C },
+ { 0x912, 0x0563 },
+ { 0x913, 0x4000 },
+ { 0x916, 0x6318 },
+ { 0x917, 0x6300 },
+ { 0x918, 0x0FC8 },
+ { 0x919, 0x03FE },
+ { 0x91A, 0x00E0 },
+ { 0x91B, 0x1EC4 },
+ { 0x91C, 0xF136 },
+ { 0x91D, 0x0409 },
+ { 0x91E, 0x04CC },
+ { 0x91F, 0x1C9B },
+ { 0x920, 0xF337 },
+ { 0x921, 0x040B },
+ { 0x922, 0x0CBB },
+ { 0x923, 0x16F8 },
+ { 0x924, 0xF7D9 },
+ { 0x925, 0x040A },
+ { 0x926, 0x1F14 },
+ { 0x927, 0x058C },
+ { 0x928, 0x0563 },
+ { 0x929, 0x4000 },
+ { 0x709, 0x2000 },
+ { 0x207, 0x200E },
+ { 0x208, 0x20D4 },
+ { 0x20A, 0x0080 },
+ { 0x07, 0x0000 },
+};
+
+static int wm2200_reset(struct wm2200_priv *wm2200)
+{
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_set_value_cansleep(wm2200->pdata.reset, 1);
+
+ return 0;
+ } else {
+ return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
+ 0x2200);
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+
+static const char *wm2200_mixer_texts[] = {
+ "None",
+ "Tone Generator",
+ "AEC loopback",
+ "IN1L",
+ "IN1R",
+ "IN2L",
+ "IN2R",
+ "IN3L",
+ "IN3R",
+ "AIF1RX1",
+ "AIF1RX2",
+ "AIF1RX3",
+ "AIF1RX4",
+ "AIF1RX5",
+ "AIF1RX6",
+ "EQL",
+ "EQR",
+ "LHPF1",
+ "LHPF2",
+ "LHPF3",
+ "LHPF4",
+ "DSP1.1",
+ "DSP1.2",
+ "DSP1.3",
+ "DSP1.4",
+ "DSP1.5",
+ "DSP1.6",
+ "DSP2.1",
+ "DSP2.2",
+ "DSP2.3",
+ "DSP2.4",
+ "DSP2.5",
+ "DSP2.6",
+};
+
+static int wm2200_mixer_values[] = {
+ 0x00,
+ 0x04, /* Tone */
+ 0x08, /* AEC */
+ 0x10, /* Input */
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x20, /* AIF */
+ 0x21,
+ 0x22,
+ 0x23,
+ 0x24,
+ 0x25,
+ 0x50, /* EQ */
+ 0x51,
+ 0x52,
+ 0x60, /* LHPF1 */
+ 0x61, /* LHPF2 */
+ 0x68, /* DSP1 */
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x70, /* DSP2 */
+ 0x71,
+ 0x72,
+ 0x73,
+ 0x74,
+ 0x75,
+};
+
+#define WM2200_MIXER_CONTROLS(name, base) \
+ SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM2200_MUX_ENUM_DECL(name, reg) \
+ SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
+ wm2200_mixer_texts, wm2200_mixer_values)
+
+#define WM2200_MUX_CTL_DECL(name) \
+ const struct snd_kcontrol_new name##_mux = \
+ SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM2200_MIXER_ENUMS(name, base_reg) \
+ static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
+ static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
+ static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
+ static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
+ static WM2200_MUX_CTL_DECL(name##_in1); \
+ static WM2200_MUX_CTL_DECL(name##_in2); \
+ static WM2200_MUX_CTL_DECL(name##_in3); \
+ static WM2200_MUX_CTL_DECL(name##_in4)
+
+static const struct snd_kcontrol_new wm2200_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
+ WM2200_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
+ WM2200_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
+ WM2200_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
+ WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
+ WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
+ WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+
+SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_OUT2_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
+ WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
+ 0x46, 0, out_tlv),
+
+SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
+ WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+};
+
+WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
+
+#define WM2200_MUX(name, ctrl) \
+ SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM2200_MIXER_WIDGETS(name, name_str) \
+ WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
+ WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
+ WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
+ WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
+ SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM2200_MIXER_INPUT_ROUTES(name) \
+ { name, "Tone Generator", "Tone Generator" }, \
+ { name, "IN1L", "IN1L PGA" }, \
+ { name, "IN1R", "IN1R PGA" }, \
+ { name, "IN2L", "IN2L PGA" }, \
+ { name, "IN2R", "IN2R PGA" }, \
+ { name, "IN3L", "IN3L PGA" }, \
+ { name, "IN3R", "IN3R PGA" }, \
+ { name, "DSP1.1", "DSP1" }, \
+ { name, "DSP1.2", "DSP1" }, \
+ { name, "DSP1.3", "DSP1" }, \
+ { name, "DSP1.4", "DSP1" }, \
+ { name, "DSP1.5", "DSP1" }, \
+ { name, "DSP1.6", "DSP1" }, \
+ { name, "DSP2.1", "DSP2" }, \
+ { name, "DSP2.2", "DSP2" }, \
+ { name, "DSP2.3", "DSP2" }, \
+ { name, "DSP2.4", "DSP2" }, \
+ { name, "DSP2.5", "DSP2" }, \
+ { name, "DSP2.6", "DSP2" }, \
+ { name, "AIF1RX1", "AIF1RX1" }, \
+ { name, "AIF1RX2", "AIF1RX2" }, \
+ { name, "AIF1RX3", "AIF1RX3" }, \
+ { name, "AIF1RX4", "AIF1RX4" }, \
+ { name, "AIF1RX5", "AIF1RX5" }, \
+ { name, "AIF1RX6", "AIF1RX6" }, \
+ { name, "EQL", "EQL" }, \
+ { name, "EQR", "EQR" }, \
+ { name, "LHPF1", "LHPF1" }, \
+ { name, "LHPF2", "LHPF2" }
+
+#define WM2200_MIXER_ROUTES(widget, name) \
+ { widget, NULL, name " Mixer" }, \
+ { name " Mixer", NULL, name " Input 1" }, \
+ { name " Mixer", NULL, name " Input 2" }, \
+ { name " Mixer", NULL, name " Input 3" }, \
+ { name " Mixer", NULL, name " Input 4" }, \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
+
+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_SIGGEN("TONE"),
+SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
+ WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("EPOUTLN"),
+SND_SOC_DAPM_OUTPUT("EPOUTLP"),
+SND_SOC_DAPM_OUTPUT("EPOUTRN"),
+SND_SOC_DAPM_OUTPUT("EPOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPK"),
+
+WM2200_MIXER_WIDGETS(EQL, "EQL"),
+WM2200_MIXER_WIDGETS(EQR, "EQR"),
+
+WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
+
+WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
+WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
+WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
+WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+
+WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+
+WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
+WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
+WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
+WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
+};
+
+static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
+ /* Everything needs SYSCLK but only hook up things on the edge
+ * of the chip */
+ { "IN1L", NULL, "SYSCLK" },
+ { "IN1R", NULL, "SYSCLK" },
+ { "IN2L", NULL, "SYSCLK" },
+ { "IN2R", NULL, "SYSCLK" },
+ { "IN3L", NULL, "SYSCLK" },
+ { "IN3R", NULL, "SYSCLK" },
+ { "OUT1L", NULL, "SYSCLK" },
+ { "OUT1R", NULL, "SYSCLK" },
+ { "OUT2L", NULL, "SYSCLK" },
+ { "OUT2R", NULL, "SYSCLK" },
+ { "AIF1RX1", NULL, "SYSCLK" },
+ { "AIF1RX2", NULL, "SYSCLK" },
+ { "AIF1RX3", NULL, "SYSCLK" },
+ { "AIF1RX4", NULL, "SYSCLK" },
+ { "AIF1RX5", NULL, "SYSCLK" },
+ { "AIF1RX6", NULL, "SYSCLK" },
+ { "AIF1TX1", NULL, "SYSCLK" },
+ { "AIF1TX2", NULL, "SYSCLK" },
+ { "AIF1TX3", NULL, "SYSCLK" },
+ { "AIF1TX4", NULL, "SYSCLK" },
+ { "AIF1TX5", NULL, "SYSCLK" },
+ { "AIF1TX6", NULL, "SYSCLK" },
+
+ { "IN1L", NULL, "AVDD" },
+ { "IN1R", NULL, "AVDD" },
+ { "IN2L", NULL, "AVDD" },
+ { "IN2R", NULL, "AVDD" },
+ { "IN3L", NULL, "AVDD" },
+ { "IN3R", NULL, "AVDD" },
+ { "OUT1L", NULL, "AVDD" },
+ { "OUT1R", NULL, "AVDD" },
+
+ { "IN1L PGA", NULL, "IN1L" },
+ { "IN1R PGA", NULL, "IN1R" },
+ { "IN2L PGA", NULL, "IN2L" },
+ { "IN2R PGA", NULL, "IN2R" },
+ { "IN3L PGA", NULL, "IN3L" },
+ { "IN3R PGA", NULL, "IN3R" },
+
+ { "Tone Generator", NULL, "TONE" },
+
+ { "CP2", NULL, "CPVDD" },
+ { "MICBIAS1", NULL, "CP2" },
+ { "MICBIAS2", NULL, "CP2" },
+
+ { "CP1", NULL, "CPVDD" },
+ { "EPD_LN", NULL, "CP1" },
+ { "EPD_LP", NULL, "CP1" },
+ { "EPD_RN", NULL, "CP1" },
+ { "EPD_RP", NULL, "CP1" },
+
+ { "EPD_LP", NULL, "OUT1L" },
+ { "EPD_OUTP_LP", NULL, "EPD_LP" },
+ { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
+ { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
+
+ { "EPD_LN", NULL, "OUT1L" },
+ { "EPD_OUTP_LN", NULL, "EPD_LN" },
+ { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
+ { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
+
+ { "EPD_RP", NULL, "OUT1R" },
+ { "EPD_OUTP_RP", NULL, "EPD_RP" },
+ { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
+ { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
+
+ { "EPD_RN", NULL, "OUT1R" },
+ { "EPD_OUTP_RN", NULL, "EPD_RN" },
+ { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
+ { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
+
+ { "SPK", NULL, "OUT2L" },
+ { "SPK", NULL, "OUT2R" },
+
+ WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
+ WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+
+ WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
+ WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
+ WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
+ WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
+
+ WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+ WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+ WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+ WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+ WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+ WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+
+ WM2200_MIXER_ROUTES("EQL", "EQL"),
+ WM2200_MIXER_ROUTES("EQR", "EQR"),
+
+ WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
+ WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
+};
+
+static int wm2200_probe(struct snd_soc_codec *codec)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
+ int ret;
+
+ wm2200->codec = codec;
+ codec->control_data = wm2200->regmap;
+ codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int lrclk, bclk, fmt_val;
+
+ lrclk = 0;
+ bclk = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ fmt_val = 0;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ fmt_val = 1;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ fmt_val = 2;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ fmt_val = 3;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported master mode %d\n",
+ fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
+ WM2200_AIF1_BCLK_INV, bclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
+ WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+
+ return 0;
+}
+
+static int wm2200_sr_code[] = {
+ 0,
+ 12000,
+ 24000,
+ 48000,
+ 96000,
+ 192000,
+ 384000,
+ 768000,
+ 0,
+ 11025,
+ 22050,
+ 44100,
+ 88200,
+ 176400,
+ 352800,
+ 705600,
+ 4000,
+ 8000,
+ 16000,
+ 32000,
+ 64000,
+ 128000,
+ 256000,
+ 512000,
+};
+
+#define WM2200_NUM_BCLK_RATES 12
+
+static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
+ 6144000,
+ 3072000,
+ 2048000,
+ 1536000,
+ 768000,
+ 512000,
+ 384000,
+ 256000,
+ 192000,
+ 128000,
+ 96000,
+ 64000,
+};
+
+static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
+ 5644800,
+ 2882400,
+ 1881600,
+ 1411200,
+ 705600,
+ 470400,
+ 352800,
+ 176400,
+ 117600,
+ 88200,
+ 58800,
+};
+
+static int wm2200_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 wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int i, bclk, lrclk, wl, fl, sr_code;
+ int *bclk_rates;
+
+ /* Data sizes if not using TDM */
+ wl = snd_pcm_format_width(params_format(params));
+ if (wl < 0)
+ return wl;
+ fl = snd_soc_params_to_frame_size(params);
+ if (fl < 0)
+ return fl;
+
+ dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+ wl, fl);
+
+ /* Target BCLK rate */
+ bclk = snd_soc_params_to_bclk(params);
+ if (bclk < 0)
+ return bclk;
+
+ if (!wm2200->sysclk) {
+ dev_err(codec->dev, "SYSCLK has no rate set\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
+ if (wm2200_sr_code[i] == params_rate(params))
+ break;
+ if (i == ARRAY_SIZE(wm2200_sr_code)) {
+ dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+ sr_code = i;
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+
+ if (wm2200->sysclk % 4000)
+ bclk_rates = wm2200_bclk_rates_cd;
+ else
+ bclk_rates = wm2200_bclk_rates_dat;
+
+ for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
+ if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+ break;
+ if (i == WM2200_NUM_BCLK_RATES) {
+ dev_err(codec->dev,
+ "No valid BCLK for %dHz found from %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+ return -EINVAL;
+ }
+
+ bclk = i;
+ dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
+ WM2200_AIF1_BCLK_DIV_MASK, bclk);
+
+ lrclk = bclk_rates[bclk] / params_rate(params);
+ dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+ dai->symmetric_rates)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
+ WM2200_AIF1RX_BCPF_MASK, lrclk);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
+ WM2200_AIF1TX_BCPF_MASK, lrclk);
+
+ i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
+ WM2200_AIF1RX_WL_MASK |
+ WM2200_AIF1RX_SLOT_LEN_MASK, i);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
+ WM2200_AIF1TX_WL_MASK |
+ WM2200_AIF1TX_SLOT_LEN_MASK, i);
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_4,
+ WM2200_SAMPLE_RATE_1_MASK, sr_code);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops wm2200_dai_ops = {
+ .set_fmt = wm2200_set_fmt,
+ .hw_params = wm2200_hw_params,
+};
+
+static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int fval;
+
+ switch (clk_id) {
+ case WM2200_CLK_SYSCLK:
+ break;
+
+ default:
+ dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case WM2200_CLKSRC_MCLK1:
+ case WM2200_CLKSRC_MCLK2:
+ case WM2200_CLKSRC_FLL:
+ case WM2200_CLKSRC_BCLK1:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid source %d\n", source);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 22579200:
+ case 24576000:
+ fval = 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+ return -EINVAL;
+ }
+
+ /* TODO: Check if MCLKs are in use and enable/disable pulls to
+ * match.
+ */
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
+ WM2200_SYSCLK_SRC_MASK,
+ fval << WM2200_SYSCLK_FREQ_SHIFT | source);
+
+ wm2200->sysclk = freq;
+
+ return 0;
+}
+
+struct _fll_div {
+ u16 fll_fratio;
+ u16 fll_outdiv;
+ u16 fll_refclk_div;
+ u16 n;
+ u16 theta;
+ u16 lambda;
+};
+
+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 > 8) {
+ 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(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+ fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+ fll_div->fll_refclk_div);
+
+ return 0;
+}
+
+static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ struct _fll_div factors;
+ int ret, i, timeout;
+
+ if (!Fout) {
+ dev_dbg(codec->dev, "FLL disabled");
+
+ if (wm2200->fll_fout)
+ pm_runtime_put(codec->dev);
+
+ wm2200->fll_fout = 0;
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, 0);
+ return 0;
+ }
+
+ switch (source) {
+ case WM2200_FLL_SRC_MCLK1:
+ case WM2200_FLL_SRC_MCLK2:
+ case WM2200_FLL_SRC_BCLK:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid FLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = fll_factors(&factors, Fref, Fout);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the FLL while we reconfigure */
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
+ WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
+ (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
+ factors.fll_fratio);
+ if (factors.theta) {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA,
+ WM2200_FLL_FRACN_ENA);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA,
+ WM2200_FLL_EFS_ENA);
+ } else {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA, 0);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA, 0);
+ }
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
+ factors.theta);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
+ factors.n);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
+ WM2200_FLL_CLK_REF_DIV_MASK |
+ WM2200_FLL_CLK_REF_SRC_MASK,
+ (factors.fll_refclk_div
+ << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
+ WM2200_FLL_LAMBDA_MASK, factors.lambda);
+
+ /* Clear any pending completions */
+ try_wait_for_completion(&wm2200->fll_lock);
+
+ pm_runtime_get_sync(codec->dev);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, WM2200_FLL_ENA);
+
+ if (i2c->irq)
+ timeout = 2;
+ else
+ timeout = 50;
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
+ WM2200_SYSCLK_ENA);
+
+ /* Poll for the lock; will use the interrupt to exit quickly */
+ for (i = 0; i < timeout; i++) {
+ if (i2c->irq) {
+ ret = wait_for_completion_timeout(&wm2200->fll_lock,
+ msecs_to_jiffies(25));
+ if (ret > 0)
+ break;
+ } else {
+ msleep(1);
+ }
+
+ ret = snd_soc_read(codec,
+ WM2200_INTERRUPT_RAW_STATUS_2);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read FLL status: %d\n",
+ ret);
+ continue;
+ }
+ if (ret & WM2200_FLL_LOCK_STS)
+ break;
+ }
+ if (i == timeout) {
+ dev_err(codec->dev, "FLL lock timed out\n");
+ pm_runtime_put(codec->dev);
+ return -ETIMEDOUT;
+ }
+
+ wm2200->fll_src = source;
+ wm2200->fll_fref = Fref;
+ wm2200->fll_fout = Fout;
+
+ dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
+
+ return 0;
+}
+
+static int wm2200_dai_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ int ret;
+
+ ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
+ if (ret >= 0) {
+ if ((ret & WM2200_GP1_FN_MASK) != 0) {
+ dai->symmetric_rates = true;
+ val = WM2200_AIF1TX_LRCLK_SRC;
+ }
+ } else {
+ dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_SRC, val);
+
+ return 0;
+}
+
+#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM2200_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 wm2200_dai = {
+ .name = "wm2200",
+ .probe = wm2200_dai_probe,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .ops = &wm2200_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_wm2200 = {
+ .probe = wm2200_probe,
+
+ .idle_bias_off = true,
+ .ignore_pmdown_time = true,
+ .set_sysclk = wm2200_set_sysclk,
+ .set_pll = wm2200_set_fll,
+
+ .controls = wm2200_snd_controls,
+ .num_controls = ARRAY_SIZE(wm2200_snd_controls),
+ .dapm_widgets = wm2200_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
+ .dapm_routes = wm2200_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
+};
+
+static irqreturn_t wm2200_irq(int irq, void *data)
+{
+ struct wm2200_priv *wm2200 = data;
+ unsigned int val, mask;
+ int ret;
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
+ if (ret != 0) {
+ dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
+ mask = 0;
+ }
+
+ val &= ~mask;
+
+ if (val & WM2200_FLL_LOCK_EINT) {
+ dev_dbg(wm2200->dev, "FLL locked\n");
+ complete(&wm2200->fll_lock);
+ }
+
+ if (val) {
+ regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
+
+ return IRQ_HANDLED;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static const struct regmap_config wm2200_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM2200_MAX_REGISTER,
+ .reg_defaults = wm2200_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
+ .volatile_reg = wm2200_volatile_register,
+ .readable_reg = wm2200_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm2200_dig_vu[] = {
+ WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R,
+ WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R,
+ WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R,
+};
+
+static const unsigned int wm2200_mic_ctrl_reg[] = {
+ WM2200_IN1L_CONTROL,
+ WM2200_IN2L_CONTROL,
+ WM2200_IN3L_CONTROL,
+};
+
+static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+ struct wm2200_priv *wm2200;
+ unsigned int reg;
+ int ret, i;
+
+ wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
+ GFP_KERNEL);
+ if (wm2200 == NULL)
+ return -ENOMEM;
+
+ wm2200->dev = &i2c->dev;
+ init_completion(&wm2200->fll_lock);
+
+ wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+ if (IS_ERR(wm2200->regmap)) {
+ ret = PTR_ERR(wm2200->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ if (pdata)
+ wm2200->pdata = *pdata;
+
+ i2c_set_clientdata(i2c, wm2200);
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
+ wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ goto err_core;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ ret = gpio_request_one(wm2200->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+ wm2200->pdata.ldo_ena, ret);
+ goto err_enable;
+ }
+ msleep(2);
+ }
+
+ if (wm2200->pdata.reset) {
+ ret = gpio_request_one(wm2200->pdata.reset,
+ GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+ wm2200->pdata.reset, ret);
+ goto err_ldo;
+ }
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+ goto err_reset;
+ }
+ switch (reg) {
+ case 0x2200:
+ break;
+
+ default:
+ dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
+ ret = -EINVAL;
+ goto err_reset;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read revision register\n");
+ goto err_reset;
+ }
+
+ wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
+
+ dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
+
+ switch (wm2200->rev) {
+ case 0:
+ ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
+ ARRAY_SIZE(wm2200_reva_patch));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register patch: %d\n",
+ ret);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = wm2200_reset(wm2200);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_reset;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
+ if (!wm2200->pdata.gpio_defaults[i])
+ continue;
+
+ regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
+ wm2200->pdata.gpio_defaults[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
+ regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
+ WM2200_OUT_VU, WM2200_OUT_VU);
+
+ /* Assign slots 1-6 to channels 1-6 for both TX and RX */
+ for (i = 0; i < 6; i++) {
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
+ regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
+ WM2200_IN1_MODE_MASK |
+ WM2200_IN1_DMIC_SUP_MASK,
+ (wm2200->pdata.in_mode[i] <<
+ WM2200_IN1_MODE_SHIFT) |
+ (wm2200->pdata.dmic_sup[i] <<
+ WM2200_IN1_DMIC_SUP_SHIFT));
+ }
+
+ if (i2c->irq) {
+ ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wm2200", wm2200);
+ if (ret == 0)
+ regmap_update_bits(wm2200->regmap,
+ WM2200_INTERRUPT_STATUS_2_MASK,
+ WM2200_FLL_LOCK_EINT, 0);
+ else
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
+ &wm2200_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_pm_runtime;
+ }
+
+ return 0;
+
+err_pm_runtime:
+ pm_runtime_disable(&i2c->dev);
+err_reset:
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+err_ldo:
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_core:
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_regmap:
+ regmap_exit(wm2200->regmap);
+err:
+ return ret;
+}
+
+static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm2200);
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ regmap_exit(wm2200->regmap);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm2200_runtime_suspend(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm2200->regmap, true);
+ regcache_mark_dirty(wm2200->regmap);
+ if (wm2200->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+
+ return 0;
+}
+
+static int wm2200_runtime_resume(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm2200->regmap, false);
+ regcache_sync(wm2200->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm2200_pm = {
+ SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
+ NULL)
+};
+
+static const struct i2c_device_id wm2200_i2c_id[] = {
+ { "wm2200", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
+
+static struct i2c_driver wm2200_i2c_driver = {
+ .driver = {
+ .name = "wm2200",
+ .owner = THIS_MODULE,
+ .pm = &wm2200_pm,
+ },
+ .probe = wm2200_i2c_probe,
+ .remove = __devexit_p(wm2200_i2c_remove),
+ .id_table = wm2200_i2c_id,
+};
+
+static int __init wm2200_modinit(void)
+{
+ return i2c_add_driver(&wm2200_i2c_driver);
+}
+module_init(wm2200_modinit);
+
+static void __exit wm2200_exit(void)
+{
+ i2c_del_driver(&wm2200_i2c_driver);
+}
+module_exit(wm2200_exit);
+
+MODULE_DESCRIPTION("ASoC WM2200 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm2200.h b/sound/soc/codecs/wm2200.h
new file mode 100644
index 000000000000..5d719d6b4a8d
--- /dev/null
+++ b/sound/soc/codecs/wm2200.h
@@ -0,0 +1,3674 @@
+/*
+ * wm2200.h - WM2200 audio codec interface
+ *
+ * Copyright 2012 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 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _WM2200_H
+#define _WM2200_H
+
+#define WM2200_CLK_SYSCLK 1
+
+#define WM2200_CLKSRC_MCLK1 0
+#define WM2200_CLKSRC_MCLK2 1
+#define WM2200_CLKSRC_FLL 4
+#define WM2200_CLKSRC_BCLK1 8
+
+#define WM2200_FLL_SRC_MCLK1 0
+#define WM2200_FLL_SRC_MCLK2 1
+#define WM2200_FLL_SRC_BCLK 2
+
+/*
+ * Register values.
+ */
+#define WM2200_SOFTWARE_RESET 0x00
+#define WM2200_DEVICE_REVISION 0x01
+#define WM2200_TONE_GENERATOR_1 0x0B
+#define WM2200_CLOCKING_3 0x102
+#define WM2200_CLOCKING_4 0x103
+#define WM2200_FLL_CONTROL_1 0x111
+#define WM2200_FLL_CONTROL_2 0x112
+#define WM2200_FLL_CONTROL_3 0x113
+#define WM2200_FLL_CONTROL_4 0x114
+#define WM2200_FLL_CONTROL_6 0x116
+#define WM2200_FLL_CONTROL_7 0x117
+#define WM2200_FLL_EFS_1 0x119
+#define WM2200_FLL_EFS_2 0x11A
+#define WM2200_MIC_CHARGE_PUMP_1 0x200
+#define WM2200_MIC_CHARGE_PUMP_2 0x201
+#define WM2200_DM_CHARGE_PUMP_1 0x202
+#define WM2200_MIC_BIAS_CTRL_1 0x20C
+#define WM2200_MIC_BIAS_CTRL_2 0x20D
+#define WM2200_EAR_PIECE_CTRL_1 0x20F
+#define WM2200_EAR_PIECE_CTRL_2 0x210
+#define WM2200_INPUT_ENABLES 0x301
+#define WM2200_IN1L_CONTROL 0x302
+#define WM2200_IN1R_CONTROL 0x303
+#define WM2200_IN2L_CONTROL 0x304
+#define WM2200_IN2R_CONTROL 0x305
+#define WM2200_IN3L_CONTROL 0x306
+#define WM2200_IN3R_CONTROL 0x307
+#define WM2200_RXANC_SRC 0x30A
+#define WM2200_INPUT_VOLUME_RAMP 0x30B
+#define WM2200_ADC_DIGITAL_VOLUME_1L 0x30C
+#define WM2200_ADC_DIGITAL_VOLUME_1R 0x30D
+#define WM2200_ADC_DIGITAL_VOLUME_2L 0x30E
+#define WM2200_ADC_DIGITAL_VOLUME_2R 0x30F
+#define WM2200_ADC_DIGITAL_VOLUME_3L 0x310
+#define WM2200_ADC_DIGITAL_VOLUME_3R 0x311
+#define WM2200_OUTPUT_ENABLES 0x400
+#define WM2200_DAC_VOLUME_LIMIT_1L 0x401
+#define WM2200_DAC_VOLUME_LIMIT_1R 0x402
+#define WM2200_DAC_VOLUME_LIMIT_2L 0x403
+#define WM2200_DAC_VOLUME_LIMIT_2R 0x404
+#define WM2200_DAC_AEC_CONTROL_1 0x409
+#define WM2200_OUTPUT_VOLUME_RAMP 0x40A
+#define WM2200_DAC_DIGITAL_VOLUME_1L 0x40B
+#define WM2200_DAC_DIGITAL_VOLUME_1R 0x40C
+#define WM2200_DAC_DIGITAL_VOLUME_2L 0x40D
+#define WM2200_DAC_DIGITAL_VOLUME_2R 0x40E
+#define WM2200_PDM_1 0x417
+#define WM2200_PDM_2 0x418
+#define WM2200_AUDIO_IF_1_1 0x500
+#define WM2200_AUDIO_IF_1_2 0x501
+#define WM2200_AUDIO_IF_1_3 0x502
+#define WM2200_AUDIO_IF_1_4 0x503
+#define WM2200_AUDIO_IF_1_5 0x504
+#define WM2200_AUDIO_IF_1_6 0x505
+#define WM2200_AUDIO_IF_1_7 0x506
+#define WM2200_AUDIO_IF_1_8 0x507
+#define WM2200_AUDIO_IF_1_9 0x508
+#define WM2200_AUDIO_IF_1_10 0x509
+#define WM2200_AUDIO_IF_1_11 0x50A
+#define WM2200_AUDIO_IF_1_12 0x50B
+#define WM2200_AUDIO_IF_1_13 0x50C
+#define WM2200_AUDIO_IF_1_14 0x50D
+#define WM2200_AUDIO_IF_1_15 0x50E
+#define WM2200_AUDIO_IF_1_16 0x50F
+#define WM2200_AUDIO_IF_1_17 0x510
+#define WM2200_AUDIO_IF_1_18 0x511
+#define WM2200_AUDIO_IF_1_19 0x512
+#define WM2200_AUDIO_IF_1_20 0x513
+#define WM2200_AUDIO_IF_1_21 0x514
+#define WM2200_AUDIO_IF_1_22 0x515
+#define WM2200_OUT1LMIX_INPUT_1_SOURCE 0x600
+#define WM2200_OUT1LMIX_INPUT_1_VOLUME 0x601
+#define WM2200_OUT1LMIX_INPUT_2_SOURCE 0x602
+#define WM2200_OUT1LMIX_INPUT_2_VOLUME 0x603
+#define WM2200_OUT1LMIX_INPUT_3_SOURCE 0x604
+#define WM2200_OUT1LMIX_INPUT_3_VOLUME 0x605
+#define WM2200_OUT1LMIX_INPUT_4_SOURCE 0x606
+#define WM2200_OUT1LMIX_INPUT_4_VOLUME 0x607
+#define WM2200_OUT1RMIX_INPUT_1_SOURCE 0x608
+#define WM2200_OUT1RMIX_INPUT_1_VOLUME 0x609
+#define WM2200_OUT1RMIX_INPUT_2_SOURCE 0x60A
+#define WM2200_OUT1RMIX_INPUT_2_VOLUME 0x60B
+#define WM2200_OUT1RMIX_INPUT_3_SOURCE 0x60C
+#define WM2200_OUT1RMIX_INPUT_3_VOLUME 0x60D
+#define WM2200_OUT1RMIX_INPUT_4_SOURCE 0x60E
+#define WM2200_OUT1RMIX_INPUT_4_VOLUME 0x60F
+#define WM2200_OUT2LMIX_INPUT_1_SOURCE 0x610
+#define WM2200_OUT2LMIX_INPUT_1_VOLUME 0x611
+#define WM2200_OUT2LMIX_INPUT_2_SOURCE 0x612
+#define WM2200_OUT2LMIX_INPUT_2_VOLUME 0x613
+#define WM2200_OUT2LMIX_INPUT_3_SOURCE 0x614
+#define WM2200_OUT2LMIX_INPUT_3_VOLUME 0x615
+#define WM2200_OUT2LMIX_INPUT_4_SOURCE 0x616
+#define WM2200_OUT2LMIX_INPUT_4_VOLUME 0x617
+#define WM2200_OUT2RMIX_INPUT_1_SOURCE 0x618
+#define WM2200_OUT2RMIX_INPUT_1_VOLUME 0x619
+#define WM2200_OUT2RMIX_INPUT_2_SOURCE 0x61A
+#define WM2200_OUT2RMIX_INPUT_2_VOLUME 0x61B
+#define WM2200_OUT2RMIX_INPUT_3_SOURCE 0x61C
+#define WM2200_OUT2RMIX_INPUT_3_VOLUME 0x61D
+#define WM2200_OUT2RMIX_INPUT_4_SOURCE 0x61E
+#define WM2200_OUT2RMIX_INPUT_4_VOLUME 0x61F
+#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE 0x620
+#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME 0x621
+#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE 0x622
+#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME 0x623
+#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE 0x624
+#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME 0x625
+#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE 0x626
+#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME 0x627
+#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE 0x628
+#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME 0x629
+#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE 0x62A
+#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME 0x62B
+#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE 0x62C
+#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME 0x62D
+#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE 0x62E
+#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME 0x62F
+#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE 0x630
+#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME 0x631
+#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE 0x632
+#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME 0x633
+#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE 0x634
+#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME 0x635
+#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE 0x636
+#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME 0x637
+#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE 0x638
+#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME 0x639
+#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE 0x63A
+#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME 0x63B
+#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE 0x63C
+#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME 0x63D
+#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE 0x63E
+#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME 0x63F
+#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE 0x640
+#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME 0x641
+#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE 0x642
+#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME 0x643
+#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE 0x644
+#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME 0x645
+#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE 0x646
+#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME 0x647
+#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE 0x648
+#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME 0x649
+#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE 0x64A
+#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME 0x64B
+#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE 0x64C
+#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME 0x64D
+#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE 0x64E
+#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME 0x64F
+#define WM2200_EQLMIX_INPUT_1_SOURCE 0x650
+#define WM2200_EQLMIX_INPUT_1_VOLUME 0x651
+#define WM2200_EQLMIX_INPUT_2_SOURCE 0x652
+#define WM2200_EQLMIX_INPUT_2_VOLUME 0x653
+#define WM2200_EQLMIX_INPUT_3_SOURCE 0x654
+#define WM2200_EQLMIX_INPUT_3_VOLUME 0x655
+#define WM2200_EQLMIX_INPUT_4_SOURCE 0x656
+#define WM2200_EQLMIX_INPUT_4_VOLUME 0x657
+#define WM2200_EQRMIX_INPUT_1_SOURCE 0x658
+#define WM2200_EQRMIX_INPUT_1_VOLUME 0x659
+#define WM2200_EQRMIX_INPUT_2_SOURCE 0x65A
+#define WM2200_EQRMIX_INPUT_2_VOLUME 0x65B
+#define WM2200_EQRMIX_INPUT_3_SOURCE 0x65C
+#define WM2200_EQRMIX_INPUT_3_VOLUME 0x65D
+#define WM2200_EQRMIX_INPUT_4_SOURCE 0x65E
+#define WM2200_EQRMIX_INPUT_4_VOLUME 0x65F
+#define WM2200_LHPF1MIX_INPUT_1_SOURCE 0x660
+#define WM2200_LHPF1MIX_INPUT_1_VOLUME 0x661
+#define WM2200_LHPF1MIX_INPUT_2_SOURCE 0x662
+#define WM2200_LHPF1MIX_INPUT_2_VOLUME 0x663
+#define WM2200_LHPF1MIX_INPUT_3_SOURCE 0x664
+#define WM2200_LHPF1MIX_INPUT_3_VOLUME 0x665
+#define WM2200_LHPF1MIX_INPUT_4_SOURCE 0x666
+#define WM2200_LHPF1MIX_INPUT_4_VOLUME 0x667
+#define WM2200_LHPF2MIX_INPUT_1_SOURCE 0x668
+#define WM2200_LHPF2MIX_INPUT_1_VOLUME 0x669
+#define WM2200_LHPF2MIX_INPUT_2_SOURCE 0x66A
+#define WM2200_LHPF2MIX_INPUT_2_VOLUME 0x66B
+#define WM2200_LHPF2MIX_INPUT_3_SOURCE 0x66C
+#define WM2200_LHPF2MIX_INPUT_3_VOLUME 0x66D
+#define WM2200_LHPF2MIX_INPUT_4_SOURCE 0x66E
+#define WM2200_LHPF2MIX_INPUT_4_VOLUME 0x66F
+#define WM2200_DSP1LMIX_INPUT_1_SOURCE 0x670
+#define WM2200_DSP1LMIX_INPUT_1_VOLUME 0x671
+#define WM2200_DSP1LMIX_INPUT_2_SOURCE 0x672
+#define WM2200_DSP1LMIX_INPUT_2_VOLUME 0x673
+#define WM2200_DSP1LMIX_INPUT_3_SOURCE 0x674
+#define WM2200_DSP1LMIX_INPUT_3_VOLUME 0x675
+#define WM2200_DSP1LMIX_INPUT_4_SOURCE 0x676
+#define WM2200_DSP1LMIX_INPUT_4_VOLUME 0x677
+#define WM2200_DSP1RMIX_INPUT_1_SOURCE 0x678
+#define WM2200_DSP1RMIX_INPUT_1_VOLUME 0x679
+#define WM2200_DSP1RMIX_INPUT_2_SOURCE 0x67A
+#define WM2200_DSP1RMIX_INPUT_2_VOLUME 0x67B
+#define WM2200_DSP1RMIX_INPUT_3_SOURCE 0x67C
+#define WM2200_DSP1RMIX_INPUT_3_VOLUME 0x67D
+#define WM2200_DSP1RMIX_INPUT_4_SOURCE 0x67E
+#define WM2200_DSP1RMIX_INPUT_4_VOLUME 0x67F
+#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE 0x680
+#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE 0x681
+#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE 0x682
+#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE 0x683
+#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE 0x684
+#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE 0x685
+#define WM2200_DSP2LMIX_INPUT_1_SOURCE 0x686
+#define WM2200_DSP2LMIX_INPUT_1_VOLUME 0x687
+#define WM2200_DSP2LMIX_INPUT_2_SOURCE 0x688
+#define WM2200_DSP2LMIX_INPUT_2_VOLUME 0x689
+#define WM2200_DSP2LMIX_INPUT_3_SOURCE 0x68A
+#define WM2200_DSP2LMIX_INPUT_3_VOLUME 0x68B
+#define WM2200_DSP2LMIX_INPUT_4_SOURCE 0x68C
+#define WM2200_DSP2LMIX_INPUT_4_VOLUME 0x68D
+#define WM2200_DSP2RMIX_INPUT_1_SOURCE 0x68E
+#define WM2200_DSP2RMIX_INPUT_1_VOLUME 0x68F
+#define WM2200_DSP2RMIX_INPUT_2_SOURCE 0x690
+#define WM2200_DSP2RMIX_INPUT_2_VOLUME 0x691
+#define WM2200_DSP2RMIX_INPUT_3_SOURCE 0x692
+#define WM2200_DSP2RMIX_INPUT_3_VOLUME 0x693
+#define WM2200_DSP2RMIX_INPUT_4_SOURCE 0x694
+#define WM2200_DSP2RMIX_INPUT_4_VOLUME 0x695
+#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE 0x696
+#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE 0x697
+#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE 0x698
+#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE 0x699
+#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE 0x69A
+#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE 0x69B
+#define WM2200_GPIO_CTRL_1 0x700
+#define WM2200_GPIO_CTRL_2 0x701
+#define WM2200_GPIO_CTRL_3 0x702
+#define WM2200_GPIO_CTRL_4 0x703
+#define WM2200_ADPS1_IRQ0 0x707
+#define WM2200_ADPS1_IRQ1 0x708
+#define WM2200_MISC_PAD_CTRL_1 0x709
+#define WM2200_INTERRUPT_STATUS_1 0x800
+#define WM2200_INTERRUPT_STATUS_1_MASK 0x801
+#define WM2200_INTERRUPT_STATUS_2 0x802
+#define WM2200_INTERRUPT_RAW_STATUS_2 0x803
+#define WM2200_INTERRUPT_STATUS_2_MASK 0x804
+#define WM2200_INTERRUPT_CONTROL 0x808
+#define WM2200_EQL_1 0x900
+#define WM2200_EQL_2 0x901
+#define WM2200_EQL_3 0x902
+#define WM2200_EQL_4 0x903
+#define WM2200_EQL_5 0x904
+#define WM2200_EQL_6 0x905
+#define WM2200_EQL_7 0x906
+#define WM2200_EQL_8 0x907
+#define WM2200_EQL_9 0x908
+#define WM2200_EQL_10 0x909
+#define WM2200_EQL_11 0x90A
+#define WM2200_EQL_12 0x90B
+#define WM2200_EQL_13 0x90C
+#define WM2200_EQL_14 0x90D
+#define WM2200_EQL_15 0x90E
+#define WM2200_EQL_16 0x90F
+#define WM2200_EQL_17 0x910
+#define WM2200_EQL_18 0x911
+#define WM2200_EQL_19 0x912
+#define WM2200_EQL_20 0x913
+#define WM2200_EQR_1 0x916
+#define WM2200_EQR_2 0x917
+#define WM2200_EQR_3 0x918
+#define WM2200_EQR_4 0x919
+#define WM2200_EQR_5 0x91A
+#define WM2200_EQR_6 0x91B
+#define WM2200_EQR_7 0x91C
+#define WM2200_EQR_8 0x91D
+#define WM2200_EQR_9 0x91E
+#define WM2200_EQR_10 0x91F
+#define WM2200_EQR_11 0x920
+#define WM2200_EQR_12 0x921
+#define WM2200_EQR_13 0x922
+#define WM2200_EQR_14 0x923
+#define WM2200_EQR_15 0x924
+#define WM2200_EQR_16 0x925
+#define WM2200_EQR_17 0x926
+#define WM2200_EQR_18 0x927
+#define WM2200_EQR_19 0x928
+#define WM2200_EQR_20 0x929
+#define WM2200_HPLPF1_1 0x93E
+#define WM2200_HPLPF1_2 0x93F
+#define WM2200_HPLPF2_1 0x942
+#define WM2200_HPLPF2_2 0x943
+#define WM2200_DSP1_CONTROL_1 0xA00
+#define WM2200_DSP1_CONTROL_2 0xA02
+#define WM2200_DSP1_CONTROL_3 0xA03
+#define WM2200_DSP1_CONTROL_4 0xA04
+#define WM2200_DSP1_CONTROL_5 0xA06
+#define WM2200_DSP1_CONTROL_6 0xA07
+#define WM2200_DSP1_CONTROL_7 0xA08
+#define WM2200_DSP1_CONTROL_8 0xA09
+#define WM2200_DSP1_CONTROL_9 0xA0A
+#define WM2200_DSP1_CONTROL_10 0xA0B
+#define WM2200_DSP1_CONTROL_11 0xA0C
+#define WM2200_DSP1_CONTROL_12 0xA0D
+#define WM2200_DSP1_CONTROL_13 0xA0F
+#define WM2200_DSP1_CONTROL_14 0xA10
+#define WM2200_DSP1_CONTROL_15 0xA11
+#define WM2200_DSP1_CONTROL_16 0xA12
+#define WM2200_DSP1_CONTROL_17 0xA13
+#define WM2200_DSP1_CONTROL_18 0xA14
+#define WM2200_DSP1_CONTROL_19 0xA16
+#define WM2200_DSP1_CONTROL_20 0xA17
+#define WM2200_DSP1_CONTROL_21 0xA18
+#define WM2200_DSP1_CONTROL_22 0xA1A
+#define WM2200_DSP1_CONTROL_23 0xA1B
+#define WM2200_DSP1_CONTROL_24 0xA1C
+#define WM2200_DSP1_CONTROL_25 0xA1E
+#define WM2200_DSP1_CONTROL_26 0xA20
+#define WM2200_DSP1_CONTROL_27 0xA21
+#define WM2200_DSP1_CONTROL_28 0xA22
+#define WM2200_DSP1_CONTROL_29 0xA23
+#define WM2200_DSP1_CONTROL_30 0xA24
+#define WM2200_DSP1_CONTROL_31 0xA26
+#define WM2200_DSP2_CONTROL_1 0xB00
+#define WM2200_DSP2_CONTROL_2 0xB02
+#define WM2200_DSP2_CONTROL_3 0xB03
+#define WM2200_DSP2_CONTROL_4 0xB04
+#define WM2200_DSP2_CONTROL_5 0xB06
+#define WM2200_DSP2_CONTROL_6 0xB07
+#define WM2200_DSP2_CONTROL_7 0xB08
+#define WM2200_DSP2_CONTROL_8 0xB09
+#define WM2200_DSP2_CONTROL_9 0xB0A
+#define WM2200_DSP2_CONTROL_10 0xB0B
+#define WM2200_DSP2_CONTROL_11 0xB0C
+#define WM2200_DSP2_CONTROL_12 0xB0D
+#define WM2200_DSP2_CONTROL_13 0xB0F
+#define WM2200_DSP2_CONTROL_14 0xB10
+#define WM2200_DSP2_CONTROL_15 0xB11
+#define WM2200_DSP2_CONTROL_16 0xB12
+#define WM2200_DSP2_CONTROL_17 0xB13
+#define WM2200_DSP2_CONTROL_18 0xB14
+#define WM2200_DSP2_CONTROL_19 0xB16
+#define WM2200_DSP2_CONTROL_20 0xB17
+#define WM2200_DSP2_CONTROL_21 0xB18
+#define WM2200_DSP2_CONTROL_22 0xB1A
+#define WM2200_DSP2_CONTROL_23 0xB1B
+#define WM2200_DSP2_CONTROL_24 0xB1C
+#define WM2200_DSP2_CONTROL_25 0xB1E
+#define WM2200_DSP2_CONTROL_26 0xB20
+#define WM2200_DSP2_CONTROL_27 0xB21
+#define WM2200_DSP2_CONTROL_28 0xB22
+#define WM2200_DSP2_CONTROL_29 0xB23
+#define WM2200_DSP2_CONTROL_30 0xB24
+#define WM2200_DSP2_CONTROL_31 0xB26
+#define WM2200_ANC_CTRL1 0xD00
+#define WM2200_ANC_CTRL2 0xD01
+#define WM2200_ANC_CTRL3 0xD02
+#define WM2200_ANC_CTRL7 0xD08
+#define WM2200_ANC_CTRL8 0xD09
+#define WM2200_ANC_CTRL9 0xD0A
+#define WM2200_ANC_CTRL10 0xD0B
+#define WM2200_ANC_CTRL11 0xD0C
+#define WM2200_ANC_CTRL12 0xD0D
+#define WM2200_ANC_CTRL13 0xD0E
+#define WM2200_ANC_CTRL14 0xD0F
+#define WM2200_ANC_CTRL15 0xD10
+#define WM2200_ANC_CTRL16 0xD11
+#define WM2200_ANC_CTRL17 0xD12
+#define WM2200_ANC_CTRL18 0xD15
+#define WM2200_ANC_CTRL19 0xD16
+#define WM2200_ANC_CTRL20 0xD17
+#define WM2200_ANC_CTRL21 0xD18
+#define WM2200_ANC_CTRL22 0xD19
+#define WM2200_ANC_CTRL23 0xD1A
+#define WM2200_ANC_CTRL24 0xD1B
+#define WM2200_ANC_CTRL25 0xD1C
+#define WM2200_ANC_CTRL26 0xD1D
+#define WM2200_ANC_CTRL27 0xD1E
+#define WM2200_ANC_CTRL28 0xD1F
+#define WM2200_ANC_CTRL29 0xD20
+#define WM2200_ANC_CTRL30 0xD21
+#define WM2200_ANC_CTRL31 0xD23
+#define WM2200_ANC_CTRL32 0xD24
+#define WM2200_ANC_CTRL33 0xD25
+#define WM2200_ANC_CTRL34 0xD27
+#define WM2200_ANC_CTRL35 0xD28
+#define WM2200_ANC_CTRL36 0xD29
+#define WM2200_ANC_CTRL37 0xD2A
+#define WM2200_ANC_CTRL38 0xD2B
+#define WM2200_ANC_CTRL39 0xD2C
+#define WM2200_ANC_CTRL40 0xD2D
+#define WM2200_ANC_CTRL41 0xD2E
+#define WM2200_ANC_CTRL42 0xD2F
+#define WM2200_ANC_CTRL43 0xD30
+#define WM2200_ANC_CTRL44 0xD31
+#define WM2200_ANC_CTRL45 0xD32
+#define WM2200_ANC_CTRL46 0xD33
+#define WM2200_ANC_CTRL47 0xD34
+#define WM2200_ANC_CTRL48 0xD35
+#define WM2200_ANC_CTRL49 0xD36
+#define WM2200_ANC_CTRL50 0xD37
+#define WM2200_ANC_CTRL51 0xD38
+#define WM2200_ANC_CTRL52 0xD39
+#define WM2200_ANC_CTRL53 0xD3A
+#define WM2200_ANC_CTRL54 0xD3B
+#define WM2200_ANC_CTRL55 0xD3C
+#define WM2200_ANC_CTRL56 0xD3D
+#define WM2200_ANC_CTRL57 0xD3E
+#define WM2200_ANC_CTRL58 0xD3F
+#define WM2200_ANC_CTRL59 0xD40
+#define WM2200_ANC_CTRL60 0xD41
+#define WM2200_ANC_CTRL61 0xD42
+#define WM2200_ANC_CTRL62 0xD43
+#define WM2200_ANC_CTRL63 0xD44
+#define WM2200_ANC_CTRL64 0xD45
+#define WM2200_ANC_CTRL65 0xD46
+#define WM2200_ANC_CTRL66 0xD47
+#define WM2200_ANC_CTRL67 0xD48
+#define WM2200_ANC_CTRL68 0xD49
+#define WM2200_ANC_CTRL69 0xD4A
+#define WM2200_ANC_CTRL70 0xD4B
+#define WM2200_ANC_CTRL71 0xD4C
+#define WM2200_ANC_CTRL72 0xD4D
+#define WM2200_ANC_CTRL73 0xD4E
+#define WM2200_ANC_CTRL74 0xD4F
+#define WM2200_ANC_CTRL75 0xD50
+#define WM2200_ANC_CTRL76 0xD51
+#define WM2200_ANC_CTRL77 0xD52
+#define WM2200_ANC_CTRL78 0xD53
+#define WM2200_ANC_CTRL79 0xD54
+#define WM2200_ANC_CTRL80 0xD55
+#define WM2200_ANC_CTRL81 0xD56
+#define WM2200_ANC_CTRL82 0xD57
+#define WM2200_ANC_CTRL83 0xD58
+#define WM2200_ANC_CTRL84 0xD5B
+#define WM2200_ANC_CTRL85 0xD5C
+#define WM2200_ANC_CTRL86 0xD5F
+#define WM2200_ANC_CTRL87 0xD60
+#define WM2200_ANC_CTRL88 0xD61
+#define WM2200_ANC_CTRL89 0xD62
+#define WM2200_ANC_CTRL90 0xD63
+#define WM2200_ANC_CTRL91 0xD64
+#define WM2200_ANC_CTRL92 0xD65
+#define WM2200_ANC_CTRL93 0xD66
+#define WM2200_ANC_CTRL94 0xD67
+#define WM2200_ANC_CTRL95 0xD68
+#define WM2200_ANC_CTRL96 0xD69
+#define WM2200_DSP1_DM_0 0x3000
+#define WM2200_DSP1_DM_1 0x3001
+#define WM2200_DSP1_DM_2 0x3002
+#define WM2200_DSP1_DM_3 0x3003
+#define WM2200_DSP1_DM_2044 0x37FC
+#define WM2200_DSP1_DM_2045 0x37FD
+#define WM2200_DSP1_DM_2046 0x37FE
+#define WM2200_DSP1_DM_2047 0x37FF
+#define WM2200_DSP1_PM_0 0x3800
+#define WM2200_DSP1_PM_1 0x3801
+#define WM2200_DSP1_PM_2 0x3802
+#define WM2200_DSP1_PM_3 0x3803
+#define WM2200_DSP1_PM_4 0x3804
+#define WM2200_DSP1_PM_5 0x3805
+#define WM2200_DSP1_PM_762 0x3AFA
+#define WM2200_DSP1_PM_763 0x3AFB
+#define WM2200_DSP1_PM_764 0x3AFC
+#define WM2200_DSP1_PM_765 0x3AFD
+#define WM2200_DSP1_PM_766 0x3AFE
+#define WM2200_DSP1_PM_767 0x3AFF
+#define WM2200_DSP1_ZM_0 0x3C00
+#define WM2200_DSP1_ZM_1 0x3C01
+#define WM2200_DSP1_ZM_2 0x3C02
+#define WM2200_DSP1_ZM_3 0x3C03
+#define WM2200_DSP1_ZM_1020 0x3FFC
+#define WM2200_DSP1_ZM_1021 0x3FFD
+#define WM2200_DSP1_ZM_1022 0x3FFE
+#define WM2200_DSP1_ZM_1023 0x3FFF
+#define WM2200_DSP2_DM_0 0x4000
+#define WM2200_DSP2_DM_1 0x4001
+#define WM2200_DSP2_DM_2 0x4002
+#define WM2200_DSP2_DM_3 0x4003
+#define WM2200_DSP2_DM_2044 0x47FC
+#define WM2200_DSP2_DM_2045 0x47FD
+#define WM2200_DSP2_DM_2046 0x47FE
+#define WM2200_DSP2_DM_2047 0x47FF
+#define WM2200_DSP2_PM_0 0x4800
+#define WM2200_DSP2_PM_1 0x4801
+#define WM2200_DSP2_PM_2 0x4802
+#define WM2200_DSP2_PM_3 0x4803
+#define WM2200_DSP2_PM_4 0x4804
+#define WM2200_DSP2_PM_5 0x4805
+#define WM2200_DSP2_PM_762 0x4AFA
+#define WM2200_DSP2_PM_763 0x4AFB
+#define WM2200_DSP2_PM_764 0x4AFC
+#define WM2200_DSP2_PM_765 0x4AFD
+#define WM2200_DSP2_PM_766 0x4AFE
+#define WM2200_DSP2_PM_767 0x4AFF
+#define WM2200_DSP2_ZM_0 0x4C00
+#define WM2200_DSP2_ZM_1 0x4C01
+#define WM2200_DSP2_ZM_2 0x4C02
+#define WM2200_DSP2_ZM_3 0x4C03
+#define WM2200_DSP2_ZM_1020 0x4FFC
+#define WM2200_DSP2_ZM_1021 0x4FFD
+#define WM2200_DSP2_ZM_1022 0x4FFE
+#define WM2200_DSP2_ZM_1023 0x4FFF
+
+#define WM2200_REGISTER_COUNT 494
+#define WM2200_MAX_REGISTER 0x4FFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM2200_SW_RESET_CHIP_ID1_MASK 0xFFFF /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_SHIFT 0 /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_WIDTH 16 /* SW_RESET_CHIP_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM2200_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R11 (0x0B) - Tone Generator 1
+ */
+#define WM2200_TONE_ENA 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_MASK 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_SHIFT 0 /* TONE_ENA */
+#define WM2200_TONE_ENA_WIDTH 1 /* TONE_ENA */
+
+/*
+ * R258 (0x102) - Clocking 3
+ */
+#define WM2200_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R259 (0x103) - Clocking 4
+ */
+#define WM2200_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R273 (0x111) - FLL Control 1
+ */
+#define WM2200_FLL_ENA 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_MASK 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_SHIFT 0 /* FLL_ENA */
+#define WM2200_FLL_ENA_WIDTH 1 /* FLL_ENA */
+
+/*
+ * R274 (0x112) - FLL Control 2
+ */
+#define WM2200_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
+
+/*
+ * R275 (0x113) - FLL Control 3
+ */
+#define WM2200_FLL_FRACN_ENA 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_MASK 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_SHIFT 0 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */
+
+/*
+ * R276 (0x114) - FLL Control 4
+ */
+#define WM2200_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */
+
+/*
+ * R278 (0x116) - FLL Control 6
+ */
+#define WM2200_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */
+#define WM2200_FLL_N_SHIFT 0 /* FLL_N - [9:0] */
+#define WM2200_FLL_N_WIDTH 10 /* FLL_N - [9:0] */
+
+/*
+ * R279 (0x117) - FLL Control 7
+ */
+#define WM2200_FLL_CLK_REF_DIV_MASK 0x0030 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_SHIFT 4 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */
+
+/*
+ * R281 (0x119) - FLL EFS 1
+ */
+#define WM2200_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R282 (0x11A) - FLL EFS 2
+ */
+#define WM2200_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM2200_CPMIC_BYPASS_MODE 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_MASK 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_SHIFT 5 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_WIDTH 1 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_ENA 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_MASK 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_SHIFT 0 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_WIDTH 1 /* CPMIC_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK 0xF800 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT 11 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH 5 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+
+/*
+ * R514 (0x202) - DM Charge Pump 1
+ */
+#define WM2200_CPDM_ENA 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_MASK 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_SHIFT 0 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_WIDTH 1 /* CPDM_ENA */
+
+/*
+ * R524 (0x20C) - Mic Bias Ctrl 1
+ */
+#define WM2200_MICB1_DISCH 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */
+#define WM2200_MICB1_RATE 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_SHIFT 5 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_WIDTH 1 /* MICB1_RATE */
+#define WM2200_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_MODE 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_MASK 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_SHIFT 1 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_WIDTH 1 /* MICB1_MODE */
+#define WM2200_MICB1_ENA 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_SHIFT 0 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+
+/*
+ * R525 (0x20D) - Mic Bias Ctrl 2
+ */
+#define WM2200_MICB2_DISCH 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
+#define WM2200_MICB2_RATE 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_SHIFT 5 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_WIDTH 1 /* MICB2_RATE */
+#define WM2200_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_MODE 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_MASK 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_SHIFT 1 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_WIDTH 1 /* MICB2_MODE */
+#define WM2200_MICB2_ENA 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_SHIFT 0 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+
+/*
+ * R527 (0x20F) - Ear Piece Ctrl 1
+ */
+#define WM2200_EPD_LP_ENA 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_MASK 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_SHIFT 14 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_WIDTH 1 /* EPD_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_MASK 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_SHIFT 13 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_WIDTH 1 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_RMV_SHRT_LP 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_MASK 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_SHIFT 12 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_WIDTH 1 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_LN_ENA 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_MASK 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_SHIFT 11 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_WIDTH 1 /* EPD_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_MASK 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_SHIFT 10 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_WIDTH 1 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_RMV_SHRT_LN 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_MASK 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_SHIFT 9 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_WIDTH 1 /* EPD_RMV_SHRT_LN */
+
+/*
+ * R528 (0x210) - Ear Piece Ctrl 2
+ */
+#define WM2200_EPD_RP_ENA 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_MASK 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_SHIFT 14 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_WIDTH 1 /* EPD_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_MASK 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_SHIFT 13 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_WIDTH 1 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_RMV_SHRT_RP 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_MASK 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_SHIFT 12 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_WIDTH 1 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RN_ENA 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_MASK 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_SHIFT 11 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_WIDTH 1 /* EPD_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_MASK 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_SHIFT 10 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_WIDTH 1 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_RMV_SHRT_RN 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_MASK 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_SHIFT 9 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_WIDTH 1 /* EPD_RMV_SHRT_RN */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM2200_IN3L_ENA 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_SHIFT 5 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_WIDTH 1 /* IN3L_ENA */
+#define WM2200_IN3R_ENA 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_SHIFT 4 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_WIDTH 1 /* IN3R_ENA */
+#define WM2200_IN2L_ENA 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_SHIFT 3 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM2200_IN2R_ENA 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_SHIFT 2 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM2200_IN1L_ENA 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_SHIFT 1 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM2200_IN1R_ENA 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_SHIFT 0 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - IN1L Control
+ */
+#define WM2200_IN1_OSR 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_MASK 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_SHIFT 13 /* IN1_OSR */
+#define WM2200_IN1_OSR_WIDTH 1 /* IN1_OSR */
+#define WM2200_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */
+#define WM2200_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R771 (0x303) - IN1R Control
+ */
+#define WM2200_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R772 (0x304) - IN2L Control
+ */
+#define WM2200_IN2_OSR 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_MASK 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_SHIFT 13 /* IN2_OSR */
+#define WM2200_IN2_OSR_WIDTH 1 /* IN2_OSR */
+#define WM2200_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */
+#define WM2200_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R773 (0x305) - IN2R Control
+ */
+#define WM2200_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R774 (0x306) - IN3L Control
+ */
+#define WM2200_IN3_OSR 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_MASK 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_SHIFT 13 /* IN3_OSR */
+#define WM2200_IN3_OSR_WIDTH 1 /* IN3_OSR */
+#define WM2200_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */
+#define WM2200_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R775 (0x307) - IN3R Control
+ */
+#define WM2200_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R778 (0x30A) - RXANC_SRC
+ */
+#define WM2200_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R779 (0x30B) - Input Volume Ramp
+ */
+#define WM2200_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R780 (0x30C) - ADC Digital Volume 1L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1L_MUTE 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM2200_IN1L_DIG_VOL_MASK 0x00FF /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_SHIFT 0 /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_WIDTH 8 /* IN1L_DIG_VOL - [7:0] */
+
+/*
+ * R781 (0x30D) - ADC Digital Volume 1R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1R_MUTE 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM2200_IN1R_DIG_VOL_MASK 0x00FF /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_SHIFT 0 /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_WIDTH 8 /* IN1R_DIG_VOL - [7:0] */
+
+/*
+ * R782 (0x30E) - ADC Digital Volume 2L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2L_MUTE 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM2200_IN2L_DIG_VOL_MASK 0x00FF /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_SHIFT 0 /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_WIDTH 8 /* IN2L_DIG_VOL - [7:0] */
+
+/*
+ * R783 (0x30F) - ADC Digital Volume 2R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2R_MUTE 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM2200_IN2R_DIG_VOL_MASK 0x00FF /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_SHIFT 0 /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_WIDTH 8 /* IN2R_DIG_VOL - [7:0] */
+
+/*
+ * R784 (0x310) - ADC Digital Volume 3L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3L_MUTE 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */
+#define WM2200_IN3L_DIG_VOL_MASK 0x00FF /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_SHIFT 0 /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_WIDTH 8 /* IN3L_DIG_VOL - [7:0] */
+
+/*
+ * R785 (0x311) - ADC Digital Volume 3R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3R_MUTE 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */
+#define WM2200_IN3R_DIG_VOL_MASK 0x00FF /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_SHIFT 0 /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_WIDTH 8 /* IN3R_DIG_VOL - [7:0] */
+
+/*
+ * R1024 (0x400) - Output Enables
+ */
+#define WM2200_OUT2L_ENA 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_MASK 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_SHIFT 3 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_WIDTH 1 /* OUT2L_ENA */
+#define WM2200_OUT2R_ENA 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_MASK 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_SHIFT 2 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_WIDTH 1 /* OUT2R_ENA */
+#define WM2200_OUT1L_ENA 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_MASK 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_SHIFT 1 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_WIDTH 1 /* OUT1L_ENA */
+#define WM2200_OUT1R_ENA 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_MASK 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_SHIFT 0 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_WIDTH 1 /* OUT1R_ENA */
+
+/*
+ * R1025 (0x401) - DAC Volume Limit 1L
+ */
+#define WM2200_OUT1_OSR 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_SHIFT 13 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_WIDTH 1 /* OUT1_OSR */
+#define WM2200_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1026 (0x402) - DAC Volume Limit 1R
+ */
+#define WM2200_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1027 (0x403) - DAC Volume Limit 2L
+ */
+#define WM2200_OUT2_OSR 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_SHIFT 13 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_WIDTH 1 /* OUT2_OSR */
+#define WM2200_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */
+
+/*
+ * R1028 (0x404) - DAC Volume Limit 2R
+ */
+#define WM2200_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */
+
+/*
+ * R1033 (0x409) - DAC AEC Control 1
+ */
+#define WM2200_AEC_LOOPBACK_ENA 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_MASK 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_SHIFT 2 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_SRC_MASK 0x0003 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_SHIFT 0 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_WIDTH 2 /* AEC_LOOPBACK_SRC - [1:0] */
+
+/*
+ * R1034 (0x40A) - Output Volume Ramp
+ */
+#define WM2200_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1035 (0x40B) - DAC Digital Volume 1L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */
+#define WM2200_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1036 (0x40C) - DAC Digital Volume 1R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */
+#define WM2200_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1037 (0x40D) - DAC Digital Volume 2L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */
+#define WM2200_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1038 (0x40E) - DAC Digital Volume 2R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */
+#define WM2200_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1047 (0x417) - PDM 1
+ */
+#define WM2200_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */
+#define WM2200_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */
+#define WM2200_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_SEQL_MASK 0x00FF /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_SHIFT 0 /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_WIDTH 8 /* SPK1_MUTE_SEQL - [7:0] */
+
+/*
+ * R1048 (0x418) - PDM 2
+ */
+#define WM2200_SPK1_FMT 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_SHIFT 0 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_WIDTH 1 /* SPK1_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM2200_AIF1_BCLK_INV 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_MASK 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_SHIFT 6 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_FRC 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_MASK 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_SHIFT 5 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_MSTR 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_MASK 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_SHIFT 4 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM2200_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM2200_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM2200_AIF1_TRI 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_SHIFT 6 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM2200_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM2200_AIF1TX_BCPF_MASK 0x07FF /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_WIDTH 11 /* AIF1TX_BCPF - [10:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM2200_AIF1RX_BCPF_MASK 0x07FF /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_WIDTH 11 /* AIF1RX_BCPF - [10:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM2200_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM2200_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM2200_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM2200_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM2200_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM2200_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM2200_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM2200_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM2200_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM2200_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM2200_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM2200_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM2200_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM2200_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM2200_AIF1RX6_ENA 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_MASK 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_SHIFT 11 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX5_ENA 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_MASK 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_SHIFT 10 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX4_ENA 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_MASK 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_SHIFT 9 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX3_ENA 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_MASK 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_SHIFT 8 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX2_ENA 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_MASK 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_SHIFT 7 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX1_ENA 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_MASK 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_SHIFT 6 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */
+#define WM2200_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */
+
+/*
+ * R1536 (0x600) - OUT1LMIX Input 1 Source
+ */
+#define WM2200_OUT1LMIX_SRC1_MASK 0x007F /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_SHIFT 0 /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_WIDTH 7 /* OUT1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1537 (0x601) - OUT1LMIX Input 1 Volume
+ */
+#define WM2200_OUT1LMIX_VOL1_MASK 0x00FE /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_SHIFT 1 /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_WIDTH 7 /* OUT1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1538 (0x602) - OUT1LMIX Input 2 Source
+ */
+#define WM2200_OUT1LMIX_SRC2_MASK 0x007F /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_SHIFT 0 /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_WIDTH 7 /* OUT1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1539 (0x603) - OUT1LMIX Input 2 Volume
+ */
+#define WM2200_OUT1LMIX_VOL2_MASK 0x00FE /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_SHIFT 1 /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_WIDTH 7 /* OUT1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1540 (0x604) - OUT1LMIX Input 3 Source
+ */
+#define WM2200_OUT1LMIX_SRC3_MASK 0x007F /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_SHIFT 0 /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_WIDTH 7 /* OUT1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1541 (0x605) - OUT1LMIX Input 3 Volume
+ */
+#define WM2200_OUT1LMIX_VOL3_MASK 0x00FE /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_SHIFT 1 /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_WIDTH 7 /* OUT1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1542 (0x606) - OUT1LMIX Input 4 Source
+ */
+#define WM2200_OUT1LMIX_SRC4_MASK 0x007F /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_SHIFT 0 /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_WIDTH 7 /* OUT1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1543 (0x607) - OUT1LMIX Input 4 Volume
+ */
+#define WM2200_OUT1LMIX_VOL4_MASK 0x00FE /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_SHIFT 1 /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_WIDTH 7 /* OUT1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1544 (0x608) - OUT1RMIX Input 1 Source
+ */
+#define WM2200_OUT1RMIX_SRC1_MASK 0x007F /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_SHIFT 0 /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_WIDTH 7 /* OUT1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1545 (0x609) - OUT1RMIX Input 1 Volume
+ */
+#define WM2200_OUT1RMIX_VOL1_MASK 0x00FE /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_SHIFT 1 /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_WIDTH 7 /* OUT1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1546 (0x60A) - OUT1RMIX Input 2 Source
+ */
+#define WM2200_OUT1RMIX_SRC2_MASK 0x007F /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_SHIFT 0 /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_WIDTH 7 /* OUT1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1547 (0x60B) - OUT1RMIX Input 2 Volume
+ */
+#define WM2200_OUT1RMIX_VOL2_MASK 0x00FE /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_SHIFT 1 /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_WIDTH 7 /* OUT1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1548 (0x60C) - OUT1RMIX Input 3 Source
+ */
+#define WM2200_OUT1RMIX_SRC3_MASK 0x007F /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_SHIFT 0 /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_WIDTH 7 /* OUT1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1549 (0x60D) - OUT1RMIX Input 3 Volume
+ */
+#define WM2200_OUT1RMIX_VOL3_MASK 0x00FE /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_SHIFT 1 /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_WIDTH 7 /* OUT1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1550 (0x60E) - OUT1RMIX Input 4 Source
+ */
+#define WM2200_OUT1RMIX_SRC4_MASK 0x007F /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_SHIFT 0 /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_WIDTH 7 /* OUT1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1551 (0x60F) - OUT1RMIX Input 4 Volume
+ */
+#define WM2200_OUT1RMIX_VOL4_MASK 0x00FE /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_SHIFT 1 /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_WIDTH 7 /* OUT1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1552 (0x610) - OUT2LMIX Input 1 Source
+ */
+#define WM2200_OUT2LMIX_SRC1_MASK 0x007F /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_SHIFT 0 /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_WIDTH 7 /* OUT2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1553 (0x611) - OUT2LMIX Input 1 Volume
+ */
+#define WM2200_OUT2LMIX_VOL1_MASK 0x00FE /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_SHIFT 1 /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_WIDTH 7 /* OUT2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1554 (0x612) - OUT2LMIX Input 2 Source
+ */
+#define WM2200_OUT2LMIX_SRC2_MASK 0x007F /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_SHIFT 0 /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_WIDTH 7 /* OUT2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1555 (0x613) - OUT2LMIX Input 2 Volume
+ */
+#define WM2200_OUT2LMIX_VOL2_MASK 0x00FE /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_SHIFT 1 /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_WIDTH 7 /* OUT2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1556 (0x614) - OUT2LMIX Input 3 Source
+ */
+#define WM2200_OUT2LMIX_SRC3_MASK 0x007F /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_SHIFT 0 /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_WIDTH 7 /* OUT2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1557 (0x615) - OUT2LMIX Input 3 Volume
+ */
+#define WM2200_OUT2LMIX_VOL3_MASK 0x00FE /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_SHIFT 1 /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_WIDTH 7 /* OUT2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1558 (0x616) - OUT2LMIX Input 4 Source
+ */
+#define WM2200_OUT2LMIX_SRC4_MASK 0x007F /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_SHIFT 0 /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_WIDTH 7 /* OUT2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1559 (0x617) - OUT2LMIX Input 4 Volume
+ */
+#define WM2200_OUT2LMIX_VOL4_MASK 0x00FE /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_SHIFT 1 /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_WIDTH 7 /* OUT2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1560 (0x618) - OUT2RMIX Input 1 Source
+ */
+#define WM2200_OUT2RMIX_SRC1_MASK 0x007F /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_SHIFT 0 /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_WIDTH 7 /* OUT2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1561 (0x619) - OUT2RMIX Input 1 Volume
+ */
+#define WM2200_OUT2RMIX_VOL1_MASK 0x00FE /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_SHIFT 1 /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_WIDTH 7 /* OUT2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1562 (0x61A) - OUT2RMIX Input 2 Source
+ */
+#define WM2200_OUT2RMIX_SRC2_MASK 0x007F /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_SHIFT 0 /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_WIDTH 7 /* OUT2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1563 (0x61B) - OUT2RMIX Input 2 Volume
+ */
+#define WM2200_OUT2RMIX_VOL2_MASK 0x00FE /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_SHIFT 1 /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_WIDTH 7 /* OUT2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1564 (0x61C) - OUT2RMIX Input 3 Source
+ */
+#define WM2200_OUT2RMIX_SRC3_MASK 0x007F /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_SHIFT 0 /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_WIDTH 7 /* OUT2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1565 (0x61D) - OUT2RMIX Input 3 Volume
+ */
+#define WM2200_OUT2RMIX_VOL3_MASK 0x00FE /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_SHIFT 1 /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_WIDTH 7 /* OUT2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1566 (0x61E) - OUT2RMIX Input 4 Source
+ */
+#define WM2200_OUT2RMIX_SRC4_MASK 0x007F /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_SHIFT 0 /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_WIDTH 7 /* OUT2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1567 (0x61F) - OUT2RMIX Input 4 Volume
+ */
+#define WM2200_OUT2RMIX_VOL4_MASK 0x00FE /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_SHIFT 1 /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_WIDTH 7 /* OUT2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1568 (0x620) - AIF1TX1MIX Input 1 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC1_MASK 0x007F /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_SHIFT 0 /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_WIDTH 7 /* AIF1TX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1569 (0x621) - AIF1TX1MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL1_MASK 0x00FE /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_SHIFT 1 /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_WIDTH 7 /* AIF1TX1MIX_VOL1 - [7:1] */
+
+/*
+ * R1570 (0x622) - AIF1TX1MIX Input 2 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC2_MASK 0x007F /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_SHIFT 0 /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_WIDTH 7 /* AIF1TX1MIX_SRC2 - [6:0] */
+
+/*
+ * R1571 (0x623) - AIF1TX1MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL2_MASK 0x00FE /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_SHIFT 1 /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_WIDTH 7 /* AIF1TX1MIX_VOL2 - [7:1] */
+
+/*
+ * R1572 (0x624) - AIF1TX1MIX Input 3 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC3_MASK 0x007F /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_SHIFT 0 /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_WIDTH 7 /* AIF1TX1MIX_SRC3 - [6:0] */
+
+/*
+ * R1573 (0x625) - AIF1TX1MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL3_MASK 0x00FE /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_SHIFT 1 /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_WIDTH 7 /* AIF1TX1MIX_VOL3 - [7:1] */
+
+/*
+ * R1574 (0x626) - AIF1TX1MIX Input 4 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC4_MASK 0x007F /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_SHIFT 0 /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_WIDTH 7 /* AIF1TX1MIX_SRC4 - [6:0] */
+
+/*
+ * R1575 (0x627) - AIF1TX1MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL4_MASK 0x00FE /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_SHIFT 1 /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_WIDTH 7 /* AIF1TX1MIX_VOL4 - [7:1] */
+
+/*
+ * R1576 (0x628) - AIF1TX2MIX Input 1 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC1_MASK 0x007F /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_SHIFT 0 /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_WIDTH 7 /* AIF1TX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1577 (0x629) - AIF1TX2MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL1_MASK 0x00FE /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_SHIFT 1 /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_WIDTH 7 /* AIF1TX2MIX_VOL1 - [7:1] */
+
+/*
+ * R1578 (0x62A) - AIF1TX2MIX Input 2 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC2_MASK 0x007F /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_SHIFT 0 /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_WIDTH 7 /* AIF1TX2MIX_SRC2 - [6:0] */
+
+/*
+ * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL2_MASK 0x00FE /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_SHIFT 1 /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_WIDTH 7 /* AIF1TX2MIX_VOL2 - [7:1] */
+
+/*
+ * R1580 (0x62C) - AIF1TX2MIX Input 3 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC3_MASK 0x007F /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_SHIFT 0 /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_WIDTH 7 /* AIF1TX2MIX_SRC3 - [6:0] */
+
+/*
+ * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL3_MASK 0x00FE /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_SHIFT 1 /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_WIDTH 7 /* AIF1TX2MIX_VOL3 - [7:1] */
+
+/*
+ * R1582 (0x62E) - AIF1TX2MIX Input 4 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC4_MASK 0x007F /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_SHIFT 0 /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_WIDTH 7 /* AIF1TX2MIX_SRC4 - [6:0] */
+
+/*
+ * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL4_MASK 0x00FE /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_SHIFT 1 /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_WIDTH 7 /* AIF1TX2MIX_VOL4 - [7:1] */
+
+/*
+ * R1584 (0x630) - AIF1TX3MIX Input 1 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC1_MASK 0x007F /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_SHIFT 0 /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_WIDTH 7 /* AIF1TX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1585 (0x631) - AIF1TX3MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL1_MASK 0x00FE /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_SHIFT 1 /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_WIDTH 7 /* AIF1TX3MIX_VOL1 - [7:1] */
+
+/*
+ * R1586 (0x632) - AIF1TX3MIX Input 2 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC2_MASK 0x007F /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_SHIFT 0 /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_WIDTH 7 /* AIF1TX3MIX_SRC2 - [6:0] */
+
+/*
+ * R1587 (0x633) - AIF1TX3MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL2_MASK 0x00FE /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_SHIFT 1 /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_WIDTH 7 /* AIF1TX3MIX_VOL2 - [7:1] */
+
+/*
+ * R1588 (0x634) - AIF1TX3MIX Input 3 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC3_MASK 0x007F /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_SHIFT 0 /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_WIDTH 7 /* AIF1TX3MIX_SRC3 - [6:0] */
+
+/*
+ * R1589 (0x635) - AIF1TX3MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL3_MASK 0x00FE /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_SHIFT 1 /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_WIDTH 7 /* AIF1TX3MIX_VOL3 - [7:1] */
+
+/*
+ * R1590 (0x636) - AIF1TX3MIX Input 4 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC4_MASK 0x007F /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_SHIFT 0 /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_WIDTH 7 /* AIF1TX3MIX_SRC4 - [6:0] */
+
+/*
+ * R1591 (0x637) - AIF1TX3MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL4_MASK 0x00FE /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_SHIFT 1 /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_WIDTH 7 /* AIF1TX3MIX_VOL4 - [7:1] */
+
+/*
+ * R1592 (0x638) - AIF1TX4MIX Input 1 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC1_MASK 0x007F /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_SHIFT 0 /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_WIDTH 7 /* AIF1TX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1593 (0x639) - AIF1TX4MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL1_MASK 0x00FE /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_SHIFT 1 /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_WIDTH 7 /* AIF1TX4MIX_VOL1 - [7:1] */
+
+/*
+ * R1594 (0x63A) - AIF1TX4MIX Input 2 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC2_MASK 0x007F /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_SHIFT 0 /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_WIDTH 7 /* AIF1TX4MIX_SRC2 - [6:0] */
+
+/*
+ * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL2_MASK 0x00FE /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_SHIFT 1 /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_WIDTH 7 /* AIF1TX4MIX_VOL2 - [7:1] */
+
+/*
+ * R1596 (0x63C) - AIF1TX4MIX Input 3 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC3_MASK 0x007F /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_SHIFT 0 /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_WIDTH 7 /* AIF1TX4MIX_SRC3 - [6:0] */
+
+/*
+ * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL3_MASK 0x00FE /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_SHIFT 1 /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_WIDTH 7 /* AIF1TX4MIX_VOL3 - [7:1] */
+
+/*
+ * R1598 (0x63E) - AIF1TX4MIX Input 4 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC4_MASK 0x007F /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_SHIFT 0 /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_WIDTH 7 /* AIF1TX4MIX_SRC4 - [6:0] */
+
+/*
+ * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL4_MASK 0x00FE /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_SHIFT 1 /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_WIDTH 7 /* AIF1TX4MIX_VOL4 - [7:1] */
+
+/*
+ * R1600 (0x640) - AIF1TX5MIX Input 1 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC1_MASK 0x007F /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_SHIFT 0 /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_WIDTH 7 /* AIF1TX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1601 (0x641) - AIF1TX5MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL1_MASK 0x00FE /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_SHIFT 1 /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_WIDTH 7 /* AIF1TX5MIX_VOL1 - [7:1] */
+
+/*
+ * R1602 (0x642) - AIF1TX5MIX Input 2 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC2_MASK 0x007F /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_SHIFT 0 /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_WIDTH 7 /* AIF1TX5MIX_SRC2 - [6:0] */
+
+/*
+ * R1603 (0x643) - AIF1TX5MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL2_MASK 0x00FE /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_SHIFT 1 /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_WIDTH 7 /* AIF1TX5MIX_VOL2 - [7:1] */
+
+/*
+ * R1604 (0x644) - AIF1TX5MIX Input 3 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC3_MASK 0x007F /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_SHIFT 0 /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_WIDTH 7 /* AIF1TX5MIX_SRC3 - [6:0] */
+
+/*
+ * R1605 (0x645) - AIF1TX5MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL3_MASK 0x00FE /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_SHIFT 1 /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_WIDTH 7 /* AIF1TX5MIX_VOL3 - [7:1] */
+
+/*
+ * R1606 (0x646) - AIF1TX5MIX Input 4 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC4_MASK 0x007F /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_SHIFT 0 /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_WIDTH 7 /* AIF1TX5MIX_SRC4 - [6:0] */
+
+/*
+ * R1607 (0x647) - AIF1TX5MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL4_MASK 0x00FE /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_SHIFT 1 /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_WIDTH 7 /* AIF1TX5MIX_VOL4 - [7:1] */
+
+/*
+ * R1608 (0x648) - AIF1TX6MIX Input 1 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC1_MASK 0x007F /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_SHIFT 0 /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_WIDTH 7 /* AIF1TX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1609 (0x649) - AIF1TX6MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL1_MASK 0x00FE /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_SHIFT 1 /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_WIDTH 7 /* AIF1TX6MIX_VOL1 - [7:1] */
+
+/*
+ * R1610 (0x64A) - AIF1TX6MIX Input 2 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC2_MASK 0x007F /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_SHIFT 0 /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_WIDTH 7 /* AIF1TX6MIX_SRC2 - [6:0] */
+
+/*
+ * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL2_MASK 0x00FE /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_SHIFT 1 /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_WIDTH 7 /* AIF1TX6MIX_VOL2 - [7:1] */
+
+/*
+ * R1612 (0x64C) - AIF1TX6MIX Input 3 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC3_MASK 0x007F /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_SHIFT 0 /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_WIDTH 7 /* AIF1TX6MIX_SRC3 - [6:0] */
+
+/*
+ * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL3_MASK 0x00FE /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_SHIFT 1 /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_WIDTH 7 /* AIF1TX6MIX_VOL3 - [7:1] */
+
+/*
+ * R1614 (0x64E) - AIF1TX6MIX Input 4 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC4_MASK 0x007F /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_SHIFT 0 /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_WIDTH 7 /* AIF1TX6MIX_SRC4 - [6:0] */
+
+/*
+ * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL4_MASK 0x00FE /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_SHIFT 1 /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_WIDTH 7 /* AIF1TX6MIX_VOL4 - [7:1] */
+
+/*
+ * R1616 (0x650) - EQLMIX Input 1 Source
+ */
+#define WM2200_EQLMIX_SRC1_MASK 0x007F /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_SHIFT 0 /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_WIDTH 7 /* EQLMIX_SRC1 - [6:0] */
+
+/*
+ * R1617 (0x651) - EQLMIX Input 1 Volume
+ */
+#define WM2200_EQLMIX_VOL1_MASK 0x00FE /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_SHIFT 1 /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_WIDTH 7 /* EQLMIX_VOL1 - [7:1] */
+
+/*
+ * R1618 (0x652) - EQLMIX Input 2 Source
+ */
+#define WM2200_EQLMIX_SRC2_MASK 0x007F /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_SHIFT 0 /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_WIDTH 7 /* EQLMIX_SRC2 - [6:0] */
+
+/*
+ * R1619 (0x653) - EQLMIX Input 2 Volume
+ */
+#define WM2200_EQLMIX_VOL2_MASK 0x00FE /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_SHIFT 1 /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_WIDTH 7 /* EQLMIX_VOL2 - [7:1] */
+
+/*
+ * R1620 (0x654) - EQLMIX Input 3 Source
+ */
+#define WM2200_EQLMIX_SRC3_MASK 0x007F /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_SHIFT 0 /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_WIDTH 7 /* EQLMIX_SRC3 - [6:0] */
+
+/*
+ * R1621 (0x655) - EQLMIX Input 3 Volume
+ */
+#define WM2200_EQLMIX_VOL3_MASK 0x00FE /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_SHIFT 1 /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_WIDTH 7 /* EQLMIX_VOL3 - [7:1] */
+
+/*
+ * R1622 (0x656) - EQLMIX Input 4 Source
+ */
+#define WM2200_EQLMIX_SRC4_MASK 0x007F /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_SHIFT 0 /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_WIDTH 7 /* EQLMIX_SRC4 - [6:0] */
+
+/*
+ * R1623 (0x657) - EQLMIX Input 4 Volume
+ */
+#define WM2200_EQLMIX_VOL4_MASK 0x00FE /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_SHIFT 1 /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_WIDTH 7 /* EQLMIX_VOL4 - [7:1] */
+
+/*
+ * R1624 (0x658) - EQRMIX Input 1 Source
+ */
+#define WM2200_EQRMIX_SRC1_MASK 0x007F /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_SHIFT 0 /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_WIDTH 7 /* EQRMIX_SRC1 - [6:0] */
+
+/*
+ * R1625 (0x659) - EQRMIX Input 1 Volume
+ */
+#define WM2200_EQRMIX_VOL1_MASK 0x00FE /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_SHIFT 1 /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_WIDTH 7 /* EQRMIX_VOL1 - [7:1] */
+
+/*
+ * R1626 (0x65A) - EQRMIX Input 2 Source
+ */
+#define WM2200_EQRMIX_SRC2_MASK 0x007F /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_SHIFT 0 /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_WIDTH 7 /* EQRMIX_SRC2 - [6:0] */
+
+/*
+ * R1627 (0x65B) - EQRMIX Input 2 Volume
+ */
+#define WM2200_EQRMIX_VOL2_MASK 0x00FE /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_SHIFT 1 /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_WIDTH 7 /* EQRMIX_VOL2 - [7:1] */
+
+/*
+ * R1628 (0x65C) - EQRMIX Input 3 Source
+ */
+#define WM2200_EQRMIX_SRC3_MASK 0x007F /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_SHIFT 0 /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_WIDTH 7 /* EQRMIX_SRC3 - [6:0] */
+
+/*
+ * R1629 (0x65D) - EQRMIX Input 3 Volume
+ */
+#define WM2200_EQRMIX_VOL3_MASK 0x00FE /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_SHIFT 1 /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_WIDTH 7 /* EQRMIX_VOL3 - [7:1] */
+
+/*
+ * R1630 (0x65E) - EQRMIX Input 4 Source
+ */
+#define WM2200_EQRMIX_SRC4_MASK 0x007F /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_SHIFT 0 /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_WIDTH 7 /* EQRMIX_SRC4 - [6:0] */
+
+/*
+ * R1631 (0x65F) - EQRMIX Input 4 Volume
+ */
+#define WM2200_EQRMIX_VOL4_MASK 0x00FE /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_SHIFT 1 /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_WIDTH 7 /* EQRMIX_VOL4 - [7:1] */
+
+/*
+ * R1632 (0x660) - LHPF1MIX Input 1 Source
+ */
+#define WM2200_LHPF1MIX_SRC1_MASK 0x007F /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_SHIFT 0 /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_WIDTH 7 /* LHPF1MIX_SRC1 - [6:0] */
+
+/*
+ * R1633 (0x661) - LHPF1MIX Input 1 Volume
+ */
+#define WM2200_LHPF1MIX_VOL1_MASK 0x00FE /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_SHIFT 1 /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_WIDTH 7 /* LHPF1MIX_VOL1 - [7:1] */
+
+/*
+ * R1634 (0x662) - LHPF1MIX Input 2 Source
+ */
+#define WM2200_LHPF1MIX_SRC2_MASK 0x007F /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_SHIFT 0 /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_WIDTH 7 /* LHPF1MIX_SRC2 - [6:0] */
+
+/*
+ * R1635 (0x663) - LHPF1MIX Input 2 Volume
+ */
+#define WM2200_LHPF1MIX_VOL2_MASK 0x00FE /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_SHIFT 1 /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_WIDTH 7 /* LHPF1MIX_VOL2 - [7:1] */
+
+/*
+ * R1636 (0x664) - LHPF1MIX Input 3 Source
+ */
+#define WM2200_LHPF1MIX_SRC3_MASK 0x007F /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_SHIFT 0 /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_WIDTH 7 /* LHPF1MIX_SRC3 - [6:0] */
+
+/*
+ * R1637 (0x665) - LHPF1MIX Input 3 Volume
+ */
+#define WM2200_LHPF1MIX_VOL3_MASK 0x00FE /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_SHIFT 1 /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_WIDTH 7 /* LHPF1MIX_VOL3 - [7:1] */
+
+/*
+ * R1638 (0x666) - LHPF1MIX Input 4 Source
+ */
+#define WM2200_LHPF1MIX_SRC4_MASK 0x007F /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_SHIFT 0 /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_WIDTH 7 /* LHPF1MIX_SRC4 - [6:0] */
+
+/*
+ * R1639 (0x667) - LHPF1MIX Input 4 Volume
+ */
+#define WM2200_LHPF1MIX_VOL4_MASK 0x00FE /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_SHIFT 1 /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_WIDTH 7 /* LHPF1MIX_VOL4 - [7:1] */
+
+/*
+ * R1640 (0x668) - LHPF2MIX Input 1 Source
+ */
+#define WM2200_LHPF2MIX_SRC1_MASK 0x007F /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_SHIFT 0 /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_WIDTH 7 /* LHPF2MIX_SRC1 - [6:0] */
+
+/*
+ * R1641 (0x669) - LHPF2MIX Input 1 Volume
+ */
+#define WM2200_LHPF2MIX_VOL1_MASK 0x00FE /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_SHIFT 1 /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_WIDTH 7 /* LHPF2MIX_VOL1 - [7:1] */
+
+/*
+ * R1642 (0x66A) - LHPF2MIX Input 2 Source
+ */
+#define WM2200_LHPF2MIX_SRC2_MASK 0x007F /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_SHIFT 0 /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_WIDTH 7 /* LHPF2MIX_SRC2 - [6:0] */
+
+/*
+ * R1643 (0x66B) - LHPF2MIX Input 2 Volume
+ */
+#define WM2200_LHPF2MIX_VOL2_MASK 0x00FE /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_SHIFT 1 /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_WIDTH 7 /* LHPF2MIX_VOL2 - [7:1] */
+
+/*
+ * R1644 (0x66C) - LHPF2MIX Input 3 Source
+ */
+#define WM2200_LHPF2MIX_SRC3_MASK 0x007F /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_SHIFT 0 /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_WIDTH 7 /* LHPF2MIX_SRC3 - [6:0] */
+
+/*
+ * R1645 (0x66D) - LHPF2MIX Input 3 Volume
+ */
+#define WM2200_LHPF2MIX_VOL3_MASK 0x00FE /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_SHIFT 1 /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_WIDTH 7 /* LHPF2MIX_VOL3 - [7:1] */
+
+/*
+ * R1646 (0x66E) - LHPF2MIX Input 4 Source
+ */
+#define WM2200_LHPF2MIX_SRC4_MASK 0x007F /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_SHIFT 0 /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_WIDTH 7 /* LHPF2MIX_SRC4 - [6:0] */
+
+/*
+ * R1647 (0x66F) - LHPF2MIX Input 4 Volume
+ */
+#define WM2200_LHPF2MIX_VOL4_MASK 0x00FE /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_SHIFT 1 /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_WIDTH 7 /* LHPF2MIX_VOL4 - [7:1] */
+
+/*
+ * R1648 (0x670) - DSP1LMIX Input 1 Source
+ */
+#define WM2200_DSP1LMIX_SRC1_MASK 0x007F /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_SHIFT 0 /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_WIDTH 7 /* DSP1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1649 (0x671) - DSP1LMIX Input 1 Volume
+ */
+#define WM2200_DSP1LMIX_VOL1_MASK 0x00FE /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_SHIFT 1 /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_WIDTH 7 /* DSP1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1650 (0x672) - DSP1LMIX Input 2 Source
+ */
+#define WM2200_DSP1LMIX_SRC2_MASK 0x007F /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_SHIFT 0 /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_WIDTH 7 /* DSP1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1651 (0x673) - DSP1LMIX Input 2 Volume
+ */
+#define WM2200_DSP1LMIX_VOL2_MASK 0x00FE /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_SHIFT 1 /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_WIDTH 7 /* DSP1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1652 (0x674) - DSP1LMIX Input 3 Source
+ */
+#define WM2200_DSP1LMIX_SRC3_MASK 0x007F /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_SHIFT 0 /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_WIDTH 7 /* DSP1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1653 (0x675) - DSP1LMIX Input 3 Volume
+ */
+#define WM2200_DSP1LMIX_VOL3_MASK 0x00FE /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_SHIFT 1 /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_WIDTH 7 /* DSP1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1654 (0x676) - DSP1LMIX Input 4 Source
+ */
+#define WM2200_DSP1LMIX_SRC4_MASK 0x007F /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_SHIFT 0 /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_WIDTH 7 /* DSP1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1655 (0x677) - DSP1LMIX Input 4 Volume
+ */
+#define WM2200_DSP1LMIX_VOL4_MASK 0x00FE /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_SHIFT 1 /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_WIDTH 7 /* DSP1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1656 (0x678) - DSP1RMIX Input 1 Source
+ */
+#define WM2200_DSP1RMIX_SRC1_MASK 0x007F /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_SHIFT 0 /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_WIDTH 7 /* DSP1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1657 (0x679) - DSP1RMIX Input 1 Volume
+ */
+#define WM2200_DSP1RMIX_VOL1_MASK 0x00FE /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_SHIFT 1 /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_WIDTH 7 /* DSP1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1658 (0x67A) - DSP1RMIX Input 2 Source
+ */
+#define WM2200_DSP1RMIX_SRC2_MASK 0x007F /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_SHIFT 0 /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_WIDTH 7 /* DSP1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1659 (0x67B) - DSP1RMIX Input 2 Volume
+ */
+#define WM2200_DSP1RMIX_VOL2_MASK 0x00FE /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_SHIFT 1 /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_WIDTH 7 /* DSP1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1660 (0x67C) - DSP1RMIX Input 3 Source
+ */
+#define WM2200_DSP1RMIX_SRC3_MASK 0x007F /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_SHIFT 0 /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_WIDTH 7 /* DSP1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1661 (0x67D) - DSP1RMIX Input 3 Volume
+ */
+#define WM2200_DSP1RMIX_VOL3_MASK 0x00FE /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_SHIFT 1 /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_WIDTH 7 /* DSP1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1662 (0x67E) - DSP1RMIX Input 4 Source
+ */
+#define WM2200_DSP1RMIX_SRC4_MASK 0x007F /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_SHIFT 0 /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_WIDTH 7 /* DSP1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1663 (0x67F) - DSP1RMIX Input 4 Volume
+ */
+#define WM2200_DSP1RMIX_VOL4_MASK 0x00FE /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_SHIFT 1 /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_WIDTH 7 /* DSP1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1664 (0x680) - DSP1AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX1MIX_SRC1_MASK 0x007F /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_SHIFT 0 /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_WIDTH 7 /* DSP1AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1665 (0x681) - DSP1AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX2MIX_SRC1_MASK 0x007F /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_SHIFT 0 /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_WIDTH 7 /* DSP1AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1666 (0x682) - DSP1AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX3MIX_SRC1_MASK 0x007F /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_SHIFT 0 /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_WIDTH 7 /* DSP1AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1667 (0x683) - DSP1AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX4MIX_SRC1_MASK 0x007F /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_SHIFT 0 /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_WIDTH 7 /* DSP1AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1668 (0x684) - DSP1AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX5MIX_SRC1_MASK 0x007F /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_SHIFT 0 /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_WIDTH 7 /* DSP1AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1669 (0x685) - DSP1AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX6MIX_SRC1_MASK 0x007F /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_SHIFT 0 /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_WIDTH 7 /* DSP1AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1670 (0x686) - DSP2LMIX Input 1 Source
+ */
+#define WM2200_DSP2LMIX_SRC1_MASK 0x007F /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_SHIFT 0 /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_WIDTH 7 /* DSP2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1671 (0x687) - DSP2LMIX Input 1 Volume
+ */
+#define WM2200_DSP2LMIX_VOL1_MASK 0x00FE /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_SHIFT 1 /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_WIDTH 7 /* DSP2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1672 (0x688) - DSP2LMIX Input 2 Source
+ */
+#define WM2200_DSP2LMIX_SRC2_MASK 0x007F /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_SHIFT 0 /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_WIDTH 7 /* DSP2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1673 (0x689) - DSP2LMIX Input 2 Volume
+ */
+#define WM2200_DSP2LMIX_VOL2_MASK 0x00FE /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_SHIFT 1 /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_WIDTH 7 /* DSP2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1674 (0x68A) - DSP2LMIX Input 3 Source
+ */
+#define WM2200_DSP2LMIX_SRC3_MASK 0x007F /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_SHIFT 0 /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_WIDTH 7 /* DSP2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1675 (0x68B) - DSP2LMIX Input 3 Volume
+ */
+#define WM2200_DSP2LMIX_VOL3_MASK 0x00FE /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_SHIFT 1 /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_WIDTH 7 /* DSP2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1676 (0x68C) - DSP2LMIX Input 4 Source
+ */
+#define WM2200_DSP2LMIX_SRC4_MASK 0x007F /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_SHIFT 0 /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_WIDTH 7 /* DSP2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1677 (0x68D) - DSP2LMIX Input 4 Volume
+ */
+#define WM2200_DSP2LMIX_VOL4_MASK 0x00FE /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_SHIFT 1 /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_WIDTH 7 /* DSP2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1678 (0x68E) - DSP2RMIX Input 1 Source
+ */
+#define WM2200_DSP2RMIX_SRC1_MASK 0x007F /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_SHIFT 0 /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_WIDTH 7 /* DSP2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1679 (0x68F) - DSP2RMIX Input 1 Volume
+ */
+#define WM2200_DSP2RMIX_VOL1_MASK 0x00FE /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_SHIFT 1 /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_WIDTH 7 /* DSP2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1680 (0x690) - DSP2RMIX Input 2 Source
+ */
+#define WM2200_DSP2RMIX_SRC2_MASK 0x007F /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_SHIFT 0 /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_WIDTH 7 /* DSP2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1681 (0x691) - DSP2RMIX Input 2 Volume
+ */
+#define WM2200_DSP2RMIX_VOL2_MASK 0x00FE /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_SHIFT 1 /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_WIDTH 7 /* DSP2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1682 (0x692) - DSP2RMIX Input 3 Source
+ */
+#define WM2200_DSP2RMIX_SRC3_MASK 0x007F /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_SHIFT 0 /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_WIDTH 7 /* DSP2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1683 (0x693) - DSP2RMIX Input 3 Volume
+ */
+#define WM2200_DSP2RMIX_VOL3_MASK 0x00FE /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_SHIFT 1 /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_WIDTH 7 /* DSP2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1684 (0x694) - DSP2RMIX Input 4 Source
+ */
+#define WM2200_DSP2RMIX_SRC4_MASK 0x007F /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_SHIFT 0 /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_WIDTH 7 /* DSP2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1685 (0x695) - DSP2RMIX Input 4 Volume
+ */
+#define WM2200_DSP2RMIX_VOL4_MASK 0x00FE /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_SHIFT 1 /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_WIDTH 7 /* DSP2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1686 (0x696) - DSP2AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX1MIX_SRC1_MASK 0x007F /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_SHIFT 0 /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_WIDTH 7 /* DSP2AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1687 (0x697) - DSP2AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX2MIX_SRC1_MASK 0x007F /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_SHIFT 0 /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_WIDTH 7 /* DSP2AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1688 (0x698) - DSP2AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX3MIX_SRC1_MASK 0x007F /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_SHIFT 0 /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_WIDTH 7 /* DSP2AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1689 (0x699) - DSP2AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX4MIX_SRC1_MASK 0x007F /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_SHIFT 0 /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_WIDTH 7 /* DSP2AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX5MIX_SRC1_MASK 0x007F /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_SHIFT 0 /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_WIDTH 7 /* DSP2AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX6MIX_SRC1_MASK 0x007F /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_SHIFT 0 /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_WIDTH 7 /* DSP2AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1792 (0x700) - GPIO CTRL 1
+ */
+#define WM2200_GP1_DIR 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_MASK 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_SHIFT 15 /* GP1_DIR */
+#define WM2200_GP1_DIR_WIDTH 1 /* GP1_DIR */
+#define WM2200_GP1_PU 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_MASK 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_SHIFT 14 /* GP1_PU */
+#define WM2200_GP1_PU_WIDTH 1 /* GP1_PU */
+#define WM2200_GP1_PD 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_MASK 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_SHIFT 13 /* GP1_PD */
+#define WM2200_GP1_PD_WIDTH 1 /* GP1_PD */
+#define WM2200_GP1_POL 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_MASK 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_SHIFT 10 /* GP1_POL */
+#define WM2200_GP1_POL_WIDTH 1 /* GP1_POL */
+#define WM2200_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
+#define WM2200_GP1_DB 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_MASK 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_SHIFT 8 /* GP1_DB */
+#define WM2200_GP1_DB_WIDTH 1 /* GP1_DB */
+#define WM2200_GP1_LVL 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_MASK 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_SHIFT 6 /* GP1_LVL */
+#define WM2200_GP1_LVL_WIDTH 1 /* GP1_LVL */
+#define WM2200_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */
+
+/*
+ * R1793 (0x701) - GPIO CTRL 2
+ */
+#define WM2200_GP2_DIR 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_MASK 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_SHIFT 15 /* GP2_DIR */
+#define WM2200_GP2_DIR_WIDTH 1 /* GP2_DIR */
+#define WM2200_GP2_PU 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_MASK 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_SHIFT 14 /* GP2_PU */
+#define WM2200_GP2_PU_WIDTH 1 /* GP2_PU */
+#define WM2200_GP2_PD 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_MASK 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_SHIFT 13 /* GP2_PD */
+#define WM2200_GP2_PD_WIDTH 1 /* GP2_PD */
+#define WM2200_GP2_POL 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM2200_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM2200_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
+#define WM2200_GP2_DB 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_MASK 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_SHIFT 8 /* GP2_DB */
+#define WM2200_GP2_DB_WIDTH 1 /* GP2_DB */
+#define WM2200_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM2200_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM2200_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */
+
+/*
+ * R1794 (0x702) - GPIO CTRL 3
+ */
+#define WM2200_GP3_DIR 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_MASK 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_SHIFT 15 /* GP3_DIR */
+#define WM2200_GP3_DIR_WIDTH 1 /* GP3_DIR */
+#define WM2200_GP3_PU 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_MASK 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_SHIFT 14 /* GP3_PU */
+#define WM2200_GP3_PU_WIDTH 1 /* GP3_PU */
+#define WM2200_GP3_PD 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_MASK 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_SHIFT 13 /* GP3_PD */
+#define WM2200_GP3_PD_WIDTH 1 /* GP3_PD */
+#define WM2200_GP3_POL 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM2200_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM2200_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
+#define WM2200_GP3_DB 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_MASK 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_SHIFT 8 /* GP3_DB */
+#define WM2200_GP3_DB_WIDTH 1 /* GP3_DB */
+#define WM2200_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM2200_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM2200_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */
+
+/*
+ * R1795 (0x703) - GPIO CTRL 4
+ */
+#define WM2200_GP4_DIR 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_MASK 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_SHIFT 15 /* GP4_DIR */
+#define WM2200_GP4_DIR_WIDTH 1 /* GP4_DIR */
+#define WM2200_GP4_PU 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_MASK 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_SHIFT 14 /* GP4_PU */
+#define WM2200_GP4_PU_WIDTH 1 /* GP4_PU */
+#define WM2200_GP4_PD 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_MASK 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_SHIFT 13 /* GP4_PD */
+#define WM2200_GP4_PD_WIDTH 1 /* GP4_PD */
+#define WM2200_GP4_POL 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_MASK 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_SHIFT 10 /* GP4_POL */
+#define WM2200_GP4_POL_WIDTH 1 /* GP4_POL */
+#define WM2200_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
+#define WM2200_GP4_DB 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_MASK 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_SHIFT 8 /* GP4_DB */
+#define WM2200_GP4_DB_WIDTH 1 /* GP4_DB */
+#define WM2200_GP4_LVL 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_MASK 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_SHIFT 6 /* GP4_LVL */
+#define WM2200_GP4_LVL_WIDTH 1 /* GP4_LVL */
+#define WM2200_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */
+
+/*
+ * R1799 (0x707) - ADPS1 IRQ0
+ */
+#define WM2200_DSP_IRQ1 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_MASK 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_SHIFT 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_WIDTH 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ0 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_MASK 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_SHIFT 0 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_WIDTH 1 /* DSP_IRQ0 */
+
+/*
+ * R1800 (0x708) - ADPS1 IRQ1
+ */
+#define WM2200_DSP_IRQ3 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_MASK 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_SHIFT 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_WIDTH 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ2 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_MASK 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_SHIFT 0 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_WIDTH 1 /* DSP_IRQ2 */
+
+/*
+ * R1801 (0x709) - Misc Pad Ctrl 1
+ */
+#define WM2200_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */
+#define WM2200_MCLK2_PD 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_SHIFT 13 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_WIDTH 1 /* MCLK2_PD */
+#define WM2200_MCLK1_PD 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_SHIFT 12 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM2200_DACLRCLK1_PU 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_MASK 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_SHIFT 10 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PD 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_MASK 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_SHIFT 9 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */
+#define WM2200_BCLK1_PU 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_MASK 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_SHIFT 8 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_WIDTH 1 /* BCLK1_PU */
+#define WM2200_BCLK1_PD 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_MASK 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_SHIFT 7 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_WIDTH 1 /* BCLK1_PD */
+#define WM2200_DACDAT1_PU 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_MASK 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_SHIFT 6 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PD 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_MASK 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_SHIFT 5 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */
+#define WM2200_DMICDAT3_PD 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_MASK 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_SHIFT 4 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */
+#define WM2200_DMICDAT2_PD 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_MASK 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_SHIFT 3 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM2200_DMICDAT1_PD 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_MASK 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_SHIFT 2 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+#define WM2200_RSTB_PU 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_MASK 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_SHIFT 1 /* RSTB_PU */
+#define WM2200_RSTB_PU_WIDTH 1 /* RSTB_PU */
+#define WM2200_ADDR_PD 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_MASK 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_SHIFT 0 /* ADDR_PD */
+#define WM2200_ADDR_PD_WIDTH 1 /* ADDR_PD */
+
+/*
+ * R2048 (0x800) - Interrupt Status 1
+ */
+#define WM2200_DSP_IRQ0_EINT 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_MASK 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_SHIFT 7 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_WIDTH 1 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ1_EINT 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_MASK 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_SHIFT 6 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ2_EINT 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_MASK 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_SHIFT 5 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ3_EINT 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_MASK 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_SHIFT 4 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */
+#define WM2200_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM2200_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM2200_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM2200_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM2200_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM2200_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM2200_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM2200_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R2049 (0x801) - Interrupt Status 1 Mask
+ */
+#define WM2200_IM_DSP_IRQ0_EINT 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_MASK 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_SHIFT 7 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_WIDTH 1 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_MASK 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_SHIFT 6 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_MASK 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_SHIFT 5 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_MASK 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_SHIFT 4 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM2200_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM2200_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R2050 (0x802) - Interrupt Status 2
+ */
+#define WM2200_WSEQ_BUSY_EINT 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_MASK 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_SHIFT 8 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
+#define WM2200_FLL_LOCK_EINT 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_MASK 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_SHIFT 1 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
+#define WM2200_CLKGEN_EINT 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_MASK 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_SHIFT 0 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_WIDTH 1 /* CLKGEN_EINT */
+
+/*
+ * R2051 (0x803) - Interrupt Raw Status 2
+ */
+#define WM2200_WSEQ_BUSY_STS 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_MASK 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_SHIFT 8 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_WIDTH 1 /* WSEQ_BUSY_STS */
+#define WM2200_FLL_LOCK_STS 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_MASK 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_SHIFT 1 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */
+#define WM2200_CLKGEN_STS 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_MASK 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_SHIFT 0 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_WIDTH 1 /* CLKGEN_STS */
+
+/*
+ * R2052 (0x804) - Interrupt Status 2 Mask
+ */
+#define WM2200_IM_WSEQ_BUSY_EINT 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_MASK 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT 8 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_FLL_LOCK_EINT 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_MASK 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_SHIFT 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_CLKGEN_EINT 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_MASK 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_SHIFT 0 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_WIDTH 1 /* IM_CLKGEN_EINT */
+
+/*
+ * R2056 (0x808) - Interrupt Control
+ */
+#define WM2200_IM_IRQ 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_MASK 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_SHIFT 0 /* IM_IRQ */
+#define WM2200_IM_IRQ_WIDTH 1 /* IM_IRQ */
+
+/*
+ * R2304 (0x900) - EQL_1
+ */
+#define WM2200_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_ENA 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_MASK 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_SHIFT 0 /* EQL_ENA */
+#define WM2200_EQL_ENA_WIDTH 1 /* EQL_ENA */
+
+/*
+ * R2305 (0x901) - EQL_2
+ */
+#define WM2200_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R2306 (0x902) - EQL_3
+ */
+#define WM2200_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */
+
+/*
+ * R2307 (0x903) - EQL_4
+ */
+#define WM2200_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */
+
+/*
+ * R2308 (0x904) - EQL_5
+ */
+#define WM2200_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */
+
+/*
+ * R2309 (0x905) - EQL_6
+ */
+#define WM2200_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */
+
+/*
+ * R2310 (0x906) - EQL_7
+ */
+#define WM2200_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */
+
+/*
+ * R2311 (0x907) - EQL_8
+ */
+#define WM2200_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */
+
+/*
+ * R2312 (0x908) - EQL_9
+ */
+#define WM2200_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */
+
+/*
+ * R2313 (0x909) - EQL_10
+ */
+#define WM2200_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */
+
+/*
+ * R2314 (0x90A) - EQL_11
+ */
+#define WM2200_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */
+
+/*
+ * R2315 (0x90B) - EQL_12
+ */
+#define WM2200_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */
+
+/*
+ * R2316 (0x90C) - EQL_13
+ */
+#define WM2200_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */
+
+/*
+ * R2317 (0x90D) - EQL_14
+ */
+#define WM2200_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */
+
+/*
+ * R2318 (0x90E) - EQL_15
+ */
+#define WM2200_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */
+
+/*
+ * R2319 (0x90F) - EQL_16
+ */
+#define WM2200_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */
+
+/*
+ * R2320 (0x910) - EQL_17
+ */
+#define WM2200_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */
+
+/*
+ * R2321 (0x911) - EQL_18
+ */
+#define WM2200_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */
+
+/*
+ * R2322 (0x912) - EQL_19
+ */
+#define WM2200_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */
+
+/*
+ * R2323 (0x913) - EQL_20
+ */
+#define WM2200_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */
+
+/*
+ * R2326 (0x916) - EQR_1
+ */
+#define WM2200_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_ENA 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_MASK 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_SHIFT 0 /* EQR_ENA */
+#define WM2200_EQR_ENA_WIDTH 1 /* EQR_ENA */
+
+/*
+ * R2327 (0x917) - EQR_2
+ */
+#define WM2200_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R2328 (0x918) - EQR_3
+ */
+#define WM2200_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */
+
+/*
+ * R2329 (0x919) - EQR_4
+ */
+#define WM2200_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */
+
+/*
+ * R2330 (0x91A) - EQR_5
+ */
+#define WM2200_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */
+
+/*
+ * R2331 (0x91B) - EQR_6
+ */
+#define WM2200_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */
+
+/*
+ * R2332 (0x91C) - EQR_7
+ */
+#define WM2200_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */
+
+/*
+ * R2333 (0x91D) - EQR_8
+ */
+#define WM2200_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */
+
+/*
+ * R2334 (0x91E) - EQR_9
+ */
+#define WM2200_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */
+
+/*
+ * R2335 (0x91F) - EQR_10
+ */
+#define WM2200_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */
+
+/*
+ * R2336 (0x920) - EQR_11
+ */
+#define WM2200_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */
+
+/*
+ * R2337 (0x921) - EQR_12
+ */
+#define WM2200_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */
+
+/*
+ * R2338 (0x922) - EQR_13
+ */
+#define WM2200_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */
+
+/*
+ * R2339 (0x923) - EQR_14
+ */
+#define WM2200_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */
+
+/*
+ * R2340 (0x924) - EQR_15
+ */
+#define WM2200_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */
+
+/*
+ * R2341 (0x925) - EQR_16
+ */
+#define WM2200_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */
+
+/*
+ * R2342 (0x926) - EQR_17
+ */
+#define WM2200_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */
+
+/*
+ * R2343 (0x927) - EQR_18
+ */
+#define WM2200_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */
+
+/*
+ * R2344 (0x928) - EQR_19
+ */
+#define WM2200_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */
+
+/*
+ * R2345 (0x929) - EQR_20
+ */
+#define WM2200_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */
+
+/*
+ * R2366 (0x93E) - HPLPF1_1
+ */
+#define WM2200_LHPF1_MODE 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_ENA 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */
+
+/*
+ * R2367 (0x93F) - HPLPF1_2
+ */
+#define WM2200_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R2370 (0x942) - HPLPF2_1
+ */
+#define WM2200_LHPF2_MODE 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_ENA 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */
+
+/*
+ * R2371 (0x943) - HPLPF2_2
+ */
+#define WM2200_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R2560 (0xA00) - DSP1 Control 1
+ */
+#define WM2200_DSP1_RW_SEQUENCE_ENA 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT 0 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH 1 /* DSP1_RW_SEQUENCE_ENA */
+
+/*
+ * R2562 (0xA02) - DSP1 Control 2
+ */
+#define WM2200_DSP1_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2563 (0xA03) - DSP1 Control 3
+ */
+#define WM2200_DSP1_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2564 (0xA04) - DSP1 Control 4
+ */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2566 (0xA06) - DSP1 Control 5
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2567 (0xA07) - DSP1 Control 6
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2568 (0xA08) - DSP1 Control 7
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2569 (0xA09) - DSP1 Control 8
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2570 (0xA0A) - DSP1 Control 9
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2571 (0xA0B) - DSP1 Control 10
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2572 (0xA0C) - DSP1 Control 11
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2573 (0xA0D) - DSP1 Control 12
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2575 (0xA0F) - DSP1 Control 13
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2576 (0xA10) - DSP1 Control 14
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2577 (0xA11) - DSP1 Control 15
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2578 (0xA12) - DSP1 Control 16
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2579 (0xA13) - DSP1 Control 17
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2580 (0xA14) - DSP1 Control 18
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2582 (0xA16) - DSP1 Control 19
+ */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2583 (0xA17) - DSP1 Control 20
+ */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2584 (0xA18) - DSP1 Control 21
+ */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2586 (0xA1A) - DSP1 Control 22
+ */
+#define WM2200_DSP1_DM_SIZE_MASK 0xFFFF /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_SHIFT 0 /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_WIDTH 16 /* DSP1_DM_SIZE - [15:0] */
+
+/*
+ * R2587 (0xA1B) - DSP1 Control 23
+ */
+#define WM2200_DSP1_PM_SIZE_MASK 0xFFFF /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_SHIFT 0 /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_WIDTH 16 /* DSP1_PM_SIZE - [15:0] */
+
+/*
+ * R2588 (0xA1C) - DSP1 Control 24
+ */
+#define WM2200_DSP1_ZM_SIZE_MASK 0xFFFF /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_SHIFT 0 /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_WIDTH 16 /* DSP1_ZM_SIZE - [15:0] */
+
+/*
+ * R2590 (0xA1E) - DSP1 Control 25
+ */
+#define WM2200_DSP1_PING_FULL 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_MASK 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_SHIFT 15 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_WIDTH 1 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PONG_FULL 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_MASK 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_SHIFT 14 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_WIDTH 1 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2592 (0xA20) - DSP1 Control 26
+ */
+#define WM2200_DSP1_SCRATCH_0_MASK 0xFFFF /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_SHIFT 0 /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_WIDTH 16 /* DSP1_SCRATCH_0 - [15:0] */
+
+/*
+ * R2593 (0xA21) - DSP1 Control 27
+ */
+#define WM2200_DSP1_SCRATCH_1_MASK 0xFFFF /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_SHIFT 0 /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_WIDTH 16 /* DSP1_SCRATCH_1 - [15:0] */
+
+/*
+ * R2594 (0xA22) - DSP1 Control 28
+ */
+#define WM2200_DSP1_SCRATCH_2_MASK 0xFFFF /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_SHIFT 0 /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_WIDTH 16 /* DSP1_SCRATCH_2 - [15:0] */
+
+/*
+ * R2595 (0xA23) - DSP1 Control 29
+ */
+#define WM2200_DSP1_SCRATCH_3_MASK 0xFFFF /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_SHIFT 0 /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_WIDTH 16 /* DSP1_SCRATCH_3 - [15:0] */
+
+/*
+ * R2596 (0xA24) - DSP1 Control 30
+ */
+#define WM2200_DSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_START 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_MASK 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_SHIFT 0 /* DSP1_START */
+#define WM2200_DSP1_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * R2598 (0xA26) - DSP1 Control 31
+ */
+#define WM2200_DSP1_CLK_RATE_MASK 0x0018 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_SHIFT 3 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_WIDTH 2 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_AVAIL 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_MASK 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_SHIFT 2 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_WIDTH 1 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_REQ_MASK 0x0003 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_SHIFT 0 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_WIDTH 2 /* DSP1_CLK_REQ - [1:0] */
+
+/*
+ * R2816 (0xB00) - DSP2 Control 1
+ */
+#define WM2200_DSP2_RW_SEQUENCE_ENA 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT 0 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH 1 /* DSP2_RW_SEQUENCE_ENA */
+
+/*
+ * R2818 (0xB02) - DSP2 Control 2
+ */
+#define WM2200_DSP2_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2819 (0xB03) - DSP2 Control 3
+ */
+#define WM2200_DSP2_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2820 (0xB04) - DSP2 Control 4
+ */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2822 (0xB06) - DSP2 Control 5
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2823 (0xB07) - DSP2 Control 6
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2824 (0xB08) - DSP2 Control 7
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2825 (0xB09) - DSP2 Control 8
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2826 (0xB0A) - DSP2 Control 9
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2827 (0xB0B) - DSP2 Control 10
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2828 (0xB0C) - DSP2 Control 11
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2829 (0xB0D) - DSP2 Control 12
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2831 (0xB0F) - DSP2 Control 13
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2832 (0xB10) - DSP2 Control 14
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2833 (0xB11) - DSP2 Control 15
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2834 (0xB12) - DSP2 Control 16
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2835 (0xB13) - DSP2 Control 17
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2836 (0xB14) - DSP2 Control 18
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2838 (0xB16) - DSP2 Control 19
+ */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2839 (0xB17) - DSP2 Control 20
+ */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2840 (0xB18) - DSP2 Control 21
+ */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2842 (0xB1A) - DSP2 Control 22
+ */
+#define WM2200_DSP2_DM_SIZE_MASK 0xFFFF /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_SHIFT 0 /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_WIDTH 16 /* DSP2_DM_SIZE - [15:0] */
+
+/*
+ * R2843 (0xB1B) - DSP2 Control 23
+ */
+#define WM2200_DSP2_PM_SIZE_MASK 0xFFFF /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_SHIFT 0 /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_WIDTH 16 /* DSP2_PM_SIZE - [15:0] */
+
+/*
+ * R2844 (0xB1C) - DSP2 Control 24
+ */
+#define WM2200_DSP2_ZM_SIZE_MASK 0xFFFF /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_SHIFT 0 /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_WIDTH 16 /* DSP2_ZM_SIZE - [15:0] */
+
+/*
+ * R2846 (0xB1E) - DSP2 Control 25
+ */
+#define WM2200_DSP2_PING_FULL 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_MASK 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_SHIFT 15 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_WIDTH 1 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PONG_FULL 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_MASK 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_SHIFT 14 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_WIDTH 1 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2848 (0xB20) - DSP2 Control 26
+ */
+#define WM2200_DSP2_SCRATCH_0_MASK 0xFFFF /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_SHIFT 0 /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_WIDTH 16 /* DSP2_SCRATCH_0 - [15:0] */
+
+/*
+ * R2849 (0xB21) - DSP2 Control 27
+ */
+#define WM2200_DSP2_SCRATCH_1_MASK 0xFFFF /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_SHIFT 0 /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_WIDTH 16 /* DSP2_SCRATCH_1 - [15:0] */
+
+/*
+ * R2850 (0xB22) - DSP2 Control 28
+ */
+#define WM2200_DSP2_SCRATCH_2_MASK 0xFFFF /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_SHIFT 0 /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_WIDTH 16 /* DSP2_SCRATCH_2 - [15:0] */
+
+/*
+ * R2851 (0xB23) - DSP2 Control 29
+ */
+#define WM2200_DSP2_SCRATCH_3_MASK 0xFFFF /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_SHIFT 0 /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_WIDTH 16 /* DSP2_SCRATCH_3 - [15:0] */
+
+/*
+ * R2852 (0xB24) - DSP2 Control 30
+ */
+#define WM2200_DSP2_DBG_CLK_ENA 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_MASK 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_SHIFT 3 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_WIDTH 1 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_SYS_ENA 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_MASK 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_SHIFT 2 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_WIDTH 1 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_CORE_ENA 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_MASK 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_SHIFT 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_WIDTH 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_START 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_MASK 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_SHIFT 0 /* DSP2_START */
+#define WM2200_DSP2_START_WIDTH 1 /* DSP2_START */
+
+/*
+ * R2854 (0xB26) - DSP2 Control 31
+ */
+#define WM2200_DSP2_CLK_RATE_MASK 0x0018 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_SHIFT 3 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_WIDTH 2 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_AVAIL 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_MASK 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_SHIFT 2 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_WIDTH 1 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_REQ_MASK 0x0003 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_SHIFT 0 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_WIDTH 2 /* DSP2_CLK_REQ - [1:0] */
+
+#endif
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 66f0611e68b6..b9c185ce64e4 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -18,6 +18,7 @@
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/fixed.h>
#include <linux/slab.h>
@@ -50,13 +51,11 @@ struct wm5100_fll {
/* codec private data */
struct wm5100_priv {
+ struct device *dev;
struct regmap *regmap;
struct snd_soc_codec *codec;
struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
- struct regulator *cpvdd;
- struct regulator *dbvdd2;
- struct regulator *dbvdd3;
int rev;
@@ -73,6 +72,7 @@ struct wm5100_priv {
bool jack_detecting;
bool jack_mic;
int jack_mode;
+ int jack_flips;
struct wm5100_fll fll[2];
@@ -709,6 +709,8 @@ WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5,
+ WM5100_DRCL_ENA | WM5100_DRCR_ENA),
WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
@@ -776,127 +778,48 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
return 0;
}
-static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(wm5100->cpvdd);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
- ret);
- return ret;
- }
- return ret;
-
- case SND_SOC_DAPM_POST_PMD:
- ret = regulator_disable_deferred(wm5100->cpvdd, 20);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
- ret);
- return ret;
- }
- return ret;
-
- default:
- BUG();
- return 0;
- }
-}
-
-static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- struct regulator *regulator;
- int ret;
-
- switch (w->shift) {
- case 2:
- regulator = wm5100->dbvdd2;
- break;
- case 3:
- regulator = wm5100->dbvdd3;
- break;
- default:
- BUG();
- return 0;
- }
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(regulator);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
- w->shift, ret);
- return ret;
- }
- return ret;
-
- case SND_SOC_DAPM_POST_PMD:
- ret = regulator_disable(regulator);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
- w->shift, ret);
- return ret;
- }
- return ret;
-
- default:
- BUG();
- return 0;
- }
-}
-
-static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
{
if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
- dev_crit(codec->dev, "Speaker shutdown warning\n");
+ dev_crit(wm5100->dev, "Speaker shutdown warning\n");
if (val & WM5100_SPK_SHUTDOWN_EINT)
- dev_crit(codec->dev, "Speaker shutdown\n");
+ dev_crit(wm5100->dev, "Speaker shutdown\n");
if (val & WM5100_CLKGEN_ERR_EINT)
- dev_crit(codec->dev, "SYSCLK underclocked\n");
+ dev_crit(wm5100->dev, "SYSCLK underclocked\n");
if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
- dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+ dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
}
-static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
{
if (val & WM5100_AIF3_ERR_EINT)
- dev_err(codec->dev, "AIF3 configuration error\n");
+ dev_err(wm5100->dev, "AIF3 configuration error\n");
if (val & WM5100_AIF2_ERR_EINT)
- dev_err(codec->dev, "AIF2 configuration error\n");
+ dev_err(wm5100->dev, "AIF2 configuration error\n");
if (val & WM5100_AIF1_ERR_EINT)
- dev_err(codec->dev, "AIF1 configuration error\n");
+ dev_err(wm5100->dev, "AIF1 configuration error\n");
if (val & WM5100_CTRLIF_ERR_EINT)
- dev_err(codec->dev, "Control interface error\n");
+ dev_err(wm5100->dev, "Control interface error\n");
if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ISRC2 underclocked\n");
+ dev_err(wm5100->dev, "ISRC2 underclocked\n");
if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ISRC1 underclocked\n");
+ dev_err(wm5100->dev, "ISRC1 underclocked\n");
if (val & WM5100_FX_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "FX underclocked\n");
+ dev_err(wm5100->dev, "FX underclocked\n");
if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF3 underclocked\n");
+ dev_err(wm5100->dev, "AIF3 underclocked\n");
if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF2 underclocked\n");
+ dev_err(wm5100->dev, "AIF2 underclocked\n");
if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "AIF1 underclocked\n");
+ dev_err(wm5100->dev, "AIF1 underclocked\n");
if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ASRC underclocked\n");
+ dev_err(wm5100->dev, "ASRC underclocked\n");
if (val & WM5100_DAC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "DAC underclocked\n");
+ dev_err(wm5100->dev, "DAC underclocked\n");
if (val & WM5100_ADC_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "ADC underclocked\n");
+ dev_err(wm5100->dev, "ADC underclocked\n");
if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
- dev_err(codec->dev, "Mixer underclocked\n");
+ dev_err(wm5100->dev, "Mixer underclocked\n");
}
static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
@@ -904,16 +827,17 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
WM5100_CLKGEN_ERR_ASYNC_STS;
- wm5100_log_status3(codec, ret);
+ wm5100_log_status3(wm5100, ret);
ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
- wm5100_log_status4(codec, ret);
+ wm5100_log_status4(wm5100, ret);
return 0;
}
@@ -924,18 +848,16 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+
SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
- wm5100_cp_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ NULL, 0),
SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
- WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
0, NULL, 0),
@@ -1146,6 +1068,9 @@ SND_SOC_DAPM_POST("Post", wm5100_post_ev),
};
static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+ { "CP1", NULL, "CPVDD" },
+ { "CP2 Active", NULL, "CPVDD" },
+
{ "IN1L", NULL, "SYSCLK" },
{ "IN1R", NULL, "SYSCLK" },
{ "IN2L", NULL, "SYSCLK" },
@@ -1308,10 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
{ "PWM2", NULL, "PWM2 Driver" },
};
-static struct {
- int reg;
- int val;
-} wm5100_reva_patches[] = {
+static const __devinitdata struct reg_default wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_1_10, 0 },
{ WM5100_AUDIO_IF_1_11, 1 },
{ WM5100_AUDIO_IF_1_12, 2 },
@@ -1343,79 +1265,6 @@ static struct {
{ WM5100_AUDIO_IF_3_19, 1 },
};
-static int wm5100_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level)
-{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int ret, i;
-
- switch (level) {
- case SND_SOC_BIAS_ON:
- break;
-
- case SND_SOC_BIAS_PREPARE:
- break;
-
- case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to enable supplies: %d\n",
- ret);
- return ret;
- }
-
- if (wm5100->pdata.ldo_ena) {
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
- 1);
- msleep(2);
- }
-
- regcache_cache_only(wm5100->regmap, false);
-
- switch (wm5100->rev) {
- case 0:
- regcache_cache_bypass(wm5100->regmap, true);
- snd_soc_write(codec, 0x11, 0x3);
- snd_soc_write(codec, 0x203, 0xc);
- snd_soc_write(codec, 0x206, 0);
- snd_soc_write(codec, 0x207, 0xf0);
- snd_soc_write(codec, 0x208, 0x3c);
- snd_soc_write(codec, 0x209, 0);
- snd_soc_write(codec, 0x211, 0x20d8);
- snd_soc_write(codec, 0x11, 0);
-
- for (i = 0;
- i < ARRAY_SIZE(wm5100_reva_patches);
- i++)
- snd_soc_write(codec,
- wm5100_reva_patches[i].reg,
- wm5100_reva_patches[i].val);
- regcache_cache_bypass(wm5100->regmap, false);
- break;
- default:
- break;
- }
-
- regcache_sync(wm5100->regmap);
- }
- break;
-
- case SND_SOC_BIAS_OFF:
- regcache_cache_only(wm5100->regmap, true);
- if (wm5100->pdata.ldo_ena)
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
- regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
- break;
- }
- codec->dapm.bias_level = level;
-
- return 0;
-}
-
static int wm5100_dai_to_base(struct snd_soc_dai *dai)
{
switch (dai->id) {
@@ -1943,6 +1792,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (!Fout) {
dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+ if (fll->fout)
+ pm_runtime_put(codec->dev);
fll->fout = 0;
snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
return 0;
@@ -1987,6 +1838,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
/* Clear any pending completions */
try_wait_for_completion(&fll->lock);
+ pm_runtime_get_sync(codec->dev);
+
snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
if (i2c->irq)
@@ -2021,6 +1874,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
if (i == timeout) {
dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+ pm_runtime_put(codec->dev);
return -ETIMEDOUT;
}
@@ -2123,55 +1977,73 @@ static int wm5100_dig_vu[] = {
WM5100_DAC_DIGITAL_VOLUME_6R,
};
-static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
- snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
- WM5100_ACCDET_BIAS_SRC_MASK |
- WM5100_ACCDET_SRC,
- (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
- mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
- snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
- WM5100_HPCOM_SRC,
- mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
+ WM5100_ACCDET_BIAS_SRC_MASK |
+ WM5100_ACCDET_SRC,
+ (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+ mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
+ WM5100_HPCOM_SRC,
+ mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
wm5100->jack_mode = the_mode;
- dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+ dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
wm5100->jack_mode);
}
-static void wm5100_micd_irq(struct snd_soc_codec *codec)
+static void wm5100_report_headphone(struct wm5100_priv *wm5100)
{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int val;
+ dev_dbg(wm5100->dev, "Headphone detected\n");
+ wm5100->jack_detecting = false;
+ snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADPHONE);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 7 << WM5100_ACCDET_RATE_SHIFT);
+}
- val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+static void wm5100_micd_irq(struct wm5100_priv *wm5100)
+{
+ unsigned int val;
+ int ret;
- dev_dbg(codec->dev, "Microphone event: %x\n", val);
+ ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
+ if (ret != 0) {
+ dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
+ ret);
+ return;
+ }
+
+ dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
if (!(val & WM5100_ACCDET_VALID)) {
- dev_warn(codec->dev, "Microphone detection state invalid\n");
+ dev_warn(wm5100->dev, "Microphone detection state invalid\n");
return;
}
/* No accessory, reset everything and report removal */
if (!(val & WM5100_ACCDET_STS)) {
- dev_dbg(codec->dev, "Jack removal detected\n");
+ dev_dbg(wm5100->dev, "Jack removal detected\n");
wm5100->jack_mic = false;
wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
snd_soc_jack_report(wm5100->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0);
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- WM5100_ACCDET_RATE_MASK);
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ WM5100_ACCDET_RATE_MASK);
return;
}
@@ -2181,19 +2053,20 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
*/
if (val & 0x400) {
if (wm5100->jack_detecting) {
- dev_dbg(codec->dev, "Microphone detected\n");
+ dev_dbg(wm5100->dev, "Microphone detected\n");
wm5100->jack_mic = true;
+ wm5100->jack_detecting = false;
snd_soc_jack_report(wm5100->jack,
SND_JACK_HEADSET,
SND_JACK_HEADSET | SND_JACK_BTN_0);
/* Increase poll rate to give better responsiveness
* for buttons */
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- 5 << WM5100_ACCDET_RATE_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 5 << WM5100_ACCDET_RATE_SHIFT);
} else {
- dev_dbg(codec->dev, "Mic button up\n");
+ dev_dbg(wm5100->dev, "Mic button up\n");
snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
}
@@ -2203,10 +2076,16 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
/* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of
- * plain headphones.
+ * plain headphones and give up if neither polarity looks
+ * sensible.
*/
if (wm5100->jack_detecting && (val & 0x3f8)) {
- wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+ wm5100->jack_flips++;
+
+ if (wm5100->jack_flips > 1)
+ wm5100_report_headphone(wm5100);
+ else
+ wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
return;
}
@@ -2216,20 +2095,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
*/
if (val & 0x3fc) {
if (wm5100->jack_mic) {
- dev_dbg(codec->dev, "Mic button detected\n");
+ dev_dbg(wm5100->dev, "Mic button detected\n");
snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
} else if (wm5100->jack_detecting) {
- dev_dbg(codec->dev, "Headphone detected\n");
- snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
- SND_JACK_HEADPHONE);
-
- /* Increase the detection rate a bit for
- * responsiveness.
- */
- snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- 7 << WM5100_ACCDET_RATE_SHIFT);
+ wm5100_report_headphone(wm5100);
}
}
}
@@ -2241,8 +2111,9 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
if (jack) {
wm5100->jack = jack;
wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
- wm5100_set_detect_mode(codec, 0);
+ wm5100_set_detect_mode(wm5100, 0);
/* Slowest detection rate, gives debounce for initial
* detection */
@@ -2281,52 +2152,70 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
static irqreturn_t wm5100_irq(int irq, void *data)
{
- struct snd_soc_codec *codec = data;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ struct wm5100_priv *wm5100 = data;
irqreturn_t status = IRQ_NONE;
- int irq_val;
+ unsigned int irq_val, mask_val;
+ int ret;
- irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
- if (irq_val < 0) {
- dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
- irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
+ ret);
irq_val = 0;
}
- irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
- snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
+
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
if (irq_val)
status = IRQ_HANDLED;
- wm5100_log_status3(codec, irq_val);
+ wm5100_log_status3(wm5100, irq_val);
if (irq_val & WM5100_FLL1_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL1 locked\n");
+ dev_dbg(wm5100->dev, "FLL1 locked\n");
complete(&wm5100->fll[0].lock);
}
if (irq_val & WM5100_FLL2_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL2 locked\n");
+ dev_dbg(wm5100->dev, "FLL2 locked\n");
complete(&wm5100->fll[1].lock);
}
if (irq_val & WM5100_ACCDET_EINT)
- wm5100_micd_irq(codec);
+ wm5100_micd_irq(wm5100);
- irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
- if (irq_val < 0) {
- dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
- irq_val);
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
+ ret);
irq_val = 0;
}
- irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
if (irq_val)
status = IRQ_HANDLED;
- snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
- wm5100_log_status4(codec, irq_val);
+ wm5100_log_status4(wm5100, irq_val);
return status;
}
@@ -2451,7 +2340,7 @@ static int wm5100_probe(struct snd_soc_codec *codec)
{
struct i2c_client *i2c = to_i2c_client(codec->dev);
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int ret, i, irq_flags;
+ int ret, i;
wm5100->codec = codec;
codec->control_data = wm5100->regmap;
@@ -2462,9 +2351,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
return ret;
}
- regcache_cache_only(wm5100->regmap, true);
-
-
for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
WM5100_OUT_VU);
@@ -2475,60 +2361,10 @@ static int wm5100_probe(struct snd_soc_codec *codec)
/* TODO: check if we're symmetric */
- if (i2c->irq) {
- if (wm5100->pdata.irq_flags)
- irq_flags = wm5100->pdata.irq_flags;
- else
- irq_flags = IRQF_TRIGGER_LOW;
-
- irq_flags |= IRQF_ONESHOT;
-
- if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
- ret = request_threaded_irq(i2c->irq, NULL,
- wm5100_edge_irq,
- irq_flags, "wm5100", codec);
- else
- ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
- irq_flags, "wm5100", codec);
-
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
- i2c->irq, ret);
- } else {
- /* Enable default interrupts */
- snd_soc_update_bits(codec,
- WM5100_INTERRUPT_STATUS_3_MASK,
- WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
- WM5100_IM_SPK_SHUTDOWN_EINT |
- WM5100_IM_ASRC2_LOCK_EINT |
- WM5100_IM_ASRC1_LOCK_EINT |
- WM5100_IM_FLL2_LOCK_EINT |
- WM5100_IM_FLL1_LOCK_EINT |
- WM5100_CLKGEN_ERR_EINT |
- WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
-
- snd_soc_update_bits(codec,
- WM5100_INTERRUPT_STATUS_4_MASK,
- WM5100_AIF3_ERR_EINT |
- WM5100_AIF2_ERR_EINT |
- WM5100_AIF1_ERR_EINT |
- WM5100_CTRLIF_ERR_EINT |
- WM5100_ISRC2_UNDERCLOCKED_EINT |
- WM5100_ISRC1_UNDERCLOCKED_EINT |
- WM5100_FX_UNDERCLOCKED_EINT |
- WM5100_AIF3_UNDERCLOCKED_EINT |
- WM5100_AIF2_UNDERCLOCKED_EINT |
- WM5100_AIF1_UNDERCLOCKED_EINT |
- WM5100_ASRC_UNDERCLOCKED_EINT |
- WM5100_DAC_UNDERCLOCKED_EINT |
- WM5100_ADC_UNDERCLOCKED_EINT |
- WM5100_MIXER_UNDERCLOCKED_EINT, 0);
- }
- } else {
+ if (i2c->irq)
snd_soc_dapm_new_controls(&codec->dapm,
wm5100_dapm_widgets_noirq,
ARRAY_SIZE(wm5100_dapm_widgets_noirq));
- }
if (wm5100->pdata.hp_pol) {
ret = gpio_request_one(wm5100->pdata.hp_pol,
@@ -2540,19 +2376,9 @@ static int wm5100_probe(struct snd_soc_codec *codec)
}
}
- /* We'll get woken up again when the system has something useful
- * for us to do.
- */
- if (wm5100->pdata.ldo_ena)
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
- regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
-
return 0;
err_gpio:
- if (i2c->irq)
- free_irq(i2c->irq, codec);
return ret;
}
@@ -2560,14 +2386,11 @@ err_gpio:
static int wm5100_remove(struct snd_soc_codec *codec)
{
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = to_i2c_client(codec->dev);
- wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF);
if (wm5100->pdata.hp_pol) {
gpio_free(wm5100->pdata.hp_pol);
}
- if (i2c->irq)
- free_irq(i2c->irq, codec);
+
return 0;
}
@@ -2584,7 +2407,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
.set_sysclk = wm5100_set_sysclk,
.set_pll = wm5100_set_fll,
- .set_bias_level = wm5100_set_bias_level,
.idle_bias_off = 1,
.reg_cache_size = WM5100_MAX_REGISTER,
.volatile_register = wm5100_soc_volatile,
@@ -2610,19 +2432,28 @@ static const struct regmap_config wm5100_regmap = {
.cache_type = REGCACHE_RBTREE,
};
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+ WM5100_IN1L_CONTROL,
+ WM5100_IN2L_CONTROL,
+ WM5100_IN3L_CONTROL,
+ WM5100_IN4L_CONTROL,
+};
+
static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm5100_priv *wm5100;
unsigned int reg;
- int ret, i;
+ int ret, i, irq_flags;
wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
GFP_KERNEL);
if (wm5100 == NULL)
return -ENOMEM;
+ wm5100->dev = &i2c->dev;
+
wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
if (IS_ERR(wm5100->regmap)) {
ret = PTR_ERR(wm5100->regmap);
@@ -2642,41 +2473,21 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
ret);
goto err_regmap;
}
- wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
- if (IS_ERR(wm5100->cpvdd)) {
- ret = PTR_ERR(wm5100->cpvdd);
- dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
- goto err_core;
- }
-
- wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
- if (IS_ERR(wm5100->dbvdd2)) {
- ret = PTR_ERR(wm5100->dbvdd2);
- dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
- goto err_cpvdd;
- }
-
- wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
- if (IS_ERR(wm5100->dbvdd3)) {
- ret = PTR_ERR(wm5100->dbvdd3);
- dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
- goto err_dbvdd2;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_dbvdd3;
+ goto err_regmap;
}
if (wm5100->pdata.ldo_ena) {
@@ -2702,7 +2513,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
if (ret < 0) {
- dev_err(&i2c->dev, "Failed to read ID register\n");
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
goto err_reset;
}
switch (reg) {
@@ -2731,6 +2542,22 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
goto err_reset;
}
+ switch (wm5100->rev) {
+ case 0:
+ ret = regmap_register_patch(wm5100->regmap,
+ wm5100_reva_patches,
+ ARRAY_SIZE(wm5100_reva_patches));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register patches: %d\n",
+ ret);
+ goto err_reset;
+ }
+ break;
+ default:
+ break;
+ }
+
+
wm5100_init_gpio(i2c);
for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
@@ -2742,7 +2569,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
}
for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
- regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+ regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
WM5100_IN1_MODE_MASK |
WM5100_IN1_DMIC_SUP_MASK,
(wm5100->pdata.in_mode[i] <<
@@ -2751,6 +2578,62 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
WM5100_IN1_DMIC_SUP_SHIFT));
}
+ if (i2c->irq) {
+ if (wm5100->pdata.irq_flags)
+ irq_flags = wm5100->pdata.irq_flags;
+ else
+ irq_flags = IRQF_TRIGGER_LOW;
+
+ irq_flags |= IRQF_ONESHOT;
+
+ if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+ ret = request_threaded_irq(i2c->irq, NULL,
+ wm5100_edge_irq, irq_flags,
+ "wm5100", wm5100);
+ else
+ ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+ irq_flags, "wm5100",
+ wm5100);
+
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ } else {
+ /* Enable default interrupts */
+ regmap_update_bits(wm5100->regmap,
+ WM5100_INTERRUPT_STATUS_3_MASK,
+ WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+ WM5100_IM_SPK_SHUTDOWN_EINT |
+ WM5100_IM_ASRC2_LOCK_EINT |
+ WM5100_IM_ASRC1_LOCK_EINT |
+ WM5100_IM_FLL2_LOCK_EINT |
+ WM5100_IM_FLL1_LOCK_EINT |
+ WM5100_CLKGEN_ERR_EINT |
+ WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+ regmap_update_bits(wm5100->regmap,
+ WM5100_INTERRUPT_STATUS_4_MASK,
+ WM5100_AIF3_ERR_EINT |
+ WM5100_AIF2_ERR_EINT |
+ WM5100_AIF1_ERR_EINT |
+ WM5100_CTRLIF_ERR_EINT |
+ WM5100_ISRC2_UNDERCLOCKED_EINT |
+ WM5100_ISRC1_UNDERCLOCKED_EINT |
+ WM5100_FX_UNDERCLOCKED_EINT |
+ WM5100_AIF3_UNDERCLOCKED_EINT |
+ WM5100_AIF2_UNDERCLOCKED_EINT |
+ WM5100_AIF1_UNDERCLOCKED_EINT |
+ WM5100_ASRC_UNDERCLOCKED_EINT |
+ WM5100_DAC_UNDERCLOCKED_EINT |
+ WM5100_ADC_UNDERCLOCKED_EINT |
+ WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+ }
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm5100, wm5100_dai,
ARRAY_SIZE(wm5100_dai));
@@ -2762,9 +2645,11 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
return ret;
err_reset:
+ if (i2c->irq)
+ free_irq(i2c->irq, wm5100);
wm5100_free_gpio(i2c);
if (wm5100->pdata.reset) {
- gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+ gpio_set_value_cansleep(wm5100->pdata.reset, 0);
gpio_free(wm5100->pdata.reset);
}
err_ldo:
@@ -2775,45 +2660,78 @@ err_ldo:
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
-err_dbvdd3:
- regulator_put(wm5100->dbvdd3);
-err_dbvdd2:
- regulator_put(wm5100->dbvdd2);
-err_cpvdd:
- regulator_put(wm5100->cpvdd);
-err_core:
- regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
err_regmap:
regmap_exit(wm5100->regmap);
err:
return ret;
}
-static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
{
- struct wm5100_priv *wm5100 = i2c_get_clientdata(client);
+ struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
- snd_soc_unregister_codec(&client->dev);
- wm5100_free_gpio(client);
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm5100);
+ wm5100_free_gpio(i2c);
if (wm5100->pdata.reset) {
- gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+ gpio_set_value_cansleep(wm5100->pdata.reset, 0);
gpio_free(wm5100->pdata.reset);
}
if (wm5100->pdata.ldo_ena) {
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpio_free(wm5100->pdata.ldo_ena);
}
- regulator_put(wm5100->dbvdd3);
- regulator_put(wm5100->dbvdd2);
- regulator_put(wm5100->cpvdd);
- regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
regmap_exit(wm5100->regmap);
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int wm5100_runtime_suspend(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm5100->regmap, true);
+ regcache_mark_dirty(wm5100->regmap);
+ if (wm5100->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+
+ return 0;
+}
+
+static int wm5100_runtime_resume(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm5100->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm5100->regmap, false);
+ regcache_sync(wm5100->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm5100_pm = {
+ SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
+ NULL)
+};
+
static const struct i2c_device_id wm5100_i2c_id[] = {
{ "wm5100", 0 },
{ }
@@ -2824,6 +2742,7 @@ static struct i2c_driver wm5100_i2c_driver = {
.driver = {
.name = "wm5100",
.owner = THIS_MODULE,
+ .pm = &wm5100_pm,
},
.probe = wm5100_i2c_probe,
.remove = __devexit_p(wm5100_i2c_remove),
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 8821af70e660..a32caa72bd7d 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/of_device.h>
@@ -41,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
/* codec private data */
struct wm8731_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
unsigned int sysclk;
int sysclk_type;
@@ -52,16 +53,30 @@ struct wm8731_priv {
/*
* wm8731 register cache
- * We can't read the WM8731 register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
*/
-static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
- 0x0097, 0x0097, 0x0079, 0x0079,
- 0x000a, 0x0008, 0x009f, 0x000a,
- 0x0000, 0x0000
+static const struct reg_default wm8731_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x000a },
+ { 5, 0x0008 },
+ { 6, 0x009f },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
};
+static bool wm8731_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8731_RESET;
+}
+
+static bool wm8731_writeable(struct device *dev, unsigned int reg)
+{
+ return reg <= WM8731_RESET;
+}
+
#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
static const char *wm8731_input_select[] = {"Line In", "Mic"};
@@ -441,7 +456,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
if (ret != 0)
return ret;
- snd_soc_cache_sync(codec);
+ regcache_sync(wm8731->regmap);
}
/* Clear PWROFF, gate CLKOUT, everything else as-is */
@@ -452,7 +467,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8731_PWR, 0xffff);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
- codec->cache_sync = 1;
+ regcache_mark_dirty(wm8731->regmap);
break;
}
codec->dapm.bias_level = level;
@@ -513,7 +528,8 @@ static int wm8731_probe(struct snd_soc_codec *codec)
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
int ret = 0, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
+ codec->control_data = wm8731->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -585,9 +601,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
.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,
.dapm_widgets = wm8731_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
.dapm_routes = wm8731_intercon,
@@ -603,6 +616,19 @@ static const struct of_device_id wm8731_of_match[] = {
MODULE_DEVICE_TABLE(of, wm8731_of_match);
+static const struct regmap_config wm8731_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8731_RESET,
+ .volatile_reg = wm8731_volatile,
+ .writeable_reg = wm8731_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8731_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults),
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8731_spi_probe(struct spi_device *spi)
{
@@ -613,20 +639,39 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
if (wm8731 == NULL)
return -ENOMEM;
- wm8731->control_type = SND_SOC_SPI;
+ wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap);
+ if (IS_ERR(wm8731->regmap)) {
+ ret = PTR_ERR(wm8731->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
spi_set_drvdata(spi, wm8731);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
- if (ret < 0)
- kfree(wm8731);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8731->regmap);
+err:
+ kfree(wm8731);
return ret;
}
static int __devexit wm8731_spi_remove(struct spi_device *spi)
{
+ struct wm8731_priv *wm8731 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8731->regmap);
+ kfree(wm8731);
return 0;
}
@@ -652,20 +697,38 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
if (wm8731 == NULL)
return -ENOMEM;
+ wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap);
+ if (IS_ERR(wm8731->regmap)) {
+ ret = PTR_ERR(wm8731->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
i2c_set_clientdata(i2c, wm8731);
- wm8731->control_type = SND_SOC_I2C;
- ret = snd_soc_register_codec(&i2c->dev,
+ ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
- if (ret < 0)
- kfree(wm8731);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8731->regmap);
+err:
+ kfree(wm8731);
return ret;
}
static __devexit int wm8731_i2c_remove(struct i2c_client *client)
{
+ struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8731->regmap);
+ kfree(wm8731);
return 0;
}
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index ff95e62c56b9..4fe9d191e277 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -599,7 +599,7 @@ static int wm8737_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
- snd_soc_add_controls(codec, wm8737_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8737_snd_controls,
ARRAY_SIZE(wm8737_snd_controls));
wm8737_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index b114c19f530a..e27e7b62b365 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -39,6 +39,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -65,28 +66,86 @@ static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
* We can't read the WM8753 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8753_reg[] = {
- 0x0000, 0x0008, 0x0000, 0x000a,
- 0x000a, 0x0033, 0x0000, 0x0007,
- 0x00ff, 0x00ff, 0x000f, 0x000f,
- 0x007b, 0x0000, 0x0032, 0x0000,
- 0x00c3, 0x00c3, 0x00c0, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0055, 0x0005, 0x0050, 0x0055,
- 0x0050, 0x0055, 0x0050, 0x0055,
- 0x0079, 0x0079, 0x0079, 0x0079,
- 0x0079, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0097, 0x0097, 0x0000,
- 0x0004, 0x0000, 0x0083, 0x0024,
- 0x01ba, 0x0000, 0x0083, 0x0024,
- 0x01ba, 0x0000, 0x0000, 0x0000
+static const struct reg_default wm8753_reg_defaults[] = {
+ { 0x00, 0x0000 },
+ { 0x01, 0x0008 },
+ { 0x02, 0x0000 },
+ { 0x03, 0x000a },
+ { 0x04, 0x000a },
+ { 0x05, 0x0033 },
+ { 0x06, 0x0000 },
+ { 0x07, 0x0007 },
+ { 0x08, 0x00ff },
+ { 0x09, 0x00ff },
+ { 0x0a, 0x000f },
+ { 0x0b, 0x000f },
+ { 0x0c, 0x007b },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0032 },
+ { 0x0f, 0x0000 },
+ { 0x10, 0x00c3 },
+ { 0x11, 0x00c3 },
+ { 0x12, 0x00c0 },
+ { 0x13, 0x0000 },
+ { 0x14, 0x0000 },
+ { 0x15, 0x0000 },
+ { 0x16, 0x0000 },
+ { 0x17, 0x0000 },
+ { 0x18, 0x0000 },
+ { 0x19, 0x0000 },
+ { 0x1a, 0x0000 },
+ { 0x1b, 0x0000 },
+ { 0x1c, 0x0000 },
+ { 0x1d, 0x0000 },
+ { 0x1e, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x20, 0x0055 },
+ { 0x21, 0x0005 },
+ { 0x22, 0x0050 },
+ { 0x23, 0x0055 },
+ { 0x24, 0x0050 },
+ { 0x25, 0x0055 },
+ { 0x26, 0x0050 },
+ { 0x27, 0x0055 },
+ { 0x28, 0x0079 },
+ { 0x29, 0x0079 },
+ { 0x2a, 0x0079 },
+ { 0x2b, 0x0079 },
+ { 0x2c, 0x0079 },
+ { 0x2d, 0x0000 },
+ { 0x2e, 0x0000 },
+ { 0x2f, 0x0000 },
+ { 0x30, 0x0000 },
+ { 0x31, 0x0097 },
+ { 0x32, 0x0097 },
+ { 0x33, 0x0000 },
+ { 0x34, 0x0004 },
+ { 0x35, 0x0000 },
+ { 0x36, 0x0083 },
+ { 0x37, 0x0024 },
+ { 0x38, 0x01ba },
+ { 0x39, 0x0000 },
+ { 0x3a, 0x0083 },
+ { 0x3b, 0x0024 },
+ { 0x3c, 0x01ba },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x0000 },
+ { 0x3f, 0x0000 },
};
+static bool wm8753_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8753_RESET;
+}
+
+static bool wm8753_writeable(struct device *dev, unsigned int reg)
+{
+ return reg <= WM8753_ADCTL2;
+}
+
/* codec private data */
struct wm8753_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
unsigned int sysclk;
unsigned int pcmclk;
@@ -1383,25 +1442,15 @@ static void wm8753_work(struct work_struct *work)
static int wm8753_suspend(struct snd_soc_codec *codec)
{
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ codec->cache_sync = 1;
return 0;
}
static int wm8753_resume(struct snd_soc_codec *codec)
{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- /* Sync reg_cache with the hardware */
- for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
- if (i == WM8753_RESET)
- continue;
-
- /* No point in writing hardware default values back */
- if (reg_cache[i] == wm8753_reg[i])
- continue;
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
- snd_soc_write(codec, i, reg_cache[i]);
- }
+ regcache_sync(wm8753->regmap);
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1423,7 +1472,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+ codec->control_data = wm8753->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -1473,9 +1523,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
.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,
.controls = wm8753_snd_controls,
.num_controls = ARRAY_SIZE(wm8753_snd_controls),
@@ -1491,30 +1538,62 @@ static const struct of_device_id wm8753_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8753_of_match);
+static const struct regmap_config wm8753_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8753_ADCTL2,
+ .writeable_reg = wm8753_writeable,
+ .volatile_reg = wm8753_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8753_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8753_spi_probe(struct spi_device *spi)
{
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
- wm8753->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, wm8753);
- ret = snd_soc_register_codec(&spi->dev,
- &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret < 0)
- kfree(wm8753);
+ wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+ if (IS_ERR(wm8753->regmap)) {
+ ret = PTR_ERR(wm8753->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
+ wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8753->regmap);
+err:
return ret;
}
static int __devexit wm8753_spi_remove(struct spi_device *spi)
{
+ struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8753->regmap);
+ kfree(wm8753);
return 0;
}
@@ -1536,24 +1615,42 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8753);
- wm8753->control_type = SND_SOC_I2C;
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret < 0)
- kfree(wm8753);
+ wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+ if (IS_ERR(wm8753->regmap)) {
+ ret = PTR_ERR(wm8753->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
+ wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8753->regmap);
+err:
return ret;
}
static __devexit int wm8753_i2c_remove(struct i2c_client *client)
{
+ struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8753->regmap);
return 0;
}
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 19374a9e5ba6..a5127b4ff9e1 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -580,8 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- codec->dapm.idle_bias_off = 1;
-
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -643,7 +641,7 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
- snd_soc_add_controls(codec, wm8770_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8770_snd_controls,
ARRAY_SIZE(wm8770_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
ARRAY_SIZE(wm8770_dapm_widgets));
@@ -679,6 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
.suspend = wm8770_suspend,
.resume = wm8770_resume,
.set_bias_level = wm8770_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
.reg_word_size = sizeof (u16),
.reg_cache_default = wm8770_reg_defs
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 33e97d1d8f46..a19db5a0a17a 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -30,6 +30,11 @@
#include "wm8776.h"
+enum wm8776_chip_type {
+ WM8775 = 1,
+ WM8776,
+};
+
/* codec private data */
struct wm8776_priv {
enum snd_soc_control_type control_type;
@@ -512,7 +517,8 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id wm8776_i2c_id[] = {
- { "wm8776", 0 },
+ { "wm8775", WM8775 },
+ { "wm8776", WM8776 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index d54a3ca5e19e..6bd1b767b138 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -35,45 +36,33 @@ static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
"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 */
+static const struct reg_default wm8804_reg_defaults[] = {
+ { 3, 0x21 }, /* R3 - PLL1 */
+ { 4, 0xFD }, /* R4 - PLL2 */
+ { 5, 0x36 }, /* R5 - PLL3 */
+ { 6, 0x07 }, /* R6 - PLL4 */
+ { 7, 0x16 }, /* R7 - PLL5 */
+ { 8, 0x18 }, /* R8 - PLL6 */
+ { 9, 0xFF }, /* R9 - SPDMODE */
+ { 10, 0x00 }, /* R10 - INTMASK */
+ { 18, 0x00 }, /* R18 - SPDTX1 */
+ { 19, 0x00 }, /* R19 - SPDTX2 */
+ { 20, 0x00 }, /* R20 - SPDTX3 */
+ { 21, 0x71 }, /* R21 - SPDTX4 */
+ { 22, 0x0B }, /* R22 - SPDTX5 */
+ { 23, 0x70 }, /* R23 - GPO0 */
+ { 24, 0x57 }, /* R24 - GPO1 */
+ { 26, 0x42 }, /* R26 - GPO2 */
+ { 27, 0x06 }, /* R27 - AIFTX */
+ { 28, 0x06 }, /* R28 - AIFRX */
+ { 29, 0x80 }, /* R29 - SPDRX1 */
+ { 30, 0x07 }, /* R30 - PWRDN */
};
struct wm8804_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
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,
@@ -94,7 +83,7 @@ static int wm8804_regulator_event_##n(struct notifier_block *nb, \
struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8804->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8804->regmap); \
} \
return 0; \
}
@@ -176,7 +165,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8804_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8804_RST_DEVID1:
@@ -189,12 +178,10 @@ static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
case WM8804_RXCHAN3:
case WM8804_RXCHAN4:
case WM8804_RXCHAN5:
- return 1;
+ return true;
default:
- break;
+ return false;
}
-
- return 0;
}
static int wm8804_reset(struct snd_soc_codec *codec)
@@ -482,24 +469,6 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
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)
{
@@ -524,7 +493,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
ret);
return ret;
}
- wm8804_sync_cache(codec);
+ regcache_sync(wm8804->regmap);
}
/* power down the OSC and the PLL */
snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
@@ -579,11 +548,10 @@ static int wm8804_probe(struct snd_soc_codec *codec)
int i, id1, id2, ret;
wm8804 = snd_soc_codec_get_drvdata(codec);
- wm8804->codec = codec;
- codec->dapm.idle_bias_off = 1;
+ codec->control_data = wm8804->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
return ret;
@@ -636,8 +604,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
id2 = (id2 << 8) | id1;
- if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
- | wm8804_reg_defs[WM8804_RST_DEVID1])) {
+ if (id2 != 0x8805) {
dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
ret = -EINVAL;
goto err_reg_enable;
@@ -710,10 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.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,
+ .idle_bias_off = true,
.controls = wm8804_snd_controls,
.num_controls = ARRAY_SIZE(wm8804_snd_controls),
@@ -725,30 +689,47 @@ static const struct of_device_id wm8804_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8804_of_match);
+static struct regmap_config wm8804_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = WM8804_MAX_REGISTER,
+ .volatile_reg = wm8804_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8804_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
+};
+
#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);
+ wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL);
if (!wm8804)
return -ENOMEM;
- wm8804->control_type = SND_SOC_SPI;
+ wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+ if (IS_ERR(wm8804->regmap)) {
+ ret = PTR_ERR(wm8804->regmap);
+ return ret;
+ }
+
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)
{
+ struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8804->regmap);
return 0;
}
@@ -770,24 +751,37 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
struct wm8804_priv *wm8804;
int ret;
- wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+ wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL);
if (!wm8804)
return -ENOMEM;
- wm8804->control_type = SND_SOC_I2C;
+ wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+ if (IS_ERR(wm8804->regmap)) {
+ ret = PTR_ERR(wm8804->regmap);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8804);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8804, &wm8804_dai, 1);
- if (ret < 0)
- kfree(wm8804);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8804->regmap);
return ret;
}
-static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm8804->regmap);
+
return 0;
}
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f31c754c8865..65d525d74c54 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -47,6 +48,7 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
/* codec private data */
struct wm8904_priv {
+ struct regmap *regmap;
enum wm8904_type devtype;
@@ -86,517 +88,230 @@ struct wm8904_priv {
int dcs_state[WM8904_NUM_DCS_CHANNELS];
};
-static const u16 wm8904_reg[WM8904_MAX_REGISTER + 1] = {
- 0x8904, /* R0 - SW Reset and ID */
- 0x0000, /* R1 - Revision */
- 0x0000, /* R2 */
- 0x0000, /* R3 */
- 0x0018, /* R4 - Bias Control 0 */
- 0x0000, /* R5 - VMID Control 0 */
- 0x0000, /* R6 - Mic Bias Control 0 */
- 0x0000, /* R7 - Mic Bias Control 1 */
- 0x0001, /* R8 - Analogue DAC 0 */
- 0x9696, /* R9 - mic Filter Control */
- 0x0001, /* R10 - Analogue ADC 0 */
- 0x0000, /* R11 */
- 0x0000, /* R12 - Power Management 0 */
- 0x0000, /* R13 */
- 0x0000, /* R14 - Power Management 2 */
- 0x0000, /* R15 - Power Management 3 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 - Power Management 6 */
- 0x0000, /* R19 */
- 0x945E, /* R20 - Clock Rates 0 */
- 0x0C05, /* R21 - Clock Rates 1 */
- 0x0006, /* R22 - Clock Rates 2 */
- 0x0000, /* R23 */
- 0x0050, /* R24 - Audio Interface 0 */
- 0x000A, /* R25 - Audio Interface 1 */
- 0x00E4, /* R26 - Audio Interface 2 */
- 0x0040, /* R27 - Audio Interface 3 */
- 0x0000, /* R28 */
- 0x0000, /* R29 */
- 0x00C0, /* R30 - DAC Digital Volume Left */
- 0x00C0, /* R31 - DAC Digital Volume Right */
- 0x0000, /* R32 - DAC Digital 0 */
- 0x0008, /* R33 - DAC Digital 1 */
- 0x0000, /* R34 */
- 0x0000, /* R35 */
- 0x00C0, /* R36 - ADC Digital Volume Left */
- 0x00C0, /* R37 - ADC Digital Volume Right */
- 0x0010, /* R38 - ADC Digital 0 */
- 0x0000, /* R39 - Digital Microphone 0 */
- 0x01AF, /* R40 - DRC 0 */
- 0x3248, /* R41 - DRC 1 */
- 0x0000, /* R42 - DRC 2 */
- 0x0000, /* R43 - DRC 3 */
- 0x0085, /* R44 - Analogue Left Input 0 */
- 0x0085, /* R45 - Analogue Right Input 0 */
- 0x0044, /* R46 - Analogue Left Input 1 */
- 0x0044, /* R47 - Analogue Right Input 1 */
- 0x0000, /* R48 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x002D, /* R57 - Analogue OUT1 Left */
- 0x002D, /* R58 - Analogue OUT1 Right */
- 0x0039, /* R59 - Analogue OUT2 Left */
- 0x0039, /* R60 - Analogue OUT2 Right */
- 0x0000, /* R61 - Analogue OUT12 ZC */
- 0x0000, /* R62 */
- 0x0000, /* R63 */
- 0x0000, /* R64 */
- 0x0000, /* R65 */
- 0x0000, /* R66 */
- 0x0000, /* R67 - DC Servo 0 */
- 0x0000, /* R68 - DC Servo 1 */
- 0xAAAA, /* R69 - DC Servo 2 */
- 0x0000, /* R70 */
- 0xAAAA, /* R71 - DC Servo 4 */
- 0xAAAA, /* R72 - DC Servo 5 */
- 0x0000, /* R73 - DC Servo 6 */
- 0x0000, /* R74 - DC Servo 7 */
- 0x0000, /* R75 - DC Servo 8 */
- 0x0000, /* R76 - DC Servo 9 */
- 0x0000, /* R77 - DC Servo Readback 0 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 */
- 0x0000, /* R85 */
- 0x0000, /* R86 */
- 0x0000, /* R87 */
- 0x0000, /* R88 */
- 0x0000, /* R89 */
- 0x0000, /* R90 - Analogue HP 0 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 - Analogue Lineout 0 */
- 0x0000, /* R95 */
- 0x0000, /* R96 */
- 0x0000, /* R97 */
- 0x0000, /* R98 - Charge Pump 0 */
- 0x0000, /* R99 */
- 0x0000, /* R100 */
- 0x0000, /* R101 */
- 0x0000, /* R102 */
- 0x0000, /* R103 */
- 0x0004, /* R104 - Class W 0 */
- 0x0000, /* R105 */
- 0x0000, /* R106 */
- 0x0000, /* R107 */
- 0x0000, /* R108 - Write Sequencer 0 */
- 0x0000, /* R109 - Write Sequencer 1 */
- 0x0000, /* R110 - Write Sequencer 2 */
- 0x0000, /* R111 - Write Sequencer 3 */
- 0x0000, /* R112 - Write Sequencer 4 */
- 0x0000, /* R113 */
- 0x0000, /* R114 */
- 0x0000, /* R115 */
- 0x0000, /* R116 - FLL Control 1 */
- 0x0007, /* R117 - FLL Control 2 */
- 0x0000, /* R118 - FLL Control 3 */
- 0x2EE0, /* R119 - FLL Control 4 */
- 0x0004, /* R120 - FLL Control 5 */
- 0x0014, /* R121 - GPIO Control 1 */
- 0x0010, /* R122 - GPIO Control 2 */
- 0x0010, /* R123 - GPIO Control 3 */
- 0x0000, /* R124 - GPIO Control 4 */
- 0x0000, /* R125 */
- 0x0000, /* R126 - Digital Pulls */
- 0x0000, /* R127 - Interrupt Status */
- 0xFFFF, /* R128 - Interrupt Status Mask */
- 0x0000, /* R129 - Interrupt Polarity */
- 0x0000, /* R130 - Interrupt Debounce */
- 0x0000, /* R131 */
- 0x0000, /* R132 */
- 0x0000, /* R133 */
- 0x0000, /* R134 - EQ1 */
- 0x000C, /* R135 - EQ2 */
- 0x000C, /* R136 - EQ3 */
- 0x000C, /* R137 - EQ4 */
- 0x000C, /* R138 - EQ5 */
- 0x000C, /* R139 - EQ6 */
- 0x0FCA, /* R140 - EQ7 */
- 0x0400, /* R141 - EQ8 */
- 0x00D8, /* R142 - EQ9 */
- 0x1EB5, /* R143 - EQ10 */
- 0xF145, /* R144 - EQ11 */
- 0x0B75, /* R145 - EQ12 */
- 0x01C5, /* R146 - EQ13 */
- 0x1C58, /* R147 - EQ14 */
- 0xF373, /* R148 - EQ15 */
- 0x0A54, /* R149 - EQ16 */
- 0x0558, /* R150 - EQ17 */
- 0x168E, /* R151 - EQ18 */
- 0xF829, /* R152 - EQ19 */
- 0x07AD, /* R153 - EQ20 */
- 0x1103, /* R154 - EQ21 */
- 0x0564, /* R155 - EQ22 */
- 0x0559, /* R156 - EQ23 */
- 0x4000, /* R157 - EQ24 */
- 0x0000, /* R158 */
- 0x0000, /* R159 */
- 0x0000, /* R160 */
- 0x0000, /* R161 - Control Interface Test 1 */
- 0x0000, /* R162 */
- 0x0000, /* R163 */
- 0x0000, /* R164 */
- 0x0000, /* R165 */
- 0x0000, /* R166 */
- 0x0000, /* R167 */
- 0x0000, /* R168 */
- 0x0000, /* R169 */
- 0x0000, /* R170 */
- 0x0000, /* R171 */
- 0x0000, /* R172 */
- 0x0000, /* R173 */
- 0x0000, /* R174 */
- 0x0000, /* R175 */
- 0x0000, /* R176 */
- 0x0000, /* R177 */
- 0x0000, /* R178 */
- 0x0000, /* R179 */
- 0x0000, /* R180 */
- 0x0000, /* R181 */
- 0x0000, /* R182 */
- 0x0000, /* R183 */
- 0x0000, /* R184 */
- 0x0000, /* R185 */
- 0x0000, /* R186 */
- 0x0000, /* R187 */
- 0x0000, /* R188 */
- 0x0000, /* R189 */
- 0x0000, /* R190 */
- 0x0000, /* R191 */
- 0x0000, /* R192 */
- 0x0000, /* R193 */
- 0x0000, /* R194 */
- 0x0000, /* R195 */
- 0x0000, /* R196 */
- 0x0000, /* R197 */
- 0x0000, /* R198 */
- 0x0000, /* R199 */
- 0x0000, /* R200 */
- 0x0000, /* R201 */
- 0x0000, /* R202 */
- 0x0000, /* R203 */
- 0x0000, /* R204 - Analogue Output Bias 0 */
- 0x0000, /* R205 */
- 0x0000, /* R206 */
- 0x0000, /* R207 */
- 0x0000, /* R208 */
- 0x0000, /* R209 */
- 0x0000, /* R210 */
- 0x0000, /* R211 */
- 0x0000, /* R212 */
- 0x0000, /* R213 */
- 0x0000, /* R214 */
- 0x0000, /* R215 */
- 0x0000, /* R216 */
- 0x0000, /* R217 */
- 0x0000, /* R218 */
- 0x0000, /* R219 */
- 0x0000, /* R220 */
- 0x0000, /* R221 */
- 0x0000, /* R222 */
- 0x0000, /* R223 */
- 0x0000, /* R224 */
- 0x0000, /* R225 */
- 0x0000, /* R226 */
- 0x0000, /* R227 */
- 0x0000, /* R228 */
- 0x0000, /* R229 */
- 0x0000, /* R230 */
- 0x0000, /* R231 */
- 0x0000, /* R232 */
- 0x0000, /* R233 */
- 0x0000, /* R234 */
- 0x0000, /* R235 */
- 0x0000, /* R236 */
- 0x0000, /* R237 */
- 0x0000, /* R238 */
- 0x0000, /* R239 */
- 0x0000, /* R240 */
- 0x0000, /* R241 */
- 0x0000, /* R242 */
- 0x0000, /* R243 */
- 0x0000, /* R244 */
- 0x0000, /* R245 */
- 0x0000, /* R246 */
- 0x0000, /* R247 - FLL NCO Test 0 */
- 0x0019, /* R248 - FLL NCO Test 1 */
+static const struct reg_default wm8904_reg_defaults[] = {
+ { 4, 0x0018 }, /* R4 - Bias Control 0 */
+ { 5, 0x0000 }, /* R5 - VMID Control 0 */
+ { 6, 0x0000 }, /* R6 - Mic Bias Control 0 */
+ { 7, 0x0000 }, /* R7 - Mic Bias Control 1 */
+ { 8, 0x0001 }, /* R8 - Analogue DAC 0 */
+ { 9, 0x9696 }, /* R9 - mic Filter Control */
+ { 10, 0x0001 }, /* R10 - Analogue ADC 0 */
+ { 12, 0x0000 }, /* R12 - Power Management 0 */
+ { 14, 0x0000 }, /* R14 - Power Management 2 */
+ { 15, 0x0000 }, /* R15 - Power Management 3 */
+ { 18, 0x0000 }, /* R18 - Power Management 6 */
+ { 19, 0x945E }, /* R20 - Clock Rates 0 */
+ { 21, 0x0C05 }, /* R21 - Clock Rates 1 */
+ { 22, 0x0006 }, /* R22 - Clock Rates 2 */
+ { 24, 0x0050 }, /* R24 - Audio Interface 0 */
+ { 25, 0x000A }, /* R25 - Audio Interface 1 */
+ { 26, 0x00E4 }, /* R26 - Audio Interface 2 */
+ { 27, 0x0040 }, /* R27 - Audio Interface 3 */
+ { 30, 0x00C0 }, /* R30 - DAC Digital Volume Left */
+ { 31, 0x00C0 }, /* R31 - DAC Digital Volume Right */
+ { 32, 0x0000 }, /* R32 - DAC Digital 0 */
+ { 33, 0x0008 }, /* R33 - DAC Digital 1 */
+ { 36, 0x00C0 }, /* R36 - ADC Digital Volume Left */
+ { 37, 0x00C0 }, /* R37 - ADC Digital Volume Right */
+ { 38, 0x0010 }, /* R38 - ADC Digital 0 */
+ { 39, 0x0000 }, /* R39 - Digital Microphone 0 */
+ { 40, 0x01AF }, /* R40 - DRC 0 */
+ { 41, 0x3248 }, /* R41 - DRC 1 */
+ { 42, 0x0000 }, /* R42 - DRC 2 */
+ { 43, 0x0000 }, /* R43 - DRC 3 */
+ { 44, 0x0085 }, /* R44 - Analogue Left Input 0 */
+ { 45, 0x0085 }, /* R45 - Analogue Right Input 0 */
+ { 46, 0x0044 }, /* R46 - Analogue Left Input 1 */
+ { 47, 0x0044 }, /* R47 - Analogue Right Input 1 */
+ { 57, 0x002D }, /* R57 - Analogue OUT1 Left */
+ { 58, 0x002D }, /* R58 - Analogue OUT1 Right */
+ { 59, 0x0039 }, /* R59 - Analogue OUT2 Left */
+ { 60, 0x0039 }, /* R60 - Analogue OUT2 Right */
+ { 61, 0x0000 }, /* R61 - Analogue OUT12 ZC */
+ { 67, 0x0000 }, /* R67 - DC Servo 0 */
+ { 69, 0xAAAA }, /* R69 - DC Servo 2 */
+ { 71, 0xAAAA }, /* R71 - DC Servo 4 */
+ { 72, 0xAAAA }, /* R72 - DC Servo 5 */
+ { 90, 0x0000 }, /* R90 - Analogue HP 0 */
+ { 94, 0x0000 }, /* R94 - Analogue Lineout 0 */
+ { 98, 0x0000 }, /* R98 - Charge Pump 0 */
+ { 104, 0x0004 }, /* R104 - Class W 0 */
+ { 108, 0x0000 }, /* R108 - Write Sequencer 0 */
+ { 109, 0x0000 }, /* R109 - Write Sequencer 1 */
+ { 110, 0x0000 }, /* R110 - Write Sequencer 2 */
+ { 111, 0x0000 }, /* R111 - Write Sequencer 3 */
+ { 112, 0x0000 }, /* R112 - Write Sequencer 4 */
+ { 116, 0x0000 }, /* R116 - FLL Control 1 */
+ { 117, 0x0007 }, /* R117 - FLL Control 2 */
+ { 118, 0x0000 }, /* R118 - FLL Control 3 */
+ { 119, 0x2EE0 }, /* R119 - FLL Control 4 */
+ { 120, 0x0004 }, /* R120 - FLL Control 5 */
+ { 121, 0x0014 }, /* R121 - GPIO Control 1 */
+ { 122, 0x0010 }, /* R122 - GPIO Control 2 */
+ { 123, 0x0010 }, /* R123 - GPIO Control 3 */
+ { 124, 0x0000 }, /* R124 - GPIO Control 4 */
+ { 126, 0x0000 }, /* R126 - Digital Pulls */
+ { 128, 0xFFFF }, /* R128 - Interrupt Status Mask */
+ { 129, 0x0000 }, /* R129 - Interrupt Polarity */
+ { 130, 0x0000 }, /* R130 - Interrupt Debounce */
+ { 134, 0x0000 }, /* R134 - EQ1 */
+ { 135, 0x000C }, /* R135 - EQ2 */
+ { 136, 0x000C }, /* R136 - EQ3 */
+ { 137, 0x000C }, /* R137 - EQ4 */
+ { 138, 0x000C }, /* R138 - EQ5 */
+ { 139, 0x000C }, /* R139 - EQ6 */
+ { 140, 0x0FCA }, /* R140 - EQ7 */
+ { 141, 0x0400 }, /* R141 - EQ8 */
+ { 142, 0x00D8 }, /* R142 - EQ9 */
+ { 143, 0x1EB5 }, /* R143 - EQ10 */
+ { 144, 0xF145 }, /* R144 - EQ11 */
+ { 145, 0x0B75 }, /* R145 - EQ12 */
+ { 146, 0x01C5 }, /* R146 - EQ13 */
+ { 147, 0x1C58 }, /* R147 - EQ14 */
+ { 148, 0xF373 }, /* R148 - EQ15 */
+ { 149, 0x0A54 }, /* R149 - EQ16 */
+ { 150, 0x0558 }, /* R150 - EQ17 */
+ { 151, 0x168E }, /* R151 - EQ18 */
+ { 152, 0xF829 }, /* R152 - EQ19 */
+ { 153, 0x07AD }, /* R153 - EQ20 */
+ { 154, 0x1103 }, /* R154 - EQ21 */
+ { 155, 0x0564 }, /* R155 - EQ22 */
+ { 156, 0x0559 }, /* R156 - EQ23 */
+ { 157, 0x4000 }, /* R157 - EQ24 */
+ { 161, 0x0000 }, /* R161 - Control Interface Test 1 */
+ { 204, 0x0000 }, /* R204 - Analogue Output Bias 0 */
+ { 247, 0x0000 }, /* R247 - FLL NCO Test 0 */
+ { 248, 0x0019 }, /* R248 - FLL NCO Test 1 */
};
-static struct {
- int readable;
- int writable;
- int vol;
-} wm8904_access[] = {
- { 0xFFFF, 0xFFFF, 1 }, /* R0 - SW Reset and ID */
- { 0x0000, 0x0000, 0 }, /* R1 - Revision */
- { 0x0000, 0x0000, 0 }, /* R2 */
- { 0x0000, 0x0000, 0 }, /* R3 */
- { 0x001F, 0x001F, 0 }, /* R4 - Bias Control 0 */
- { 0x0047, 0x0047, 0 }, /* R5 - VMID Control 0 */
- { 0x007F, 0x007F, 0 }, /* R6 - Mic Bias Control 0 */
- { 0xC007, 0xC007, 0 }, /* R7 - Mic Bias Control 1 */
- { 0x001E, 0x001E, 0 }, /* R8 - Analogue DAC 0 */
- { 0xFFFF, 0xFFFF, 0 }, /* R9 - mic Filter Control */
- { 0x0001, 0x0001, 0 }, /* R10 - Analogue ADC 0 */
- { 0x0000, 0x0000, 0 }, /* R11 */
- { 0x0003, 0x0003, 0 }, /* R12 - Power Management 0 */
- { 0x0000, 0x0000, 0 }, /* R13 */
- { 0x0003, 0x0003, 0 }, /* R14 - Power Management 2 */
- { 0x0003, 0x0003, 0 }, /* R15 - Power Management 3 */
- { 0x0000, 0x0000, 0 }, /* R16 */
- { 0x0000, 0x0000, 0 }, /* R17 */
- { 0x000F, 0x000F, 0 }, /* R18 - Power Management 6 */
- { 0x0000, 0x0000, 0 }, /* R19 */
- { 0x7001, 0x7001, 0 }, /* R20 - Clock Rates 0 */
- { 0x3C07, 0x3C07, 0 }, /* R21 - Clock Rates 1 */
- { 0xD00F, 0xD00F, 0 }, /* R22 - Clock Rates 2 */
- { 0x0000, 0x0000, 0 }, /* R23 */
- { 0x1FFF, 0x1FFF, 0 }, /* R24 - Audio Interface 0 */
- { 0x3DDF, 0x3DDF, 0 }, /* R25 - Audio Interface 1 */
- { 0x0F1F, 0x0F1F, 0 }, /* R26 - Audio Interface 2 */
- { 0x0FFF, 0x0FFF, 0 }, /* R27 - Audio Interface 3 */
- { 0x0000, 0x0000, 0 }, /* R28 */
- { 0x0000, 0x0000, 0 }, /* R29 */
- { 0x00FF, 0x01FF, 0 }, /* R30 - DAC Digital Volume Left */
- { 0x00FF, 0x01FF, 0 }, /* R31 - DAC Digital Volume Right */
- { 0x0FFF, 0x0FFF, 0 }, /* R32 - DAC Digital 0 */
- { 0x1E4E, 0x1E4E, 0 }, /* R33 - DAC Digital 1 */
- { 0x0000, 0x0000, 0 }, /* R34 */
- { 0x0000, 0x0000, 0 }, /* R35 */
- { 0x00FF, 0x01FF, 0 }, /* R36 - ADC Digital Volume Left */
- { 0x00FF, 0x01FF, 0 }, /* R37 - ADC Digital Volume Right */
- { 0x0073, 0x0073, 0 }, /* R38 - ADC Digital 0 */
- { 0x1800, 0x1800, 0 }, /* R39 - Digital Microphone 0 */
- { 0xDFEF, 0xDFEF, 0 }, /* R40 - DRC 0 */
- { 0xFFFF, 0xFFFF, 0 }, /* R41 - DRC 1 */
- { 0x003F, 0x003F, 0 }, /* R42 - DRC 2 */
- { 0x07FF, 0x07FF, 0 }, /* R43 - DRC 3 */
- { 0x009F, 0x009F, 0 }, /* R44 - Analogue Left Input 0 */
- { 0x009F, 0x009F, 0 }, /* R45 - Analogue Right Input 0 */
- { 0x007F, 0x007F, 0 }, /* R46 - Analogue Left Input 1 */
- { 0x007F, 0x007F, 0 }, /* R47 - Analogue Right Input 1 */
- { 0x0000, 0x0000, 0 }, /* R48 */
- { 0x0000, 0x0000, 0 }, /* R49 */
- { 0x0000, 0x0000, 0 }, /* R50 */
- { 0x0000, 0x0000, 0 }, /* R51 */
- { 0x0000, 0x0000, 0 }, /* R52 */
- { 0x0000, 0x0000, 0 }, /* R53 */
- { 0x0000, 0x0000, 0 }, /* R54 */
- { 0x0000, 0x0000, 0 }, /* R55 */
- { 0x0000, 0x0000, 0 }, /* R56 */
- { 0x017F, 0x01FF, 0 }, /* R57 - Analogue OUT1 Left */
- { 0x017F, 0x01FF, 0 }, /* R58 - Analogue OUT1 Right */
- { 0x017F, 0x01FF, 0 }, /* R59 - Analogue OUT2 Left */
- { 0x017F, 0x01FF, 0 }, /* R60 - Analogue OUT2 Right */
- { 0x000F, 0x000F, 0 }, /* R61 - Analogue OUT12 ZC */
- { 0x0000, 0x0000, 0 }, /* R62 */
- { 0x0000, 0x0000, 0 }, /* R63 */
- { 0x0000, 0x0000, 0 }, /* R64 */
- { 0x0000, 0x0000, 0 }, /* R65 */
- { 0x0000, 0x0000, 0 }, /* R66 */
- { 0x000F, 0x000F, 0 }, /* R67 - DC Servo 0 */
- { 0xFFFF, 0xFFFF, 1 }, /* R68 - DC Servo 1 */
- { 0x0F0F, 0x0F0F, 0 }, /* R69 - DC Servo 2 */
- { 0x0000, 0x0000, 0 }, /* R70 */
- { 0x007F, 0x007F, 0 }, /* R71 - DC Servo 4 */
- { 0x007F, 0x007F, 0 }, /* R72 - DC Servo 5 */
- { 0x00FF, 0x00FF, 1 }, /* R73 - DC Servo 6 */
- { 0x00FF, 0x00FF, 1 }, /* R74 - DC Servo 7 */
- { 0x00FF, 0x00FF, 1 }, /* R75 - DC Servo 8 */
- { 0x00FF, 0x00FF, 1 }, /* R76 - DC Servo 9 */
- { 0x0FFF, 0x0000, 1 }, /* R77 - DC Servo Readback 0 */
- { 0x0000, 0x0000, 0 }, /* R78 */
- { 0x0000, 0x0000, 0 }, /* R79 */
- { 0x0000, 0x0000, 0 }, /* R80 */
- { 0x0000, 0x0000, 0 }, /* R81 */
- { 0x0000, 0x0000, 0 }, /* R82 */
- { 0x0000, 0x0000, 0 }, /* R83 */
- { 0x0000, 0x0000, 0 }, /* R84 */
- { 0x0000, 0x0000, 0 }, /* R85 */
- { 0x0000, 0x0000, 0 }, /* R86 */
- { 0x0000, 0x0000, 0 }, /* R87 */
- { 0x0000, 0x0000, 0 }, /* R88 */
- { 0x0000, 0x0000, 0 }, /* R89 */
- { 0x00FF, 0x00FF, 0 }, /* R90 - Analogue HP 0 */
- { 0x0000, 0x0000, 0 }, /* R91 */
- { 0x0000, 0x0000, 0 }, /* R92 */
- { 0x0000, 0x0000, 0 }, /* R93 */
- { 0x00FF, 0x00FF, 0 }, /* R94 - Analogue Lineout 0 */
- { 0x0000, 0x0000, 0 }, /* R95 */
- { 0x0000, 0x0000, 0 }, /* R96 */
- { 0x0000, 0x0000, 0 }, /* R97 */
- { 0x0001, 0x0001, 0 }, /* R98 - Charge Pump 0 */
- { 0x0000, 0x0000, 0 }, /* R99 */
- { 0x0000, 0x0000, 0 }, /* R100 */
- { 0x0000, 0x0000, 0 }, /* R101 */
- { 0x0000, 0x0000, 0 }, /* R102 */
- { 0x0000, 0x0000, 0 }, /* R103 */
- { 0x0001, 0x0001, 0 }, /* R104 - Class W 0 */
- { 0x0000, 0x0000, 0 }, /* R105 */
- { 0x0000, 0x0000, 0 }, /* R106 */
- { 0x0000, 0x0000, 0 }, /* R107 */
- { 0x011F, 0x011F, 0 }, /* R108 - Write Sequencer 0 */
- { 0x7FFF, 0x7FFF, 0 }, /* R109 - Write Sequencer 1 */
- { 0x4FFF, 0x4FFF, 0 }, /* R110 - Write Sequencer 2 */
- { 0x003F, 0x033F, 0 }, /* R111 - Write Sequencer 3 */
- { 0x03F1, 0x0000, 0 }, /* R112 - Write Sequencer 4 */
- { 0x0000, 0x0000, 0 }, /* R113 */
- { 0x0000, 0x0000, 0 }, /* R114 */
- { 0x0000, 0x0000, 0 }, /* R115 */
- { 0x0007, 0x0007, 0 }, /* R116 - FLL Control 1 */
- { 0x3F77, 0x3F77, 0 }, /* R117 - FLL Control 2 */
- { 0xFFFF, 0xFFFF, 0 }, /* R118 - FLL Control 3 */
- { 0x7FEF, 0x7FEF, 0 }, /* R119 - FLL Control 4 */
- { 0x001B, 0x001B, 0 }, /* R120 - FLL Control 5 */
- { 0x003F, 0x003F, 0 }, /* R121 - GPIO Control 1 */
- { 0x003F, 0x003F, 0 }, /* R122 - GPIO Control 2 */
- { 0x003F, 0x003F, 0 }, /* R123 - GPIO Control 3 */
- { 0x038F, 0x038F, 0 }, /* R124 - GPIO Control 4 */
- { 0x0000, 0x0000, 0 }, /* R125 */
- { 0x00FF, 0x00FF, 0 }, /* R126 - Digital Pulls */
- { 0x07FF, 0x03FF, 1 }, /* R127 - Interrupt Status */
- { 0x03FF, 0x03FF, 0 }, /* R128 - Interrupt Status Mask */
- { 0x03FF, 0x03FF, 0 }, /* R129 - Interrupt Polarity */
- { 0x03FF, 0x03FF, 0 }, /* R130 - Interrupt Debounce */
- { 0x0000, 0x0000, 0 }, /* R131 */
- { 0x0000, 0x0000, 0 }, /* R132 */
- { 0x0000, 0x0000, 0 }, /* R133 */
- { 0x0001, 0x0001, 0 }, /* R134 - EQ1 */
- { 0x001F, 0x001F, 0 }, /* R135 - EQ2 */
- { 0x001F, 0x001F, 0 }, /* R136 - EQ3 */
- { 0x001F, 0x001F, 0 }, /* R137 - EQ4 */
- { 0x001F, 0x001F, 0 }, /* R138 - EQ5 */
- { 0x001F, 0x001F, 0 }, /* R139 - EQ6 */
- { 0xFFFF, 0xFFFF, 0 }, /* R140 - EQ7 */
- { 0xFFFF, 0xFFFF, 0 }, /* R141 - EQ8 */
- { 0xFFFF, 0xFFFF, 0 }, /* R142 - EQ9 */
- { 0xFFFF, 0xFFFF, 0 }, /* R143 - EQ10 */
- { 0xFFFF, 0xFFFF, 0 }, /* R144 - EQ11 */
- { 0xFFFF, 0xFFFF, 0 }, /* R145 - EQ12 */
- { 0xFFFF, 0xFFFF, 0 }, /* R146 - EQ13 */
- { 0xFFFF, 0xFFFF, 0 }, /* R147 - EQ14 */
- { 0xFFFF, 0xFFFF, 0 }, /* R148 - EQ15 */
- { 0xFFFF, 0xFFFF, 0 }, /* R149 - EQ16 */
- { 0xFFFF, 0xFFFF, 0 }, /* R150 - EQ17 */
- { 0xFFFF, 0xFFFF, 0 }, /* R151wm8523_dai - EQ18 */
- { 0xFFFF, 0xFFFF, 0 }, /* R152 - EQ19 */
- { 0xFFFF, 0xFFFF, 0 }, /* R153 - EQ20 */
- { 0xFFFF, 0xFFFF, 0 }, /* R154 - EQ21 */
- { 0xFFFF, 0xFFFF, 0 }, /* R155 - EQ22 */
- { 0xFFFF, 0xFFFF, 0 }, /* R156 - EQ23 */
- { 0xFFFF, 0xFFFF, 0 }, /* R157 - EQ24 */
- { 0x0000, 0x0000, 0 }, /* R158 */
- { 0x0000, 0x0000, 0 }, /* R159 */
- { 0x0000, 0x0000, 0 }, /* R160 */
- { 0x0002, 0x0002, 0 }, /* R161 - Control Interface Test 1 */
- { 0x0000, 0x0000, 0 }, /* R162 */
- { 0x0000, 0x0000, 0 }, /* R163 */
- { 0x0000, 0x0000, 0 }, /* R164 */
- { 0x0000, 0x0000, 0 }, /* R165 */
- { 0x0000, 0x0000, 0 }, /* R166 */
- { 0x0000, 0x0000, 0 }, /* R167 */
- { 0x0000, 0x0000, 0 }, /* R168 */
- { 0x0000, 0x0000, 0 }, /* R169 */
- { 0x0000, 0x0000, 0 }, /* R170 */
- { 0x0000, 0x0000, 0 }, /* R171 */
- { 0x0000, 0x0000, 0 }, /* R172 */
- { 0x0000, 0x0000, 0 }, /* R173 */
- { 0x0000, 0x0000, 0 }, /* R174 */
- { 0x0000, 0x0000, 0 }, /* R175 */
- { 0x0000, 0x0000, 0 }, /* R176 */
- { 0x0000, 0x0000, 0 }, /* R177 */
- { 0x0000, 0x0000, 0 }, /* R178 */
- { 0x0000, 0x0000, 0 }, /* R179 */
- { 0x0000, 0x0000, 0 }, /* R180 */
- { 0x0000, 0x0000, 0 }, /* R181 */
- { 0x0000, 0x0000, 0 }, /* R182 */
- { 0x0000, 0x0000, 0 }, /* R183 */
- { 0x0000, 0x0000, 0 }, /* R184 */
- { 0x0000, 0x0000, 0 }, /* R185 */
- { 0x0000, 0x0000, 0 }, /* R186 */
- { 0x0000, 0x0000, 0 }, /* R187 */
- { 0x0000, 0x0000, 0 }, /* R188 */
- { 0x0000, 0x0000, 0 }, /* R189 */
- { 0x0000, 0x0000, 0 }, /* R190 */
- { 0x0000, 0x0000, 0 }, /* R191 */
- { 0x0000, 0x0000, 0 }, /* R192 */
- { 0x0000, 0x0000, 0 }, /* R193 */
- { 0x0000, 0x0000, 0 }, /* R194 */
- { 0x0000, 0x0000, 0 }, /* R195 */
- { 0x0000, 0x0000, 0 }, /* R196 */
- { 0x0000, 0x0000, 0 }, /* R197 */
- { 0x0000, 0x0000, 0 }, /* R198 */
- { 0x0000, 0x0000, 0 }, /* R199 */
- { 0x0000, 0x0000, 0 }, /* R200 */
- { 0x0000, 0x0000, 0 }, /* R201 */
- { 0x0000, 0x0000, 0 }, /* R202 */
- { 0x0000, 0x0000, 0 }, /* R203 */
- { 0x0070, 0x0070, 0 }, /* R204 - Analogue Output Bias 0 */
- { 0x0000, 0x0000, 0 }, /* R205 */
- { 0x0000, 0x0000, 0 }, /* R206 */
- { 0x0000, 0x0000, 0 }, /* R207 */
- { 0x0000, 0x0000, 0 }, /* R208 */
- { 0x0000, 0x0000, 0 }, /* R209 */
- { 0x0000, 0x0000, 0 }, /* R210 */
- { 0x0000, 0x0000, 0 }, /* R211 */
- { 0x0000, 0x0000, 0 }, /* R212 */
- { 0x0000, 0x0000, 0 }, /* R213 */
- { 0x0000, 0x0000, 0 }, /* R214 */
- { 0x0000, 0x0000, 0 }, /* R215 */
- { 0x0000, 0x0000, 0 }, /* R216 */
- { 0x0000, 0x0000, 0 }, /* R217 */
- { 0x0000, 0x0000, 0 }, /* R218 */
- { 0x0000, 0x0000, 0 }, /* R219 */
- { 0x0000, 0x0000, 0 }, /* R220 */
- { 0x0000, 0x0000, 0 }, /* R221 */
- { 0x0000, 0x0000, 0 }, /* R222 */
- { 0x0000, 0x0000, 0 }, /* R223 */
- { 0x0000, 0x0000, 0 }, /* R224 */
- { 0x0000, 0x0000, 0 }, /* R225 */
- { 0x0000, 0x0000, 0 }, /* R226 */
- { 0x0000, 0x0000, 0 }, /* R227 */
- { 0x0000, 0x0000, 0 }, /* R228 */
- { 0x0000, 0x0000, 0 }, /* R229 */
- { 0x0000, 0x0000, 0 }, /* R230 */
- { 0x0000, 0x0000, 0 }, /* R231 */
- { 0x0000, 0x0000, 0 }, /* R232 */
- { 0x0000, 0x0000, 0 }, /* R233 */
- { 0x0000, 0x0000, 0 }, /* R234 */
- { 0x0000, 0x0000, 0 }, /* R235 */
- { 0x0000, 0x0000, 0 }, /* R236 */
- { 0x0000, 0x0000, 0 }, /* R237 */
- { 0x0000, 0x0000, 0 }, /* R238 */
- { 0x0000, 0x0000, 0 }, /* R239 */
- { 0x0000, 0x0000, 0 }, /* R240 */
- { 0x0000, 0x0000, 0 }, /* R241 */
- { 0x0000, 0x0000, 0 }, /* R242 */
- { 0x0000, 0x0000, 0 }, /* R243 */
- { 0x0000, 0x0000, 0 }, /* R244 */
- { 0x0000, 0x0000, 0 }, /* R245 */
- { 0x0000, 0x0000, 0 }, /* R246 */
- { 0x0001, 0x0001, 0 }, /* R247 - FLL NCO Test 0 */
- { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
-};
+static bool wm8904_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8904_SW_RESET_AND_ID:
+ case WM8904_REVISION:
+ case WM8904_DC_SERVO_1:
+ case WM8904_DC_SERVO_6:
+ case WM8904_DC_SERVO_7:
+ case WM8904_DC_SERVO_8:
+ case WM8904_DC_SERVO_9:
+ case WM8904_DC_SERVO_READBACK_0:
+ case WM8904_INTERRUPT_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
-static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8904_readable_register(struct device *dev, unsigned int reg)
{
- return wm8904_access[reg].vol;
+ switch (reg) {
+ case WM8904_SW_RESET_AND_ID:
+ case WM8904_REVISION:
+ case WM8904_BIAS_CONTROL_0:
+ case WM8904_VMID_CONTROL_0:
+ case WM8904_MIC_BIAS_CONTROL_0:
+ case WM8904_MIC_BIAS_CONTROL_1:
+ case WM8904_ANALOGUE_DAC_0:
+ case WM8904_MIC_FILTER_CONTROL:
+ case WM8904_ANALOGUE_ADC_0:
+ case WM8904_POWER_MANAGEMENT_0:
+ case WM8904_POWER_MANAGEMENT_2:
+ case WM8904_POWER_MANAGEMENT_3:
+ case WM8904_POWER_MANAGEMENT_6:
+ case WM8904_CLOCK_RATES_0:
+ case WM8904_CLOCK_RATES_1:
+ case WM8904_CLOCK_RATES_2:
+ case WM8904_AUDIO_INTERFACE_0:
+ case WM8904_AUDIO_INTERFACE_1:
+ case WM8904_AUDIO_INTERFACE_2:
+ case WM8904_AUDIO_INTERFACE_3:
+ case WM8904_DAC_DIGITAL_VOLUME_LEFT:
+ case WM8904_DAC_DIGITAL_VOLUME_RIGHT:
+ case WM8904_DAC_DIGITAL_0:
+ case WM8904_DAC_DIGITAL_1:
+ case WM8904_ADC_DIGITAL_VOLUME_LEFT:
+ case WM8904_ADC_DIGITAL_VOLUME_RIGHT:
+ case WM8904_ADC_DIGITAL_0:
+ case WM8904_DIGITAL_MICROPHONE_0:
+ case WM8904_DRC_0:
+ case WM8904_DRC_1:
+ case WM8904_DRC_2:
+ case WM8904_DRC_3:
+ case WM8904_ANALOGUE_LEFT_INPUT_0:
+ case WM8904_ANALOGUE_RIGHT_INPUT_0:
+ case WM8904_ANALOGUE_LEFT_INPUT_1:
+ case WM8904_ANALOGUE_RIGHT_INPUT_1:
+ case WM8904_ANALOGUE_OUT1_LEFT:
+ case WM8904_ANALOGUE_OUT1_RIGHT:
+ case WM8904_ANALOGUE_OUT2_LEFT:
+ case WM8904_ANALOGUE_OUT2_RIGHT:
+ case WM8904_ANALOGUE_OUT12_ZC:
+ case WM8904_DC_SERVO_0:
+ case WM8904_DC_SERVO_1:
+ case WM8904_DC_SERVO_2:
+ case WM8904_DC_SERVO_4:
+ case WM8904_DC_SERVO_5:
+ case WM8904_DC_SERVO_6:
+ case WM8904_DC_SERVO_7:
+ case WM8904_DC_SERVO_8:
+ case WM8904_DC_SERVO_9:
+ case WM8904_DC_SERVO_READBACK_0:
+ case WM8904_ANALOGUE_HP_0:
+ case WM8904_ANALOGUE_LINEOUT_0:
+ case WM8904_CHARGE_PUMP_0:
+ case WM8904_CLASS_W_0:
+ case WM8904_WRITE_SEQUENCER_0:
+ case WM8904_WRITE_SEQUENCER_1:
+ case WM8904_WRITE_SEQUENCER_2:
+ case WM8904_WRITE_SEQUENCER_3:
+ case WM8904_WRITE_SEQUENCER_4:
+ case WM8904_FLL_CONTROL_1:
+ case WM8904_FLL_CONTROL_2:
+ case WM8904_FLL_CONTROL_3:
+ case WM8904_FLL_CONTROL_4:
+ case WM8904_FLL_CONTROL_5:
+ case WM8904_GPIO_CONTROL_1:
+ case WM8904_GPIO_CONTROL_2:
+ case WM8904_GPIO_CONTROL_3:
+ case WM8904_GPIO_CONTROL_4:
+ case WM8904_DIGITAL_PULLS:
+ case WM8904_INTERRUPT_STATUS:
+ case WM8904_INTERRUPT_STATUS_MASK:
+ case WM8904_INTERRUPT_POLARITY:
+ case WM8904_INTERRUPT_DEBOUNCE:
+ case WM8904_EQ1:
+ case WM8904_EQ2:
+ case WM8904_EQ3:
+ case WM8904_EQ4:
+ case WM8904_EQ5:
+ case WM8904_EQ6:
+ case WM8904_EQ7:
+ case WM8904_EQ8:
+ case WM8904_EQ9:
+ case WM8904_EQ10:
+ case WM8904_EQ11:
+ case WM8904_EQ12:
+ case WM8904_EQ13:
+ case WM8904_EQ14:
+ case WM8904_EQ15:
+ case WM8904_EQ16:
+ case WM8904_EQ17:
+ case WM8904_EQ18:
+ case WM8904_EQ19:
+ case WM8904_EQ20:
+ case WM8904_EQ21:
+ case WM8904_EQ22:
+ case WM8904_EQ23:
+ case WM8904_EQ24:
+ case WM8904_CONTROL_INTERFACE_TEST_1:
+ case WM8904_ADC_TEST_0:
+ case WM8904_ANALOGUE_OUTPUT_BIAS_0:
+ case WM8904_FLL_NCO_TEST_0:
+ case WM8904_FLL_NCO_TEST_1:
+ return true;
+ default:
+ return true;
+ }
}
static int wm8904_reset(struct snd_soc_codec *codec)
@@ -855,6 +570,29 @@ static const char *hpf_mode_text[] = {
static const struct soc_enum hpf_mode =
SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
+static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int ret;
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ if (ucontrol->value.integer.value[0])
+ val = 0;
+ else
+ val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5;
+
+ snd_soc_update_bits(codec, WM8904_ADC_TEST_0,
+ WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5,
+ val);
+
+ return ret;
+}
+
static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
@@ -871,7 +609,12 @@ SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
SOC_ENUM("High Pass Filter Mode", hpf_mode),
-SOC_SINGLE("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "ADC 128x OSR Switch",
+ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,
+ .put = wm8904_adc_osr_put,
+ .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+},
};
static const char *drc_path_text[] = {
@@ -1433,11 +1176,11 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
switch (wm8904->devtype) {
case WM8904:
- snd_soc_add_controls(codec, wm8904_adc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls,
ARRAY_SIZE(wm8904_adc_snd_controls));
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
- snd_soc_add_controls(codec, wm8904_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_snd_controls,
ARRAY_SIZE(wm8904_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets,
@@ -1458,7 +1201,7 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
break;
case WM8912:
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets,
@@ -2088,32 +1831,6 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
return 0;
}
-static void wm8904_sync_cache(struct snd_soc_codec *codec)
-{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
-
- /* Sync back cached values if they're different from the
- * hardware default.
- */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- if (!wm8904_access[i].writable)
- continue;
-
- if (reg_cache[i] == wm8904_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- codec->cache_sync = 0;
-}
-
static int wm8904_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -2146,7 +1863,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- wm8904_sync_cache(codec);
+ regcache_sync(wm8904->regmap);
/* Enable bias */
snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
@@ -2303,7 +2020,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile control: %d\n", ret);
@@ -2316,7 +2033,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
int ret, i;
if (!pdata) {
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
return;
}
@@ -2344,7 +2061,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
wm8904->drc_enum.max = pdata->num_drc_cfgs;
wm8904->drc_enum.texts = wm8904->drc_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add DRC mode control: %d\n", ret);
@@ -2358,7 +2075,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
if (pdata->num_retune_mobile_cfgs)
wm8904_handle_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
}
@@ -2371,7 +2088,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
int ret, i;
codec->cache_sync = 1;
- codec->dapm.idle_bias_off = 1;
+ codec->control_data = wm8904->regmap;
switch (wm8904->devtype) {
case WM8904:
@@ -2385,7 +2102,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -2413,7 +2130,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
dev_err(codec->dev, "Failed to read ID register\n");
goto err_enable;
}
- if (ret != wm8904_reg[WM8904_SW_RESET_AND_ID]) {
+ if (ret != 0x8904) {
dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
ret = -EINVAL;
goto err_enable;
@@ -2519,38 +2236,62 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
.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,
+ .idle_bias_off = true,
+};
+
+static const struct regmap_config wm8904_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM8904_MAX_REGISTER,
+ .volatile_reg = wm8904_volatile_register,
+ .readable_reg = wm8904_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8904_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
-#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;
int ret;
- wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
+ wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
+ GFP_KERNEL);
if (wm8904 == NULL)
return -ENOMEM;
+ wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap);
+ if (IS_ERR(wm8904->regmap)) {
+ ret = PTR_ERR(wm8904->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
wm8904->devtype = id->driver_data;
i2c_set_clientdata(i2c, wm8904);
wm8904->pdata = i2c->dev.platform_data;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8904, &wm8904_dai, 1);
- if (ret < 0)
- kfree(wm8904);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8904->regmap);
return ret;
}
static __devexit int wm8904_i2c_remove(struct i2c_client *client)
{
+ struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8904->regmap);
return 0;
}
@@ -2571,27 +2312,22 @@ static struct i2c_driver wm8904_i2c_driver = {
.remove = __devexit_p(wm8904_i2c_remove),
.id_table = wm8904_i2c_id,
};
-#endif
static int __init wm8904_modinit(void)
{
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",
ret);
}
-#endif
return ret;
}
module_init(wm8904_modinit);
static void __exit wm8904_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8904_i2c_driver);
-#endif
}
module_exit(wm8904_exit);
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index 9e8c84188ba7..c29a0e8131ca 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -123,6 +123,7 @@
#define WM8904_EQ23 0x9C
#define WM8904_EQ24 0x9D
#define WM8904_CONTROL_INTERFACE_TEST_1 0xA1
+#define WM8904_ADC_TEST_0 0xC6
#define WM8904_ANALOGUE_OUTPUT_BIAS_0 0xCC
#define WM8904_FLL_NCO_TEST_0 0xF7
#define WM8904_FLL_NCO_TEST_1 0xF8
@@ -1557,6 +1558,16 @@
#define WM8904_USER_KEY_WIDTH 1 /* USER_KEY */
/*
+ * R198 (0xC6) - ADC Test 0
+ */
+#define WM8904_ADC_128_OSR_TST_MODE 0x0004 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_SHIFT 2 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_WIDTH 1 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_BIASX1P5 0x0001 /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_SHIFT 0 /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_WIDTH 1 /* ADC_BIASX1P5 */
+
+/*
* R204 (0xCC) - Analogue Output Bias 0
*/
#define WM8904_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 14039ea2f3e4..d2883affea3b 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -717,7 +717,7 @@ static int wm8940_probe(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
ARRAY_SIZE(wm8940_snd_controls));
if (ret)
return ret;
@@ -743,14 +743,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
.volatile_register = wm8940_volatile_register,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8940_priv *wm8940;
int ret;
- wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
+ wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv),
+ GFP_KERNEL);
if (wm8940 == NULL)
return -ENOMEM;
@@ -759,15 +759,14 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8940, &wm8940_dai, 1);
- if (ret < 0)
- kfree(wm8940);
+
return ret;
}
static __devexit int wm8940_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
@@ -786,27 +785,22 @@ static struct i2c_driver wm8940_i2c_driver = {
.remove = __devexit_p(wm8940_i2c_remove),
.id_table = wm8940_i2c_id,
};
-#endif
static int __init wm8940_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8940_i2c_driver);
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);
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 924548182d58..61fe97433e73 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
/* codec private data */
struct wm8955_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
unsigned int mclk_rate;
@@ -48,69 +49,85 @@ struct wm8955_priv {
struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
};
-static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
- 0x0000, /* R0 */
- 0x0000, /* R1 */
- 0x0079, /* R2 - LOUT1 volume */
- 0x0079, /* R3 - ROUT1 volume */
- 0x0000, /* R4 */
- 0x0008, /* R5 - DAC Control */
- 0x0000, /* R6 */
- 0x000A, /* R7 - Audio Interface */
- 0x0000, /* R8 - Sample Rate */
- 0x0000, /* R9 */
- 0x00FF, /* R10 - Left DAC volume */
- 0x00FF, /* R11 - Right DAC volume */
- 0x000F, /* R12 - Bass control */
- 0x000F, /* R13 - Treble control */
- 0x0000, /* R14 */
- 0x0000, /* R15 - Reset */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 */
- 0x0000, /* R22 */
- 0x00C1, /* R23 - Additional control (1) */
- 0x0000, /* R24 - Additional control (2) */
- 0x0000, /* R25 - Power Management (1) */
- 0x0000, /* R26 - Power Management (2) */
- 0x0000, /* R27 - Additional Control (3) */
- 0x0000, /* R28 */
- 0x0000, /* R29 */
- 0x0000, /* R30 */
- 0x0000, /* R31 */
- 0x0000, /* R32 */
- 0x0000, /* R33 */
- 0x0050, /* R34 - Left out Mix (1) */
- 0x0050, /* R35 - Left out Mix (2) */
- 0x0050, /* R36 - Right out Mix (1) */
- 0x0050, /* R37 - Right Out Mix (2) */
- 0x0050, /* R38 - Mono out Mix (1) */
- 0x0050, /* R39 - Mono out Mix (2) */
- 0x0079, /* R40 - LOUT2 volume */
- 0x0079, /* R41 - ROUT2 volume */
- 0x0079, /* R42 - MONOOUT volume */
- 0x0000, /* R43 - Clocking / PLL */
- 0x0103, /* R44 - PLL Control 1 */
- 0x0024, /* R45 - PLL Control 2 */
- 0x01BA, /* R46 - PLL Control 3 */
- 0x0000, /* R47 */
- 0x0000, /* R48 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x0000, /* R57 */
- 0x0000, /* R58 */
- 0x0000, /* R59 - PLL Control 4 */
+static const struct reg_default wm8955_reg_defaults[] = {
+ { 2, 0x0079 }, /* R2 - LOUT1 volume */
+ { 3, 0x0079 }, /* R3 - ROUT1 volume */
+ { 5, 0x0008 }, /* R5 - DAC Control */
+ { 7, 0x000A }, /* R7 - Audio Interface */
+ { 8, 0x0000 }, /* R8 - Sample Rate */
+ { 10, 0x00FF }, /* R10 - Left DAC volume */
+ { 11, 0x00FF }, /* R11 - Right DAC volume */
+ { 12, 0x000F }, /* R12 - Bass control */
+ { 13, 0x000F }, /* R13 - Treble control */
+ { 23, 0x00C1 }, /* R23 - Additional control (1) */
+ { 24, 0x0000 }, /* R24 - Additional control (2) */
+ { 25, 0x0000 }, /* R25 - Power Management (1) */
+ { 26, 0x0000 }, /* R26 - Power Management (2) */
+ { 27, 0x0000 }, /* R27 - Additional Control (3) */
+ { 34, 0x0050 }, /* R34 - Left out Mix (1) */
+ { 35, 0x0050 }, /* R35 - Left out Mix (2) */
+ { 36, 0x0050 }, /* R36 - Right out Mix (1) */
+ { 37, 0x0050 }, /* R37 - Right Out Mix (2) */
+ { 38, 0x0050 }, /* R38 - Mono out Mix (1) */
+ { 39, 0x0050 }, /* R39 - Mono out Mix (2) */
+ { 40, 0x0079 }, /* R40 - LOUT2 volume */
+ { 41, 0x0079 }, /* R41 - ROUT2 volume */
+ { 42, 0x0079 }, /* R42 - MONOOUT volume */
+ { 43, 0x0000 }, /* R43 - Clocking / PLL */
+ { 44, 0x0103 }, /* R44 - PLL Control 1 */
+ { 45, 0x0024 }, /* R45 - PLL Control 2 */
+ { 46, 0x01BA }, /* R46 - PLL Control 3 */
+ { 59, 0x0000 }, /* R59 - PLL Control 4 */
};
+static bool wm8955_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8955_LOUT1_VOLUME:
+ case WM8955_ROUT1_VOLUME:
+ case WM8955_DAC_CONTROL:
+ case WM8955_AUDIO_INTERFACE:
+ case WM8955_SAMPLE_RATE:
+ case WM8955_LEFT_DAC_VOLUME:
+ case WM8955_RIGHT_DAC_VOLUME:
+ case WM8955_BASS_CONTROL:
+ case WM8955_TREBLE_CONTROL:
+ case WM8955_RESET:
+ case WM8955_ADDITIONAL_CONTROL_1:
+ case WM8955_ADDITIONAL_CONTROL_2:
+ case WM8955_POWER_MANAGEMENT_1:
+ case WM8955_POWER_MANAGEMENT_2:
+ case WM8955_ADDITIONAL_CONTROL_3:
+ case WM8955_LEFT_OUT_MIX_1:
+ case WM8955_LEFT_OUT_MIX_2:
+ case WM8955_RIGHT_OUT_MIX_1:
+ case WM8955_RIGHT_OUT_MIX_2:
+ case WM8955_MONO_OUT_MIX_1:
+ case WM8955_MONO_OUT_MIX_2:
+ case WM8955_LOUT2_VOLUME:
+ case WM8955_ROUT2_VOLUME:
+ case WM8955_MONOOUT_VOLUME:
+ case WM8955_CLOCKING_PLL:
+ case WM8955_PLL_CONTROL_1:
+ case WM8955_PLL_CONTROL_2:
+ case WM8955_PLL_CONTROL_3:
+ case WM8955_PLL_CONTROL_4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8955_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8955_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int wm8955_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, WM8955_RESET, 0);
@@ -527,7 +544,7 @@ SND_SOC_DAPM_OUTPUT("MONOOUT"),
SND_SOC_DAPM_OUTPUT("OUT3"),
};
-static const struct snd_soc_dapm_route wm8955_intercon[] = {
+static const struct snd_soc_dapm_route wm8955_dapm_routes[] = {
{ "DACL", NULL, "SYSCLK" },
{ "DACR", NULL, "SYSCLK" },
@@ -572,21 +589,6 @@ static const struct snd_soc_dapm_route wm8955_intercon[] = {
{ "OUT3", NULL, "OUT3 PGA" },
};
-static int wm8955_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_add_controls(codec, wm8955_snd_controls,
- ARRAY_SIZE(wm8955_snd_controls));
-
- snd_soc_dapm_new_controls(dapm, wm8955_dapm_widgets,
- ARRAY_SIZE(wm8955_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, wm8955_intercon,
- ARRAY_SIZE(wm8955_intercon));
-
- return 0;
-}
-
static int wm8955_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -765,8 +767,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
- u16 *reg_cache = codec->reg_cache;
- int ret, i;
+ int ret;
switch (level) {
case SND_SOC_BIAS_ON:
@@ -795,18 +796,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- /* Sync back cached values if they're
- * different from the hardware default.
- */
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8955_RESET)
- continue;
-
- if (reg_cache[i] == wm8955_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
+ regcache_sync(wm8955->regmap);
/* Enable VREF and VMID */
snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
@@ -880,8 +870,12 @@ static struct snd_soc_dai_driver wm8955_dai = {
#ifdef CONFIG_PM
static int wm8955_suspend(struct snd_soc_codec *codec)
{
+ struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_mark_dirty(wm8955->regmap);
+
return 0;
}
@@ -900,10 +894,11 @@ static int wm8955_probe(struct snd_soc_codec *codec)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
- u16 *reg_cache = codec->reg_cache;
int ret, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
+ codec->control_data = wm8955->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -958,12 +953,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
/* Set platform data values */
if (pdata) {
if (pdata->out2_speaker)
- reg_cache[WM8955_ADDITIONAL_CONTROL_2]
- |= WM8955_ROUT2INV;
+ snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2,
+ WM8955_ROUT2INV, WM8955_ROUT2INV);
if (pdata->monoin_diff)
- reg_cache[WM8955_MONO_OUT_MIX_1]
- |= WM8955_DMEN;
+ snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1,
+ WM8955_DMEN, WM8955_DMEN);
}
wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -971,7 +966,6 @@ static int wm8955_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
- wm8955_add_widgets(codec);
return 0;
err_enable:
@@ -996,36 +990,68 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
.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,
+
+ .controls = wm8955_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8955_snd_controls),
+ .dapm_widgets = wm8955_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets),
+ .dapm_routes = wm8955_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes),
+};
+
+static const struct regmap_config wm8955_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8955_MAX_REGISTER,
+ .volatile_reg = wm8955_volatile,
+ .writeable_reg = wm8955_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8955_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
};
-#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;
int ret;
- wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
+ wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv),
+ GFP_KERNEL);
if (wm8955 == NULL)
return -ENOMEM;
+ wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+ if (IS_ERR(wm8955->regmap)) {
+ ret = PTR_ERR(wm8955->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8955);
- wm8955->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1);
- if (ret < 0)
- kfree(wm8955);
+ if (ret != 0)
+ goto err;
+
+ return ret;
+
+err:
+ regmap_exit(wm8955->regmap);
return ret;
}
static __devexit int wm8955_i2c_remove(struct i2c_client *client)
{
+ struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8955->regmap);
+
return 0;
}
@@ -1044,27 +1070,22 @@ static struct i2c_driver wm8955_i2c_driver = {
.remove = __devexit_p(wm8955_i2c_remove),
.id_table = wm8955_i2c_id,
};
-#endif
static int __init wm8955_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8955_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8955_modinit);
static void __exit wm8955_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8955_i2c_driver);
-#endif
}
module_exit(wm8955_exit);
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 40ac888faf3d..1332692ef81b 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -920,11 +920,11 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->dsp_active = -1;
- snd_soc_add_controls(codec, wm8958_mbc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls,
ARRAY_SIZE(wm8958_mbc_snd_controls));
- snd_soc_add_controls(codec, wm8958_vss_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls,
ARRAY_SIZE(wm8958_vss_snd_controls));
- snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls,
ARRAY_SIZE(wm8958_enh_eq_snd_controls));
@@ -958,7 +958,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
wm8994->mbc_enum.texts = wm8994->mbc_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add MBC mode controls: %d\n", ret);
@@ -986,7 +986,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_enum.max = pdata->num_vss_cfgs;
wm8994->vss_enum.texts = wm8994->vss_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS mode controls: %d\n", ret);
@@ -1015,7 +1015,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS HPFmode controls: %d\n",
@@ -1045,7 +1045,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add enhanced EQ controls: %d\n",
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index e5caae32e541..840d72086d04 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -940,7 +940,7 @@ static int wm8960_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
- snd_soc_add_controls(codec, wm8960_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8960_snd_controls,
ARRAY_SIZE(wm8960_snd_controls));
wm8960_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 4f20c72a0f1d..05ea7c274093 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1022,7 +1022,7 @@ static int wm8961_probe(struct snd_soc_codec *codec)
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8961_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8961_snd_controls,
ARRAY_SIZE(wm8961_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
ARRAY_SIZE(wm8961_dapm_widgets));
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 296de4e30d26..15d467ff91b4 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -96,7 +97,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \
struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- regcache_cache_only(wm8962->regmap, true); \
+ regcache_mark_dirty(wm8962->regmap); \
} \
return 0; \
}
@@ -115,11 +116,11 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -128,7 +129,7 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -152,10 +153,6 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -167,8 +164,6 @@ static struct reg_default wm8962_reg[] = {
{ 64, 0x0810 }, /* R64 - DC Servo 4 */
- { 66, 0x0000 }, /* R66 - DC Servo 6 */
-
{ 68, 0x001B }, /* R68 - Analogue PGA Bias */
{ 69, 0x0000 }, /* R69 - Analogue HP 0 */
@@ -207,8 +202,6 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -303,9 +296,6 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -317,8 +307,6 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -797,1167 +785,660 @@ static struct reg_default wm8962_reg[] = {
{ 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, 0x0000 }, /* 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, 0xFFFF }, /* 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, 0xFFFF }, /* 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 bool wm8962_volatile_register(struct device *dev, unsigned int reg)
{
- if (wm8962_reg_access[reg].vol)
- return 1;
- else
- return 0;
+ switch (reg) {
+ case WM8962_CLOCKING1:
+ case WM8962_CLOCKING2:
+ case WM8962_SOFTWARE_RESET:
+ case WM8962_ALC2:
+ case WM8962_THERMAL_SHUTDOWN_STATUS:
+ case WM8962_ADDITIONAL_CONTROL_4:
+ case WM8962_CLASS_D_CONTROL_1:
+ case WM8962_DC_SERVO_6:
+ case WM8962_INTERRUPT_STATUS_1:
+ case WM8962_INTERRUPT_STATUS_2:
+ case WM8962_DSP2_EXECCONTROL:
+ return true;
+ default:
+ return false;
+ }
}
static bool wm8962_readable_register(struct device *dev, unsigned int reg)
{
- if (wm8962_reg_access[reg].read)
- return 1;
- else
- return 0;
+ switch (reg) {
+ case WM8962_LEFT_INPUT_VOLUME:
+ case WM8962_RIGHT_INPUT_VOLUME:
+ case WM8962_HPOUTL_VOLUME:
+ case WM8962_HPOUTR_VOLUME:
+ case WM8962_CLOCKING1:
+ case WM8962_ADC_DAC_CONTROL_1:
+ case WM8962_ADC_DAC_CONTROL_2:
+ case WM8962_AUDIO_INTERFACE_0:
+ case WM8962_CLOCKING2:
+ case WM8962_AUDIO_INTERFACE_1:
+ case WM8962_LEFT_DAC_VOLUME:
+ case WM8962_RIGHT_DAC_VOLUME:
+ case WM8962_AUDIO_INTERFACE_2:
+ case WM8962_SOFTWARE_RESET:
+ case WM8962_ALC1:
+ case WM8962_ALC2:
+ case WM8962_ALC3:
+ case WM8962_NOISE_GATE:
+ case WM8962_LEFT_ADC_VOLUME:
+ case WM8962_RIGHT_ADC_VOLUME:
+ case WM8962_ADDITIONAL_CONTROL_1:
+ case WM8962_ADDITIONAL_CONTROL_2:
+ case WM8962_PWR_MGMT_1:
+ case WM8962_PWR_MGMT_2:
+ case WM8962_ADDITIONAL_CONTROL_3:
+ case WM8962_ANTI_POP:
+ case WM8962_CLOCKING_3:
+ case WM8962_INPUT_MIXER_CONTROL_1:
+ case WM8962_LEFT_INPUT_MIXER_VOLUME:
+ case WM8962_RIGHT_INPUT_MIXER_VOLUME:
+ case WM8962_INPUT_MIXER_CONTROL_2:
+ case WM8962_INPUT_BIAS_CONTROL:
+ case WM8962_LEFT_INPUT_PGA_CONTROL:
+ case WM8962_RIGHT_INPUT_PGA_CONTROL:
+ case WM8962_SPKOUTL_VOLUME:
+ case WM8962_SPKOUTR_VOLUME:
+ case WM8962_THERMAL_SHUTDOWN_STATUS:
+ case WM8962_ADDITIONAL_CONTROL_4:
+ case WM8962_CLASS_D_CONTROL_1:
+ case WM8962_CLASS_D_CONTROL_2:
+ case WM8962_CLOCKING_4:
+ case WM8962_DAC_DSP_MIXING_1:
+ case WM8962_DAC_DSP_MIXING_2:
+ case WM8962_DC_SERVO_0:
+ case WM8962_DC_SERVO_1:
+ case WM8962_DC_SERVO_4:
+ case WM8962_DC_SERVO_6:
+ case WM8962_ANALOGUE_PGA_BIAS:
+ case WM8962_ANALOGUE_HP_0:
+ case WM8962_ANALOGUE_HP_2:
+ case WM8962_CHARGE_PUMP_1:
+ case WM8962_CHARGE_PUMP_B:
+ case WM8962_WRITE_SEQUENCER_CONTROL_1:
+ case WM8962_WRITE_SEQUENCER_CONTROL_2:
+ case WM8962_WRITE_SEQUENCER_CONTROL_3:
+ case WM8962_CONTROL_INTERFACE:
+ case WM8962_MIXER_ENABLES:
+ case WM8962_HEADPHONE_MIXER_1:
+ case WM8962_HEADPHONE_MIXER_2:
+ case WM8962_HEADPHONE_MIXER_3:
+ case WM8962_HEADPHONE_MIXER_4:
+ case WM8962_SPEAKER_MIXER_1:
+ case WM8962_SPEAKER_MIXER_2:
+ case WM8962_SPEAKER_MIXER_3:
+ case WM8962_SPEAKER_MIXER_4:
+ case WM8962_SPEAKER_MIXER_5:
+ case WM8962_BEEP_GENERATOR_1:
+ case WM8962_OSCILLATOR_TRIM_3:
+ case WM8962_OSCILLATOR_TRIM_4:
+ case WM8962_OSCILLATOR_TRIM_7:
+ case WM8962_ANALOGUE_CLOCKING1:
+ case WM8962_ANALOGUE_CLOCKING2:
+ case WM8962_ANALOGUE_CLOCKING3:
+ case WM8962_PLL_SOFTWARE_RESET:
+ case WM8962_PLL2:
+ case WM8962_PLL_4:
+ case WM8962_PLL_9:
+ case WM8962_PLL_10:
+ case WM8962_PLL_11:
+ case WM8962_PLL_12:
+ case WM8962_PLL_13:
+ case WM8962_PLL_14:
+ case WM8962_PLL_15:
+ case WM8962_PLL_16:
+ case WM8962_FLL_CONTROL_1:
+ case WM8962_FLL_CONTROL_2:
+ case WM8962_FLL_CONTROL_3:
+ case WM8962_FLL_CONTROL_5:
+ case WM8962_FLL_CONTROL_6:
+ case WM8962_FLL_CONTROL_7:
+ case WM8962_FLL_CONTROL_8:
+ case WM8962_GENERAL_TEST_1:
+ case WM8962_DF1:
+ case WM8962_DF2:
+ case WM8962_DF3:
+ case WM8962_DF4:
+ case WM8962_DF5:
+ case WM8962_DF6:
+ case WM8962_DF7:
+ case WM8962_LHPF1:
+ case WM8962_LHPF2:
+ case WM8962_THREED1:
+ case WM8962_THREED2:
+ case WM8962_THREED3:
+ case WM8962_THREED4:
+ case WM8962_DRC_1:
+ case WM8962_DRC_2:
+ case WM8962_DRC_3:
+ case WM8962_DRC_4:
+ case WM8962_DRC_5:
+ case WM8962_TLOOPBACK:
+ case WM8962_EQ1:
+ case WM8962_EQ2:
+ case WM8962_EQ3:
+ case WM8962_EQ4:
+ case WM8962_EQ5:
+ case WM8962_EQ6:
+ case WM8962_EQ7:
+ case WM8962_EQ8:
+ case WM8962_EQ9:
+ case WM8962_EQ10:
+ case WM8962_EQ11:
+ case WM8962_EQ12:
+ case WM8962_EQ13:
+ case WM8962_EQ14:
+ case WM8962_EQ15:
+ case WM8962_EQ16:
+ case WM8962_EQ17:
+ case WM8962_EQ18:
+ case WM8962_EQ19:
+ case WM8962_EQ20:
+ case WM8962_EQ21:
+ case WM8962_EQ22:
+ case WM8962_EQ23:
+ case WM8962_EQ24:
+ case WM8962_EQ25:
+ case WM8962_EQ26:
+ case WM8962_EQ27:
+ case WM8962_EQ28:
+ case WM8962_EQ29:
+ case WM8962_EQ30:
+ case WM8962_EQ31:
+ case WM8962_EQ32:
+ case WM8962_EQ33:
+ case WM8962_EQ34:
+ case WM8962_EQ35:
+ case WM8962_EQ36:
+ case WM8962_EQ37:
+ case WM8962_EQ38:
+ case WM8962_EQ39:
+ case WM8962_EQ40:
+ case WM8962_EQ41:
+ case WM8962_GPIO_BASE:
+ case WM8962_GPIO_2:
+ case WM8962_GPIO_3:
+ case WM8962_GPIO_5:
+ case WM8962_GPIO_6:
+ case WM8962_INTERRUPT_STATUS_1:
+ case WM8962_INTERRUPT_STATUS_2:
+ case WM8962_INTERRUPT_STATUS_1_MASK:
+ case WM8962_INTERRUPT_STATUS_2_MASK:
+ case WM8962_INTERRUPT_CONTROL:
+ case WM8962_IRQ_DEBOUNCE:
+ case WM8962_MICINT_SOURCE_POL:
+ case WM8962_DSP2_POWER_MANAGEMENT:
+ case WM8962_DSP2_EXECCONTROL:
+ case WM8962_DSP2_INSTRUCTION_RAM_0:
+ case WM8962_DSP2_ADDRESS_RAM_2:
+ case WM8962_DSP2_ADDRESS_RAM_1:
+ case WM8962_DSP2_ADDRESS_RAM_0:
+ case WM8962_DSP2_DATA1_RAM_1:
+ case WM8962_DSP2_DATA1_RAM_0:
+ case WM8962_DSP2_DATA2_RAM_1:
+ case WM8962_DSP2_DATA2_RAM_0:
+ case WM8962_DSP2_DATA3_RAM_1:
+ case WM8962_DSP2_DATA3_RAM_0:
+ case WM8962_DSP2_COEFF_RAM_0:
+ case WM8962_RETUNEADC_SHARED_COEFF_1:
+ case WM8962_RETUNEADC_SHARED_COEFF_0:
+ case WM8962_RETUNEDAC_SHARED_COEFF_1:
+ case WM8962_RETUNEDAC_SHARED_COEFF_0:
+ case WM8962_SOUNDSTAGE_ENABLES_1:
+ case WM8962_SOUNDSTAGE_ENABLES_0:
+ case WM8962_HDBASS_AI_1:
+ case WM8962_HDBASS_AI_0:
+ case WM8962_HDBASS_AR_1:
+ case WM8962_HDBASS_AR_0:
+ case WM8962_HDBASS_B_1:
+ case WM8962_HDBASS_B_0:
+ case WM8962_HDBASS_K_1:
+ case WM8962_HDBASS_K_0:
+ case WM8962_HDBASS_N1_1:
+ case WM8962_HDBASS_N1_0:
+ case WM8962_HDBASS_N2_1:
+ case WM8962_HDBASS_N2_0:
+ case WM8962_HDBASS_N3_1:
+ case WM8962_HDBASS_N3_0:
+ case WM8962_HDBASS_N4_1:
+ case WM8962_HDBASS_N4_0:
+ case WM8962_HDBASS_N5_1:
+ case WM8962_HDBASS_N5_0:
+ case WM8962_HDBASS_X1_1:
+ case WM8962_HDBASS_X1_0:
+ case WM8962_HDBASS_X2_1:
+ case WM8962_HDBASS_X2_0:
+ case WM8962_HDBASS_X3_1:
+ case WM8962_HDBASS_X3_0:
+ case WM8962_HDBASS_ATK_1:
+ case WM8962_HDBASS_ATK_0:
+ case WM8962_HDBASS_DCY_1:
+ case WM8962_HDBASS_DCY_0:
+ case WM8962_HDBASS_PG_1:
+ case WM8962_HDBASS_PG_0:
+ case WM8962_HPF_C_1:
+ case WM8962_HPF_C_0:
+ case WM8962_ADCL_RETUNE_C1_1:
+ case WM8962_ADCL_RETUNE_C1_0:
+ case WM8962_ADCL_RETUNE_C2_1:
+ case WM8962_ADCL_RETUNE_C2_0:
+ case WM8962_ADCL_RETUNE_C3_1:
+ case WM8962_ADCL_RETUNE_C3_0:
+ case WM8962_ADCL_RETUNE_C4_1:
+ case WM8962_ADCL_RETUNE_C4_0:
+ case WM8962_ADCL_RETUNE_C5_1:
+ case WM8962_ADCL_RETUNE_C5_0:
+ case WM8962_ADCL_RETUNE_C6_1:
+ case WM8962_ADCL_RETUNE_C6_0:
+ case WM8962_ADCL_RETUNE_C7_1:
+ case WM8962_ADCL_RETUNE_C7_0:
+ case WM8962_ADCL_RETUNE_C8_1:
+ case WM8962_ADCL_RETUNE_C8_0:
+ case WM8962_ADCL_RETUNE_C9_1:
+ case WM8962_ADCL_RETUNE_C9_0:
+ case WM8962_ADCL_RETUNE_C10_1:
+ case WM8962_ADCL_RETUNE_C10_0:
+ case WM8962_ADCL_RETUNE_C11_1:
+ case WM8962_ADCL_RETUNE_C11_0:
+ case WM8962_ADCL_RETUNE_C12_1:
+ case WM8962_ADCL_RETUNE_C12_0:
+ case WM8962_ADCL_RETUNE_C13_1:
+ case WM8962_ADCL_RETUNE_C13_0:
+ case WM8962_ADCL_RETUNE_C14_1:
+ case WM8962_ADCL_RETUNE_C14_0:
+ case WM8962_ADCL_RETUNE_C15_1:
+ case WM8962_ADCL_RETUNE_C15_0:
+ case WM8962_ADCL_RETUNE_C16_1:
+ case WM8962_ADCL_RETUNE_C16_0:
+ case WM8962_ADCL_RETUNE_C17_1:
+ case WM8962_ADCL_RETUNE_C17_0:
+ case WM8962_ADCL_RETUNE_C18_1:
+ case WM8962_ADCL_RETUNE_C18_0:
+ case WM8962_ADCL_RETUNE_C19_1:
+ case WM8962_ADCL_RETUNE_C19_0:
+ case WM8962_ADCL_RETUNE_C20_1:
+ case WM8962_ADCL_RETUNE_C20_0:
+ case WM8962_ADCL_RETUNE_C21_1:
+ case WM8962_ADCL_RETUNE_C21_0:
+ case WM8962_ADCL_RETUNE_C22_1:
+ case WM8962_ADCL_RETUNE_C22_0:
+ case WM8962_ADCL_RETUNE_C23_1:
+ case WM8962_ADCL_RETUNE_C23_0:
+ case WM8962_ADCL_RETUNE_C24_1:
+ case WM8962_ADCL_RETUNE_C24_0:
+ case WM8962_ADCL_RETUNE_C25_1:
+ case WM8962_ADCL_RETUNE_C25_0:
+ case WM8962_ADCL_RETUNE_C26_1:
+ case WM8962_ADCL_RETUNE_C26_0:
+ case WM8962_ADCL_RETUNE_C27_1:
+ case WM8962_ADCL_RETUNE_C27_0:
+ case WM8962_ADCL_RETUNE_C28_1:
+ case WM8962_ADCL_RETUNE_C28_0:
+ case WM8962_ADCL_RETUNE_C29_1:
+ case WM8962_ADCL_RETUNE_C29_0:
+ case WM8962_ADCL_RETUNE_C30_1:
+ case WM8962_ADCL_RETUNE_C30_0:
+ case WM8962_ADCL_RETUNE_C31_1:
+ case WM8962_ADCL_RETUNE_C31_0:
+ case WM8962_ADCL_RETUNE_C32_1:
+ case WM8962_ADCL_RETUNE_C32_0:
+ case WM8962_RETUNEADC_PG2_1:
+ case WM8962_RETUNEADC_PG2_0:
+ case WM8962_RETUNEADC_PG_1:
+ case WM8962_RETUNEADC_PG_0:
+ case WM8962_ADCR_RETUNE_C1_1:
+ case WM8962_ADCR_RETUNE_C1_0:
+ case WM8962_ADCR_RETUNE_C2_1:
+ case WM8962_ADCR_RETUNE_C2_0:
+ case WM8962_ADCR_RETUNE_C3_1:
+ case WM8962_ADCR_RETUNE_C3_0:
+ case WM8962_ADCR_RETUNE_C4_1:
+ case WM8962_ADCR_RETUNE_C4_0:
+ case WM8962_ADCR_RETUNE_C5_1:
+ case WM8962_ADCR_RETUNE_C5_0:
+ case WM8962_ADCR_RETUNE_C6_1:
+ case WM8962_ADCR_RETUNE_C6_0:
+ case WM8962_ADCR_RETUNE_C7_1:
+ case WM8962_ADCR_RETUNE_C7_0:
+ case WM8962_ADCR_RETUNE_C8_1:
+ case WM8962_ADCR_RETUNE_C8_0:
+ case WM8962_ADCR_RETUNE_C9_1:
+ case WM8962_ADCR_RETUNE_C9_0:
+ case WM8962_ADCR_RETUNE_C10_1:
+ case WM8962_ADCR_RETUNE_C10_0:
+ case WM8962_ADCR_RETUNE_C11_1:
+ case WM8962_ADCR_RETUNE_C11_0:
+ case WM8962_ADCR_RETUNE_C12_1:
+ case WM8962_ADCR_RETUNE_C12_0:
+ case WM8962_ADCR_RETUNE_C13_1:
+ case WM8962_ADCR_RETUNE_C13_0:
+ case WM8962_ADCR_RETUNE_C14_1:
+ case WM8962_ADCR_RETUNE_C14_0:
+ case WM8962_ADCR_RETUNE_C15_1:
+ case WM8962_ADCR_RETUNE_C15_0:
+ case WM8962_ADCR_RETUNE_C16_1:
+ case WM8962_ADCR_RETUNE_C16_0:
+ case WM8962_ADCR_RETUNE_C17_1:
+ case WM8962_ADCR_RETUNE_C17_0:
+ case WM8962_ADCR_RETUNE_C18_1:
+ case WM8962_ADCR_RETUNE_C18_0:
+ case WM8962_ADCR_RETUNE_C19_1:
+ case WM8962_ADCR_RETUNE_C19_0:
+ case WM8962_ADCR_RETUNE_C20_1:
+ case WM8962_ADCR_RETUNE_C20_0:
+ case WM8962_ADCR_RETUNE_C21_1:
+ case WM8962_ADCR_RETUNE_C21_0:
+ case WM8962_ADCR_RETUNE_C22_1:
+ case WM8962_ADCR_RETUNE_C22_0:
+ case WM8962_ADCR_RETUNE_C23_1:
+ case WM8962_ADCR_RETUNE_C23_0:
+ case WM8962_ADCR_RETUNE_C24_1:
+ case WM8962_ADCR_RETUNE_C24_0:
+ case WM8962_ADCR_RETUNE_C25_1:
+ case WM8962_ADCR_RETUNE_C25_0:
+ case WM8962_ADCR_RETUNE_C26_1:
+ case WM8962_ADCR_RETUNE_C26_0:
+ case WM8962_ADCR_RETUNE_C27_1:
+ case WM8962_ADCR_RETUNE_C27_0:
+ case WM8962_ADCR_RETUNE_C28_1:
+ case WM8962_ADCR_RETUNE_C28_0:
+ case WM8962_ADCR_RETUNE_C29_1:
+ case WM8962_ADCR_RETUNE_C29_0:
+ case WM8962_ADCR_RETUNE_C30_1:
+ case WM8962_ADCR_RETUNE_C30_0:
+ case WM8962_ADCR_RETUNE_C31_1:
+ case WM8962_ADCR_RETUNE_C31_0:
+ case WM8962_ADCR_RETUNE_C32_1:
+ case WM8962_ADCR_RETUNE_C32_0:
+ case WM8962_DACL_RETUNE_C1_1:
+ case WM8962_DACL_RETUNE_C1_0:
+ case WM8962_DACL_RETUNE_C2_1:
+ case WM8962_DACL_RETUNE_C2_0:
+ case WM8962_DACL_RETUNE_C3_1:
+ case WM8962_DACL_RETUNE_C3_0:
+ case WM8962_DACL_RETUNE_C4_1:
+ case WM8962_DACL_RETUNE_C4_0:
+ case WM8962_DACL_RETUNE_C5_1:
+ case WM8962_DACL_RETUNE_C5_0:
+ case WM8962_DACL_RETUNE_C6_1:
+ case WM8962_DACL_RETUNE_C6_0:
+ case WM8962_DACL_RETUNE_C7_1:
+ case WM8962_DACL_RETUNE_C7_0:
+ case WM8962_DACL_RETUNE_C8_1:
+ case WM8962_DACL_RETUNE_C8_0:
+ case WM8962_DACL_RETUNE_C9_1:
+ case WM8962_DACL_RETUNE_C9_0:
+ case WM8962_DACL_RETUNE_C10_1:
+ case WM8962_DACL_RETUNE_C10_0:
+ case WM8962_DACL_RETUNE_C11_1:
+ case WM8962_DACL_RETUNE_C11_0:
+ case WM8962_DACL_RETUNE_C12_1:
+ case WM8962_DACL_RETUNE_C12_0:
+ case WM8962_DACL_RETUNE_C13_1:
+ case WM8962_DACL_RETUNE_C13_0:
+ case WM8962_DACL_RETUNE_C14_1:
+ case WM8962_DACL_RETUNE_C14_0:
+ case WM8962_DACL_RETUNE_C15_1:
+ case WM8962_DACL_RETUNE_C15_0:
+ case WM8962_DACL_RETUNE_C16_1:
+ case WM8962_DACL_RETUNE_C16_0:
+ case WM8962_DACL_RETUNE_C17_1:
+ case WM8962_DACL_RETUNE_C17_0:
+ case WM8962_DACL_RETUNE_C18_1:
+ case WM8962_DACL_RETUNE_C18_0:
+ case WM8962_DACL_RETUNE_C19_1:
+ case WM8962_DACL_RETUNE_C19_0:
+ case WM8962_DACL_RETUNE_C20_1:
+ case WM8962_DACL_RETUNE_C20_0:
+ case WM8962_DACL_RETUNE_C21_1:
+ case WM8962_DACL_RETUNE_C21_0:
+ case WM8962_DACL_RETUNE_C22_1:
+ case WM8962_DACL_RETUNE_C22_0:
+ case WM8962_DACL_RETUNE_C23_1:
+ case WM8962_DACL_RETUNE_C23_0:
+ case WM8962_DACL_RETUNE_C24_1:
+ case WM8962_DACL_RETUNE_C24_0:
+ case WM8962_DACL_RETUNE_C25_1:
+ case WM8962_DACL_RETUNE_C25_0:
+ case WM8962_DACL_RETUNE_C26_1:
+ case WM8962_DACL_RETUNE_C26_0:
+ case WM8962_DACL_RETUNE_C27_1:
+ case WM8962_DACL_RETUNE_C27_0:
+ case WM8962_DACL_RETUNE_C28_1:
+ case WM8962_DACL_RETUNE_C28_0:
+ case WM8962_DACL_RETUNE_C29_1:
+ case WM8962_DACL_RETUNE_C29_0:
+ case WM8962_DACL_RETUNE_C30_1:
+ case WM8962_DACL_RETUNE_C30_0:
+ case WM8962_DACL_RETUNE_C31_1:
+ case WM8962_DACL_RETUNE_C31_0:
+ case WM8962_DACL_RETUNE_C32_1:
+ case WM8962_DACL_RETUNE_C32_0:
+ case WM8962_RETUNEDAC_PG2_1:
+ case WM8962_RETUNEDAC_PG2_0:
+ case WM8962_RETUNEDAC_PG_1:
+ case WM8962_RETUNEDAC_PG_0:
+ case WM8962_DACR_RETUNE_C1_1:
+ case WM8962_DACR_RETUNE_C1_0:
+ case WM8962_DACR_RETUNE_C2_1:
+ case WM8962_DACR_RETUNE_C2_0:
+ case WM8962_DACR_RETUNE_C3_1:
+ case WM8962_DACR_RETUNE_C3_0:
+ case WM8962_DACR_RETUNE_C4_1:
+ case WM8962_DACR_RETUNE_C4_0:
+ case WM8962_DACR_RETUNE_C5_1:
+ case WM8962_DACR_RETUNE_C5_0:
+ case WM8962_DACR_RETUNE_C6_1:
+ case WM8962_DACR_RETUNE_C6_0:
+ case WM8962_DACR_RETUNE_C7_1:
+ case WM8962_DACR_RETUNE_C7_0:
+ case WM8962_DACR_RETUNE_C8_1:
+ case WM8962_DACR_RETUNE_C8_0:
+ case WM8962_DACR_RETUNE_C9_1:
+ case WM8962_DACR_RETUNE_C9_0:
+ case WM8962_DACR_RETUNE_C10_1:
+ case WM8962_DACR_RETUNE_C10_0:
+ case WM8962_DACR_RETUNE_C11_1:
+ case WM8962_DACR_RETUNE_C11_0:
+ case WM8962_DACR_RETUNE_C12_1:
+ case WM8962_DACR_RETUNE_C12_0:
+ case WM8962_DACR_RETUNE_C13_1:
+ case WM8962_DACR_RETUNE_C13_0:
+ case WM8962_DACR_RETUNE_C14_1:
+ case WM8962_DACR_RETUNE_C14_0:
+ case WM8962_DACR_RETUNE_C15_1:
+ case WM8962_DACR_RETUNE_C15_0:
+ case WM8962_DACR_RETUNE_C16_1:
+ case WM8962_DACR_RETUNE_C16_0:
+ case WM8962_DACR_RETUNE_C17_1:
+ case WM8962_DACR_RETUNE_C17_0:
+ case WM8962_DACR_RETUNE_C18_1:
+ case WM8962_DACR_RETUNE_C18_0:
+ case WM8962_DACR_RETUNE_C19_1:
+ case WM8962_DACR_RETUNE_C19_0:
+ case WM8962_DACR_RETUNE_C20_1:
+ case WM8962_DACR_RETUNE_C20_0:
+ case WM8962_DACR_RETUNE_C21_1:
+ case WM8962_DACR_RETUNE_C21_0:
+ case WM8962_DACR_RETUNE_C22_1:
+ case WM8962_DACR_RETUNE_C22_0:
+ case WM8962_DACR_RETUNE_C23_1:
+ case WM8962_DACR_RETUNE_C23_0:
+ case WM8962_DACR_RETUNE_C24_1:
+ case WM8962_DACR_RETUNE_C24_0:
+ case WM8962_DACR_RETUNE_C25_1:
+ case WM8962_DACR_RETUNE_C25_0:
+ case WM8962_DACR_RETUNE_C26_1:
+ case WM8962_DACR_RETUNE_C26_0:
+ case WM8962_DACR_RETUNE_C27_1:
+ case WM8962_DACR_RETUNE_C27_0:
+ case WM8962_DACR_RETUNE_C28_1:
+ case WM8962_DACR_RETUNE_C28_0:
+ case WM8962_DACR_RETUNE_C29_1:
+ case WM8962_DACR_RETUNE_C29_0:
+ case WM8962_DACR_RETUNE_C30_1:
+ case WM8962_DACR_RETUNE_C30_0:
+ case WM8962_DACR_RETUNE_C31_1:
+ case WM8962_DACR_RETUNE_C31_0:
+ case WM8962_DACR_RETUNE_C32_1:
+ case WM8962_DACR_RETUNE_C32_0:
+ case WM8962_VSS_XHD2_1:
+ case WM8962_VSS_XHD2_0:
+ case WM8962_VSS_XHD3_1:
+ case WM8962_VSS_XHD3_0:
+ case WM8962_VSS_XHN1_1:
+ case WM8962_VSS_XHN1_0:
+ case WM8962_VSS_XHN2_1:
+ case WM8962_VSS_XHN2_0:
+ case WM8962_VSS_XHN3_1:
+ case WM8962_VSS_XHN3_0:
+ case WM8962_VSS_XLA_1:
+ case WM8962_VSS_XLA_0:
+ case WM8962_VSS_XLB_1:
+ case WM8962_VSS_XLB_0:
+ case WM8962_VSS_XLG_1:
+ case WM8962_VSS_XLG_0:
+ case WM8962_VSS_PG2_1:
+ case WM8962_VSS_PG2_0:
+ case WM8962_VSS_PG_1:
+ case WM8962_VSS_PG_0:
+ case WM8962_VSS_XTD1_1:
+ case WM8962_VSS_XTD1_0:
+ case WM8962_VSS_XTD2_1:
+ case WM8962_VSS_XTD2_0:
+ case WM8962_VSS_XTD3_1:
+ case WM8962_VSS_XTD3_0:
+ case WM8962_VSS_XTD4_1:
+ case WM8962_VSS_XTD4_0:
+ case WM8962_VSS_XTD5_1:
+ case WM8962_VSS_XTD5_0:
+ case WM8962_VSS_XTD6_1:
+ case WM8962_VSS_XTD6_0:
+ case WM8962_VSS_XTD7_1:
+ case WM8962_VSS_XTD7_0:
+ case WM8962_VSS_XTD8_1:
+ case WM8962_VSS_XTD8_0:
+ case WM8962_VSS_XTD9_1:
+ case WM8962_VSS_XTD9_0:
+ case WM8962_VSS_XTD10_1:
+ case WM8962_VSS_XTD10_0:
+ case WM8962_VSS_XTD11_1:
+ case WM8962_VSS_XTD11_0:
+ case WM8962_VSS_XTD12_1:
+ case WM8962_VSS_XTD12_0:
+ case WM8962_VSS_XTD13_1:
+ case WM8962_VSS_XTD13_0:
+ case WM8962_VSS_XTD14_1:
+ case WM8962_VSS_XTD14_0:
+ case WM8962_VSS_XTD15_1:
+ case WM8962_VSS_XTD15_0:
+ case WM8962_VSS_XTD16_1:
+ case WM8962_VSS_XTD16_0:
+ case WM8962_VSS_XTD17_1:
+ case WM8962_VSS_XTD17_0:
+ case WM8962_VSS_XTD18_1:
+ case WM8962_VSS_XTD18_0:
+ case WM8962_VSS_XTD19_1:
+ case WM8962_VSS_XTD19_0:
+ case WM8962_VSS_XTD20_1:
+ case WM8962_VSS_XTD20_0:
+ case WM8962_VSS_XTD21_1:
+ case WM8962_VSS_XTD21_0:
+ case WM8962_VSS_XTD22_1:
+ case WM8962_VSS_XTD22_0:
+ case WM8962_VSS_XTD23_1:
+ case WM8962_VSS_XTD23_0:
+ case WM8962_VSS_XTD24_1:
+ case WM8962_VSS_XTD24_0:
+ case WM8962_VSS_XTD25_1:
+ case WM8962_VSS_XTD25_0:
+ case WM8962_VSS_XTD26_1:
+ case WM8962_VSS_XTD26_0:
+ case WM8962_VSS_XTD27_1:
+ case WM8962_VSS_XTD27_0:
+ case WM8962_VSS_XTD28_1:
+ case WM8962_VSS_XTD28_0:
+ case WM8962_VSS_XTD29_1:
+ case WM8962_VSS_XTD29_0:
+ case WM8962_VSS_XTD30_1:
+ case WM8962_VSS_XTD30_0:
+ case WM8962_VSS_XTD31_1:
+ case WM8962_VSS_XTD31_0:
+ case WM8962_VSS_XTD32_1:
+ case WM8962_VSS_XTD32_0:
+ case WM8962_VSS_XTS1_1:
+ case WM8962_VSS_XTS1_0:
+ case WM8962_VSS_XTS2_1:
+ case WM8962_VSS_XTS2_0:
+ case WM8962_VSS_XTS3_1:
+ case WM8962_VSS_XTS3_0:
+ case WM8962_VSS_XTS4_1:
+ case WM8962_VSS_XTS4_0:
+ case WM8962_VSS_XTS5_1:
+ case WM8962_VSS_XTS5_0:
+ case WM8962_VSS_XTS6_1:
+ case WM8962_VSS_XTS6_0:
+ case WM8962_VSS_XTS7_1:
+ case WM8962_VSS_XTS7_0:
+ case WM8962_VSS_XTS8_1:
+ case WM8962_VSS_XTS8_0:
+ case WM8962_VSS_XTS9_1:
+ case WM8962_VSS_XTS9_0:
+ case WM8962_VSS_XTS10_1:
+ case WM8962_VSS_XTS10_0:
+ case WM8962_VSS_XTS11_1:
+ case WM8962_VSS_XTS11_0:
+ case WM8962_VSS_XTS12_1:
+ case WM8962_VSS_XTS12_0:
+ case WM8962_VSS_XTS13_1:
+ case WM8962_VSS_XTS13_0:
+ case WM8962_VSS_XTS14_1:
+ case WM8962_VSS_XTS14_0:
+ case WM8962_VSS_XTS15_1:
+ case WM8962_VSS_XTS15_0:
+ case WM8962_VSS_XTS16_1:
+ case WM8962_VSS_XTS16_0:
+ case WM8962_VSS_XTS17_1:
+ case WM8962_VSS_XTS17_0:
+ case WM8962_VSS_XTS18_1:
+ case WM8962_VSS_XTS18_0:
+ case WM8962_VSS_XTS19_1:
+ case WM8962_VSS_XTS19_0:
+ case WM8962_VSS_XTS20_1:
+ case WM8962_VSS_XTS20_0:
+ case WM8962_VSS_XTS21_1:
+ case WM8962_VSS_XTS21_0:
+ case WM8962_VSS_XTS22_1:
+ case WM8962_VSS_XTS22_0:
+ case WM8962_VSS_XTS23_1:
+ case WM8962_VSS_XTS23_0:
+ case WM8962_VSS_XTS24_1:
+ case WM8962_VSS_XTS24_0:
+ case WM8962_VSS_XTS25_1:
+ case WM8962_VSS_XTS25_0:
+ case WM8962_VSS_XTS26_1:
+ case WM8962_VSS_XTS26_0:
+ case WM8962_VSS_XTS27_1:
+ case WM8962_VSS_XTS27_0:
+ case WM8962_VSS_XTS28_1:
+ case WM8962_VSS_XTS28_0:
+ case WM8962_VSS_XTS29_1:
+ case WM8962_VSS_XTS29_0:
+ case WM8962_VSS_XTS30_1:
+ case WM8962_VSS_XTS30_0:
+ case WM8962_VSS_XTS31_1:
+ case WM8962_VSS_XTS31_0:
+ case WM8962_VSS_XTS32_1:
+ case WM8962_VSS_XTS32_0:
+ return true;
+ default:
+ return false;
+ }
}
static int wm8962_reset(struct wm8962_priv *wm8962)
@@ -2221,6 +1702,8 @@ SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
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("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0),
+SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0),
SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
5, 1, 0),
@@ -2337,65 +1820,6 @@ 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;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- unsigned long timeout;
- int src;
- int fll;
-
- /* Ignore attempts to run the event during startup */
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
- return 0;
-
- 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) {
- try_wait_for_completion(&wm8962->fll_lock);
-
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
- WM8962_FLL_ENA, WM8962_FLL_ENA);
-
- timeout = msecs_to_jiffies(5);
- timeout = wait_for_completion_timeout(&wm8962->fll_lock,
- timeout);
-
- if (wm8962->irq && timeout == 0)
- dev_err(codec->dev,
- "Timed out starting FLL\n");
- }
- 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)
{
@@ -2564,7 +1988,7 @@ static int dsp2_event(struct snd_soc_dapm_widget *w,
return 0;
}
-static const char *st_text[] = { "None", "Right", "Left" };
+static const char *st_text[] = { "None", "Left", "Right" };
static const struct soc_enum str_enum =
SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
@@ -2681,8 +2105,7 @@ SND_SOC_DAPM_INPUT("DMICDAT"),
SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 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("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0),
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),
@@ -2796,9 +2219,11 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "STL", "Left", "ADCL" },
{ "STL", "Right", "ADCR" },
+ { "STL", NULL, "Class G" },
{ "STR", "Left", "ADCL" },
{ "STR", "Right", "ADCR" },
+ { "STR", NULL, "Class G" },
{ "DACL", NULL, "SYSCLK" },
{ "DACL", NULL, "TOCLK" },
@@ -2910,13 +2335,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_add_controls(codec, wm8962_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8962_snd_controls,
ARRAY_SIZE(wm8962_snd_controls));
if (pdata && pdata->spk_mono)
- snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
ARRAY_SIZE(wm8962_spk_mono_controls));
else
- snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls,
ARRAY_SIZE(wm8962_spk_stereo_controls));
@@ -2950,7 +2375,7 @@ static const int bclk_divs[] = {
};
static const int sysclk_rates[] = {
- 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144
};
static void wm8962_configure_bclk(struct snd_soc_codec *codec)
@@ -2984,6 +2409,8 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
return;
}
+ dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
+
snd_soc_update_bits(codec, WM8962_CLOCKING_4,
WM8962_SYSCLK_RATE_MASK, clocking4);
@@ -3042,9 +2469,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
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->dapm.bias_level)
return 0;
@@ -3061,51 +2485,15 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.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;
- }
-
- regcache_cache_only(wm8962->regmap, false);
- regcache_sync(wm8962->regmap);
-
- 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);
- }
-
/* 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->dapm.bias_level = level;
return 0;
}
@@ -3139,6 +2527,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
int adctl3 = 0;
wm8962->bclk = snd_soc_params_to_bclk(params);
+ if (params_channels(params) == 1)
+ wm8962->bclk *= 2;
+
wm8962->lrclk = params_rate(params);
for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
@@ -3159,13 +2550,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
break;
case SNDRV_PCM_FORMAT_S20_3LE:
- aif0 |= 0x40;
+ aif0 |= 0x4;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- aif0 |= 0x80;
+ aif0 |= 0x8;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- aif0 |= 0xc0;
+ aif0 |= 0xc;
break;
default:
return -EINVAL;
@@ -3177,7 +2568,8 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
WM8962_SAMPLE_RATE_INT_MODE |
WM8962_SAMPLE_RATE_MASK, adctl3);
- wm8962_configure_bclk(codec);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ wm8962_configure_bclk(codec);
return 0;
}
@@ -3207,6 +2599,8 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
wm8962->sysclk_rate = freq;
+ wm8962_configure_bclk(codec);
+
return 0;
}
@@ -3385,8 +2779,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
struct _fll_div fll_div;
unsigned long timeout;
int ret;
- int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
- int sysclk = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_ENA;
+ int fll1 = 0;
/* Any change? */
if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3402,6 +2795,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, 0);
+ pm_runtime_put(codec->dev);
+
return 0;
}
@@ -3409,6 +2804,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (ret != 0)
return ret;
+ /* Parameters good, disable so we can reprogram */
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
switch (fll_id) {
case WM8962_FLL_MCLK:
case WM8962_FLL_BCLK:
@@ -3447,12 +2845,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
try_wait_for_completion(&wm8962->fll_lock);
- if (sysclk)
- fll1 |= WM8962_FLL_ENA;
+ pm_runtime_get_sync(codec->dev);
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
- WM8962_FLL_ENA, fll1);
+ WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA);
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
@@ -3513,14 +2910,14 @@ static struct snd_soc_dai_driver wm8962_dai = {
.name = "wm8962",
.playback = {
.stream_name = "Playback",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
},
.capture = {
.stream_name = "Capture",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
@@ -3561,54 +2958,73 @@ static void wm8962_mic_work(struct work_struct *work)
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;
- int reg;
+ struct device *dev = data;
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ unsigned int mask;
+ unsigned int active;
+ int reg, ret;
- mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt mask: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt: %d\n", ret);
+ return IRQ_NONE;
+ }
- active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
active &= ~mask;
if (!active)
return IRQ_NONE;
/* Acknowledge the interrupts */
- snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
+ if (ret != 0)
+ dev_warn(dev, "Failed to ack interrupt: %d\n", ret);
if (active & WM8962_FLL_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL locked\n");
+ dev_dbg(dev, "FLL locked\n");
complete(&wm8962->fll_lock);
}
if (active & WM8962_FIFOS_ERR_EINT)
- dev_err(codec->dev, "FIFO error\n");
+ dev_err(dev, "FIFO error\n");
if (active & WM8962_TEMP_SHUT_EINT) {
- dev_crit(codec->dev, "Thermal shutdown\n");
+ dev_crit(dev, "Thermal shutdown\n");
- reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS);
+ ret = regmap_read(wm8962->regmap,
+ WM8962_THERMAL_SHUTDOWN_STATUS, &reg);
+ if (ret != 0) {
+ dev_warn(dev, "Failed to read thermal status: %d\n",
+ ret);
+ reg = 0;
+ }
if (reg & WM8962_TEMP_ERR_HP)
- dev_crit(codec->dev, "Headphone thermal error\n");
+ dev_crit(dev, "Headphone thermal error\n");
if (reg & WM8962_TEMP_WARN_HP)
- dev_crit(codec->dev, "Headphone thermal warning\n");
+ dev_crit(dev, "Headphone thermal warning\n");
if (reg & WM8962_TEMP_ERR_SPK)
- dev_crit(codec->dev, "Speaker thermal error\n");
+ dev_crit(dev, "Speaker thermal error\n");
if (reg & WM8962_TEMP_WARN_SPK)
- dev_crit(codec->dev, "Speaker thermal warning\n");
+ dev_crit(dev, "Speaker thermal warning\n");
}
if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
- dev_dbg(codec->dev, "Microphone event detected\n");
+ dev_dbg(dev, "Microphone event detected\n");
#ifndef CONFIG_SND_SOC_WM8962_MODULE
- trace_snd_soc_jack_irq(dev_name(codec->dev));
+ trace_snd_soc_jack_irq(dev_name(dev));
#endif
- pm_wakeup_event(codec->dev, 300);
+ pm_wakeup_event(dev, 300);
schedule_delayed_work(&wm8962->mic_work,
msecs_to_jiffies(250));
@@ -4089,7 +3505,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
trigger | IRQF_ONESHOT,
- "wm8962", codec);
+ "wm8962", codec->dev);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
wm8962->irq, ret);
@@ -4127,20 +3543,19 @@ static int wm8962_remove(struct snd_soc_codec *codec)
return 0;
}
-static int wm8962_soc_volatile(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
-
static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
.probe = wm8962_probe,
.remove = wm8962_remove,
.set_bias_level = wm8962_set_bias_level,
.set_pll = wm8962_set_fll,
- .reg_cache_size = WM8962_MAX_REGISTER,
- .volatile_register = wm8962_soc_volatile,
+ .idle_bias_off = true,
+};
+
+/* Improve power consumption for IN4 DC measurement mode */
+static const struct reg_default wm8962_dc_measure[] = {
+ { 0xfd, 0x1 },
+ { 0xcc, 0x40 },
+ { 0xfd, 0 },
};
static const struct regmap_config wm8962_regmap = {
@@ -4155,10 +3570,10 @@ static const struct regmap_config wm8962_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-#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_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm8962_priv *wm8962;
unsigned int reg;
int ret, i;
@@ -4212,7 +3627,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
}
if (reg != 0x6243) {
dev_err(&i2c->dev,
- "Device is not a WM8962, ID %x != 0x6243\n", ret);
+ "Device is not a WM8962, ID %x != 0x6243\n", reg);
ret = -EINVAL;
goto err_regmap;
}
@@ -4237,7 +3652,18 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
goto err_regmap;
}
- regcache_cache_only(wm8962->regmap, true);
+ if (pdata && pdata->in4_dc_measure) {
+ ret = regmap_register_patch(wm8962->regmap,
+ wm8962_dc_measure,
+ ARRAY_SIZE(wm8962_dc_measure));
+ if (ret != 0)
+ dev_err(&i2c->dev,
+ "Failed to configure for DC mesurement: %d\n",
+ ret);
+ }
+
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
@@ -4269,6 +3695,65 @@ static __devexit int wm8962_i2c_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int wm8962_runtime_resume(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(dev,
+ "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(wm8962->regmap, false);
+ regcache_sync(wm8962->regmap);
+
+ regmap_update_bits(wm8962->regmap, 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 */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA,
+ WM8962_BIAS_ENA | 0x180);
+
+ msleep(5);
+
+ /* VMID back to 2x250k for standby */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK, 0x100);
+
+ return 0;
+}
+
+static int wm8962_runtime_suspend(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+ regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA, 0);
+
+ regcache_cache_only(wm8962->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm8962_pm = {
+ SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+};
+
static const struct i2c_device_id wm8962_i2c_id[] = {
{ "wm8962", 0 },
{ }
@@ -4279,34 +3764,14 @@ static struct i2c_driver wm8962_i2c_driver = {
.driver = {
.name = "wm8962",
.owner = THIS_MODULE,
+ .pm = &wm8962_pm,
},
.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_i2c_driver(wm8962_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8962 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 4af893601f00..28fe59e3ce01 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -252,7 +252,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MIC"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8971_dapm_routes[] = {
/* left mixer */
{"Left Mixer", "Playback Switch", "Left DAC"},
{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -329,17 +329,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Right ADC", NULL, "Right ADC Mux"},
};
-static int wm8971_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8971_dapm_widgets,
- ARRAY_SIZE(wm8971_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct _coeff_div {
u32 mclk;
u32 rate;
@@ -659,10 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
- snd_soc_add_controls(codec, wm8971_snd_controls,
- ARRAY_SIZE(wm8971_snd_controls));
- wm8971_add_widgets(codec);
-
return ret;
}
@@ -686,16 +671,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.reg_cache_size = ARRAY_SIZE(wm8971_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8971_reg,
+
+ .controls = wm8971_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8971_snd_controls),
+ .dapm_widgets = wm8971_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets),
+ .dapm_routes = wm8971_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
};
-#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 wm8971_priv *wm8971;
int ret;
- wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+ wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
+ GFP_KERNEL);
if (wm8971 == NULL)
return -ENOMEM;
@@ -704,15 +696,13 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8971, &wm8971_dai, 1);
- if (ret < 0)
- kfree(wm8971);
+
return ret;
}
static __devexit int wm8971_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -731,27 +721,22 @@ static struct i2c_driver wm8971_i2c_driver = {
.remove = __devexit_p(wm8971_i2c_remove),
.id_table = wm8971_i2c_id,
};
-#endif
static int __init wm8971_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8971_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8971_modinit);
static void __exit wm8971_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8971_i2c_driver);
-#endif
}
module_exit(wm8971_exit);
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 4a6a7b5a61ba..d93c03f820c9 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -48,10 +48,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
#define WM8974_POWER1_BIASEN 0x08
#define WM8974_POWER1_BUFIOEN 0x04
-struct wm8974_priv {
- enum snd_soc_control_type control_type;
-};
-
#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -235,7 +231,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8974_dapm_routes[] = {
/* Mono output mixer */
{"Mono Mixer", "PCM Playback Switch", "DAC"},
{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -269,17 +265,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Aux Input", NULL, "AUX"},
};
-static int wm8974_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8974_dapm_widgets,
- ARRAY_SIZE(wm8974_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct pll_ {
unsigned int pre_div:1;
unsigned int n:4;
@@ -611,9 +596,6 @@ static int wm8974_probe(struct snd_soc_codec *codec)
}
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;
}
@@ -634,32 +616,30 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.reg_cache_size = ARRAY_SIZE(wm8974_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8974_reg,
+
+ .controls = wm8974_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8974_snd_controls),
+ .dapm_widgets = wm8974_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets),
+ .dapm_routes = wm8974_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
};
-#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;
int ret;
- wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
- if (wm8974 == NULL)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, 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)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
@@ -678,27 +658,22 @@ static struct i2c_driver wm8974_i2c_driver = {
.remove = __devexit_p(wm8974_i2c_remove),
.id_table = wm8974_i2c_id,
};
-#endif
static int __init wm8974_modinit(void)
{
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);
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 85d514d63a4c..72d5fdcd3cc2 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -29,28 +30,74 @@
#include "wm8978.h"
-/* 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 */
- 0x0050, 0x0000, 0x0140, 0x0000, /* 0x04...0x07 */
- 0x0000, 0x0000, 0x0000, 0x00ff, /* 0x08...0x0b */
- 0x00ff, 0x0000, 0x0100, 0x00ff, /* 0x0c...0x0f */
- 0x00ff, 0x0000, 0x012c, 0x002c, /* 0x10...0x13 */
- 0x002c, 0x002c, 0x002c, 0x0000, /* 0x14...0x17 */
- 0x0032, 0x0000, 0x0000, 0x0000, /* 0x18...0x1b */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1c...0x1f */
- 0x0038, 0x000b, 0x0032, 0x0000, /* 0x20...0x23 */
- 0x0008, 0x000c, 0x0093, 0x00e9, /* 0x24...0x27 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 0x28...0x2b */
- 0x0033, 0x0010, 0x0010, 0x0100, /* 0x2c...0x2f */
- 0x0100, 0x0002, 0x0001, 0x0001, /* 0x30...0x33 */
- 0x0039, 0x0039, 0x0039, 0x0039, /* 0x34...0x37 */
- 0x0001, 0x0001, /* 0x38...0x3b */
+static const struct reg_default wm8978_reg_defaults[] = {
+ { 1, 0x0000 },
+ { 2, 0x0000 },
+ { 3, 0x0000 },
+ { 4, 0x0050 },
+ { 5, 0x0000 },
+ { 6, 0x0140 },
+ { 7, 0x0000 },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x0000 },
+ { 11, 0x00ff },
+ { 12, 0x00ff },
+ { 13, 0x0000 },
+ { 14, 0x0100 },
+ { 15, 0x00ff },
+ { 16, 0x00ff },
+ { 17, 0x0000 },
+ { 18, 0x012c },
+ { 19, 0x002c },
+ { 20, 0x002c },
+ { 21, 0x002c },
+ { 22, 0x002c },
+ { 23, 0x0000 },
+ { 24, 0x0032 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0038 },
+ { 33, 0x000b },
+ { 34, 0x0032 },
+ { 35, 0x0000 },
+ { 36, 0x0008 },
+ { 37, 0x000c },
+ { 38, 0x0093 },
+ { 39, 0x00e9 },
+ { 40, 0x0000 },
+ { 41, 0x0000 },
+ { 42, 0x0000 },
+ { 43, 0x0000 },
+ { 44, 0x0033 },
+ { 45, 0x0010 },
+ { 46, 0x0010 },
+ { 47, 0x0100 },
+ { 48, 0x0100 },
+ { 49, 0x0002 },
+ { 50, 0x0001 },
+ { 51, 0x0001 },
+ { 52, 0x0039 },
+ { 53, 0x0039 },
+ { 54, 0x0039 },
+ { 55, 0x0039 },
+ { 56, 0x0001 },
+ { 57, 0x0001 },
};
+static bool wm8978_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8978_RESET;
+}
+
/* codec private data */
struct wm8978_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
unsigned int f_pllout;
unsigned int f_mclk;
unsigned int f_256fs;
@@ -303,7 +350,7 @@ static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("RSPK"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8978_dapm_routes[] = {
/* Output mixer */
{"Right Output Mixer", "PCM Playback Switch", "Right DAC"},
{"Right Output Mixer", "Aux Playback Switch", "RAUX"},
@@ -352,18 +399,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Left Input Mixer", "MicP Switch", "LMICP"},
};
-static int wm8978_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8978_dapm_widgets,
- ARRAY_SIZE(wm8978_dapm_widgets));
- /* set up the WM8978 audio map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
/* PLL divisors */
struct wm8978_pll_div {
u32 k;
@@ -894,26 +929,23 @@ static struct snd_soc_dai_driver wm8978_dai = {
static int wm8978_suspend(struct snd_soc_codec *codec)
{
+ struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+
wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
/* Also switch PLL off */
snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
+ regcache_mark_dirty(wm8978->regmap);
+
return 0;
}
static int wm8978_resume(struct snd_soc_codec *codec)
{
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
- int i;
- u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
- if (i == WM8978_RESET)
- continue;
- if (cache[i] != wm8978_reg[i])
- snd_soc_write(codec, i, cache[i]);
- }
+ regcache_sync(wm8978->regmap);
wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -953,7 +985,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
* default hardware setting
*/
wm8978->sysclk = WM8978_PLL;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+ codec->control_data = wm8978->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -967,19 +1000,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(update_reg); i++)
snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
- /* Reset the codec */
- ret = snd_soc_write(codec, WM8978_RESET, 0);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- return ret;
- }
-
wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8978_snd_controls,
- ARRAY_SIZE(wm8978_snd_controls));
- wm8978_add_widgets(codec);
-
return 0;
}
@@ -996,35 +1018,75 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
.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,
+
+ .controls = wm8978_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8978_snd_controls),
+ .dapm_widgets = wm8978_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets),
+ .dapm_routes = wm8978_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
+};
+
+static const struct regmap_config wm8978_regmap_config = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8978_MAX_REGISTER,
+ .volatile_reg = wm8978_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8978_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8978_priv *wm8978;
int ret;
- wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
+ wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv),
+ GFP_KERNEL);
if (wm8978 == NULL)
return -ENOMEM;
+ wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+ if (IS_ERR(wm8978->regmap)) {
+ ret = PTR_ERR(wm8978->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8978);
+ /* Reset the codec */
+ ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+ goto err;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8978, &wm8978_dai, 1);
- if (ret < 0)
- kfree(wm8978);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regmap_exit(wm8978->regmap);
return ret;
}
static __devexit int wm8978_i2c_remove(struct i2c_client *client)
{
+ struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8978->regmap);
+
return 0;
}
@@ -1043,27 +1105,22 @@ static struct i2c_driver wm8978_i2c_driver = {
.remove = __devexit_p(wm8978_i2c_remove),
.id_table = wm8978_i2c_id,
};
-#endif
static int __init wm8978_modinit(void)
{
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);
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index c75525b7f154..6ae43495b7cf 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -67,6 +67,8 @@
#define WM8978_OUT3_MIXER_CONTROL 0x38
#define WM8978_OUT4_MIXER_CONTROL 0x39
+#define WM8978_MAX_REGISTER 0x39
+
#define WM8978_CACHEREGNUM 58
/* Clock divider Id's */
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index cebde568d191..367388fdc486 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -249,9 +249,6 @@ static const char *eq5_cutoff_text[] = {
static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_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%",
@@ -369,8 +366,6 @@ static const struct snd_kcontrol_new wm8983_snd_controls[] = {
SOC_SINGLE_TLV("EQ5 Volume", WM8983_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[] = {
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index c0c86b3c6adf..14f666398d0c 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -39,73 +40,127 @@ static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
"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 */
+static const struct reg_default wm8985_reg_defaults[] = {
+ { 1, 0x0000 }, /* R1 - Power management 1 */
+ { 2, 0x0000 }, /* R2 - Power management 2 */
+ { 3, 0x0000 }, /* R3 - Power management 3 */
+ { 4, 0x0050 }, /* R4 - Audio Interface */
+ { 5, 0x0000 }, /* R5 - Companding control */
+ { 6, 0x0140 }, /* R6 - Clock Gen control */
+ { 7, 0x0000 }, /* R7 - Additional control */
+ { 8, 0x0000 }, /* R8 - GPIO Control */
+ { 9, 0x0000 }, /* R9 - Jack Detect Control 1 */
+ { 10, 0x0000 }, /* R10 - DAC Control */
+ { 11, 0x00FF }, /* R11 - Left DAC digital Vol */
+ { 12, 0x00FF }, /* R12 - Right DAC digital vol */
+ { 13, 0x0000 }, /* R13 - Jack Detect Control 2 */
+ { 14, 0x0100 }, /* R14 - ADC Control */
+ { 15, 0x00FF }, /* R15 - Left ADC Digital Vol */
+ { 16, 0x00FF }, /* R16 - Right ADC Digital Vol */
+ { 18, 0x012C }, /* R18 - EQ1 - low shelf */
+ { 19, 0x002C }, /* R19 - EQ2 - peak 1 */
+ { 20, 0x002C }, /* R20 - EQ3 - peak 2 */
+ { 21, 0x002C }, /* R21 - EQ4 - peak 3 */
+ { 22, 0x002C }, /* R22 - EQ5 - high shelf */
+ { 24, 0x0032 }, /* R24 - DAC Limiter 1 */
+ { 25, 0x0000 }, /* R25 - DAC Limiter 2 */
+ { 27, 0x0000 }, /* R27 - Notch Filter 1 */
+ { 28, 0x0000 }, /* R28 - Notch Filter 2 */
+ { 29, 0x0000 }, /* R29 - Notch Filter 3 */
+ { 30, 0x0000 }, /* R30 - Notch Filter 4 */
+ { 32, 0x0038 }, /* R32 - ALC control 1 */
+ { 33, 0x000B }, /* R33 - ALC control 2 */
+ { 34, 0x0032 }, /* R34 - ALC control 3 */
+ { 35, 0x0000 }, /* R35 - Noise Gate */
+ { 36, 0x0008 }, /* R36 - PLL N */
+ { 37, 0x000C }, /* R37 - PLL K 1 */
+ { 38, 0x0093 }, /* R38 - PLL K 2 */
+ { 39, 0x00E9 }, /* R39 - PLL K 3 */
+ { 41, 0x0000 }, /* R41 - 3D control */
+ { 42, 0x0000 }, /* R42 - OUT4 to ADC */
+ { 43, 0x0000 }, /* R43 - Beep control */
+ { 44, 0x0033 }, /* R44 - Input ctrl */
+ { 45, 0x0010 }, /* R45 - Left INP PGA gain ctrl */
+ { 46, 0x0010 }, /* R46 - Right INP PGA gain ctrl */
+ { 47, 0x0100 }, /* R47 - Left ADC BOOST ctrl */
+ { 48, 0x0100 }, /* R48 - Right ADC BOOST ctrl */
+ { 49, 0x0002 }, /* R49 - Output ctrl */
+ { 50, 0x0001 }, /* R50 - Left mixer ctrl */
+ { 51, 0x0001 }, /* R51 - Right mixer ctrl */
+ { 52, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */
+ { 53, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */
+ { 54, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */
+ { 55, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */
+ { 56, 0x0001 }, /* R56 - OUT3 mixer ctrl */
+ { 57, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */
+ { 60, 0x0004 }, /* R60 - OUTPUT ctrl */
+ { 61, 0x0000 }, /* R61 - BIAS CTRL */
};
+static bool wm8985_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8985_SOFTWARE_RESET:
+ case WM8985_POWER_MANAGEMENT_1:
+ case WM8985_POWER_MANAGEMENT_2:
+ case WM8985_POWER_MANAGEMENT_3:
+ case WM8985_AUDIO_INTERFACE:
+ case WM8985_COMPANDING_CONTROL:
+ case WM8985_CLOCK_GEN_CONTROL:
+ case WM8985_ADDITIONAL_CONTROL:
+ case WM8985_GPIO_CONTROL:
+ case WM8985_JACK_DETECT_CONTROL_1:
+ case WM8985_DAC_CONTROL:
+ case WM8985_LEFT_DAC_DIGITAL_VOL:
+ case WM8985_RIGHT_DAC_DIGITAL_VOL:
+ case WM8985_JACK_DETECT_CONTROL_2:
+ case WM8985_ADC_CONTROL:
+ case WM8985_LEFT_ADC_DIGITAL_VOL:
+ case WM8985_RIGHT_ADC_DIGITAL_VOL:
+ case WM8985_EQ1_LOW_SHELF:
+ case WM8985_EQ2_PEAK_1:
+ case WM8985_EQ3_PEAK_2:
+ case WM8985_EQ4_PEAK_3:
+ case WM8985_EQ5_HIGH_SHELF:
+ case WM8985_DAC_LIMITER_1:
+ case WM8985_DAC_LIMITER_2:
+ case WM8985_NOTCH_FILTER_1:
+ case WM8985_NOTCH_FILTER_2:
+ case WM8985_NOTCH_FILTER_3:
+ case WM8985_NOTCH_FILTER_4:
+ case WM8985_ALC_CONTROL_1:
+ case WM8985_ALC_CONTROL_2:
+ case WM8985_ALC_CONTROL_3:
+ case WM8985_NOISE_GATE:
+ case WM8985_PLL_N:
+ case WM8985_PLL_K_1:
+ case WM8985_PLL_K_2:
+ case WM8985_PLL_K_3:
+ case WM8985_3D_CONTROL:
+ case WM8985_OUT4_TO_ADC:
+ case WM8985_BEEP_CONTROL:
+ case WM8985_INPUT_CTRL:
+ case WM8985_LEFT_INP_PGA_GAIN_CTRL:
+ case WM8985_RIGHT_INP_PGA_GAIN_CTRL:
+ case WM8985_LEFT_ADC_BOOST_CTRL:
+ case WM8985_RIGHT_ADC_BOOST_CTRL:
+ case WM8985_OUTPUT_CTRL0:
+ case WM8985_LEFT_MIXER_CTRL:
+ case WM8985_RIGHT_MIXER_CTRL:
+ case WM8985_LOUT1_HP_VOLUME_CTRL:
+ case WM8985_ROUT1_HP_VOLUME_CTRL:
+ case WM8985_LOUT2_SPK_VOLUME_CTRL:
+ case WM8985_ROUT2_SPK_VOLUME_CTRL:
+ case WM8985_OUT3_MIXER_CTRL:
+ case WM8985_OUT4_MONO_MIX_CTRL:
+ case WM8985_OUTPUT_CTRL1:
+ case WM8985_BIAS_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* latch bit 8 of these registers to ensure instant
* volume updates
@@ -124,7 +179,7 @@ static const int volume_update_regs[] = {
};
struct wm8985_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
unsigned int sysclk;
unsigned int bclk;
@@ -428,7 +483,7 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("SPKR")
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
{ "Right Output Mixer", "PCM Switch", "Right DAC" },
{ "Right Output Mixer", "Aux Switch", "AUXR" },
{ "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
@@ -531,17 +586,6 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int wm8985_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8985_dapm_widgets,
- ARRAY_SIZE(wm8985_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, 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);
@@ -845,25 +889,6 @@ static int wm8985_set_sysclk(struct snd_soc_dai *dai,
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)
{
@@ -890,7 +915,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- wm8985_sync_cache(codec);
+ regcache_sync(wm8985->regmap);
/* enable anti-pop features */
snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
@@ -933,7 +958,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
- codec->cache_sync = 1;
+ regcache_mark_dirty(wm8985->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
wm8985->supplies);
@@ -976,11 +1001,11 @@ 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);
+ codec->control_data = wm8985->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
return ret;
@@ -1009,17 +1034,13 @@ static int wm8985_probe(struct snd_soc_codec *codec)
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;
+ snd_soc_update_bits(codec, volume_update_regs[i],
+ 0x100, 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);
+ snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT,
+ WM8985_BIASCUT);
wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -1068,9 +1089,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
.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
+
+ .controls = wm8985_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8985_snd_controls),
+ .dapm_widgets = wm8985_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets),
+ .dapm_routes = wm8985_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes),
+};
+
+static const struct regmap_config wm8985_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8985_MAX_REGISTER,
+ .writeable_reg = wm8985_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8985_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -1079,24 +1116,39 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
struct wm8985_priv *wm8985;
int ret;
- wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ wm8985 = devm_kzalloc(&spi->dev, sizeof *wm8985, GFP_KERNEL);
if (!wm8985)
return -ENOMEM;
- wm8985->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, wm8985);
+ wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+ if (IS_ERR(wm8985->regmap)) {
+ ret = PTR_ERR(wm8985->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret < 0)
- kfree(wm8985);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8985->regmap);
return ret;
}
static int __devexit wm8985_spi_remove(struct spi_device *spi)
{
+ struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8985->regmap);
+
return 0;
}
@@ -1117,24 +1169,39 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
struct wm8985_priv *wm8985;
int ret;
- wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ wm8985 = devm_kzalloc(&i2c->dev, sizeof *wm8985, GFP_KERNEL);
if (!wm8985)
return -ENOMEM;
- wm8985->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, wm8985);
+ wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+ if (IS_ERR(wm8985->regmap)) {
+ ret = PTR_ERR(wm8985->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret < 0)
- kfree(wm8985);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8985->regmap);
return ret;
}
-static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm8985->regmap);
+
return 0;
}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index ab52963dd04c..6cdf6a2bc283 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -33,24 +33,89 @@
* We can't read the WM8988 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8988_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8988_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 5, 0x0008 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
+static bool wm8988_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8988_LINVOL:
+ case WM8988_RINVOL:
+ case WM8988_LOUT1V:
+ case WM8988_ROUT1V:
+ case WM8988_ADCDAC:
+ case WM8988_IFACE:
+ case WM8988_SRATE:
+ case WM8988_LDAC:
+ case WM8988_RDAC:
+ case WM8988_BASS:
+ case WM8988_TREBLE:
+ case WM8988_RESET:
+ case WM8988_3D:
+ case WM8988_ALC1:
+ case WM8988_ALC2:
+ case WM8988_ALC3:
+ case WM8988_NGATE:
+ case WM8988_LADC:
+ case WM8988_RADC:
+ case WM8988_ADCTL1:
+ case WM8988_ADCTL2:
+ case WM8988_PWR1:
+ case WM8988_PWR2:
+ case WM8988_ADCTL3:
+ case WM8988_ADCIN:
+ case WM8988_LADCIN:
+ case WM8988_RADCIN:
+ case WM8988_LOUTM1:
+ case WM8988_LOUTM2:
+ case WM8988_ROUTM1:
+ case WM8988_ROUTM2:
+ case WM8988_LOUT2V:
+ case WM8988_ROUT2V:
+ case WM8988_LPPB:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* codec private data */
struct wm8988_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
@@ -317,7 +382,7 @@ static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("RINPUT2"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {
{ "Left Line Mux", "Line 1", "LINPUT1" },
{ "Left Line Mux", "Line 2", "LINPUT2" },
@@ -661,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
static int wm8988_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
switch (level) {
@@ -674,7 +740,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- snd_soc_cache_sync(codec);
+ regcache_sync(wm8988->regmap);
/* VREF, VMID=2x5k */
snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -730,7 +796,10 @@ static struct snd_soc_dai_driver wm8988_dai = {
static int wm8988_suspend(struct snd_soc_codec *codec)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
+
wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_mark_dirty(wm8988->regmap);
return 0;
}
@@ -743,10 +812,10 @@ static int wm8988_resume(struct snd_soc_codec *codec)
static int wm8988_probe(struct snd_soc_codec *codec)
{
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
+ codec->control_data = wm8988->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -767,12 +836,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8988_snd_controls,
- ARRAY_SIZE(wm8988_snd_controls));
- snd_soc_dapm_new_controls(dapm, wm8988_dapm_widgets,
- ARRAY_SIZE(wm8988_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
return 0;
}
@@ -788,9 +851,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.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,
+
+ .controls = wm8988_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8988_snd_controls),
+ .dapm_widgets = wm8988_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
+ .dapm_routes = wm8988_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
+};
+
+static struct regmap_config wm8988_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8988_LPPB,
+ .writeable_reg = wm8988_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8988_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -799,24 +878,33 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
struct wm8988_priv *wm8988;
int ret;
- wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),
+ GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
- wm8988->control_type = SND_SOC_SPI;
+ wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
spi_set_drvdata(spi, wm8988);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret < 0)
- kfree(wm8988);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
+
return ret;
}
static int __devexit wm8988_spi_remove(struct spi_device *spi)
{
+ struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8988->regmap);
return 0;
}
@@ -837,24 +925,33 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
struct wm8988_priv *wm8988;
int ret;
- wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),
+ GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8988);
- wm8988->control_type = SND_SOC_I2C;
+
+ wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret < 0)
- kfree(wm8988);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
+
return ret;
}
static __devexit int wm8988_i2c_remove(struct i2c_client *client)
{
+ struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8988->regmap);
return 0;
}
@@ -866,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
static struct i2c_driver wm8988_i2c_driver = {
.driver = {
- .name = "wm8988-codec",
+ .name = "wm8988",
.owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index e538edaae1f0..9d242351e6e8 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1356,7 +1356,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8990_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8990_snd_controls,
ARRAY_SIZE(wm8990_snd_controls));
wm8990_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 7ee40da8dbb5..9ac31ba9b82e 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1297,7 +1297,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8991_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8991_snd_controls,
ARRAY_SIZE(wm8991_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 7c7fd925db8d..d256a9340644 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -40,134 +41,113 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = {
"SPKVDD",
};
-static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
- 0x8993, /* R0 - Software Reset */
- 0x0000, /* R1 - Power Management (1) */
- 0x6000, /* R2 - Power Management (2) */
- 0x0000, /* R3 - Power Management (3) */
- 0x4050, /* R4 - Audio Interface (1) */
- 0x4000, /* R5 - Audio Interface (2) */
- 0x01C8, /* R6 - Clocking 1 */
- 0x0000, /* R7 - Clocking 2 */
- 0x0000, /* R8 - Audio Interface (3) */
- 0x0040, /* R9 - Audio Interface (4) */
- 0x0004, /* R10 - DAC CTRL */
- 0x00C0, /* R11 - Left DAC Digital Volume */
- 0x00C0, /* R12 - Right DAC Digital Volume */
- 0x0000, /* R13 - Digital Side Tone */
- 0x0300, /* R14 - ADC CTRL */
- 0x00C0, /* R15 - Left ADC Digital Volume */
- 0x00C0, /* R16 - Right ADC Digital Volume */
- 0x0000, /* R17 */
- 0x0000, /* R18 - GPIO CTRL 1 */
- 0x0010, /* R19 - GPIO1 */
- 0x0000, /* R20 - IRQ_DEBOUNCE */
- 0x0000, /* R21 */
- 0x8000, /* R22 - GPIOCTRL 2 */
- 0x0800, /* R23 - GPIO_POL */
- 0x008B, /* R24 - Left Line Input 1&2 Volume */
- 0x008B, /* R25 - Left Line Input 3&4 Volume */
- 0x008B, /* R26 - Right Line Input 1&2 Volume */
- 0x008B, /* R27 - Right Line Input 3&4 Volume */
- 0x006D, /* R28 - Left Output Volume */
- 0x006D, /* R29 - Right Output Volume */
- 0x0066, /* R30 - Line Outputs Volume */
- 0x0020, /* R31 - HPOUT2 Volume */
- 0x0079, /* R32 - Left OPGA Volume */
- 0x0079, /* R33 - Right OPGA Volume */
- 0x0003, /* R34 - SPKMIXL Attenuation */
- 0x0003, /* R35 - SPKMIXR Attenuation */
- 0x0011, /* R36 - SPKOUT Mixers */
- 0x0100, /* R37 - SPKOUT Boost */
- 0x0079, /* R38 - Speaker Volume Left */
- 0x0079, /* R39 - Speaker Volume Right */
- 0x0000, /* R40 - Input Mixer2 */
- 0x0000, /* R41 - Input Mixer3 */
- 0x0000, /* R42 - Input Mixer4 */
- 0x0000, /* R43 - Input Mixer5 */
- 0x0000, /* R44 - Input Mixer6 */
- 0x0000, /* R45 - Output Mixer1 */
- 0x0000, /* R46 - Output Mixer2 */
- 0x0000, /* R47 - Output Mixer3 */
- 0x0000, /* R48 - Output Mixer4 */
- 0x0000, /* R49 - Output Mixer5 */
- 0x0000, /* R50 - Output Mixer6 */
- 0x0000, /* R51 - HPOUT2 Mixer */
- 0x0000, /* R52 - Line Mixer1 */
- 0x0000, /* R53 - Line Mixer2 */
- 0x0000, /* R54 - Speaker Mixer */
- 0x0000, /* R55 - Additional Control */
- 0x0000, /* R56 - AntiPOP1 */
- 0x0000, /* R57 - AntiPOP2 */
- 0x0000, /* R58 - MICBIAS */
- 0x0000, /* R59 */
- 0x0000, /* R60 - FLL Control 1 */
- 0x0000, /* R61 - FLL Control 2 */
- 0x0000, /* R62 - FLL Control 3 */
- 0x2EE0, /* R63 - FLL Control 4 */
- 0x0002, /* R64 - FLL Control 5 */
- 0x2287, /* R65 - Clocking 3 */
- 0x025F, /* R66 - Clocking 4 */
- 0x0000, /* R67 - MW Slave Control */
- 0x0000, /* R68 */
- 0x0002, /* R69 - Bus Control 1 */
- 0x0000, /* R70 - Write Sequencer 0 */
- 0x0000, /* R71 - Write Sequencer 1 */
- 0x0000, /* R72 - Write Sequencer 2 */
- 0x0000, /* R73 - Write Sequencer 3 */
- 0x0000, /* R74 - Write Sequencer 4 */
- 0x0000, /* R75 - Write Sequencer 5 */
- 0x1F25, /* R76 - Charge Pump 1 */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 - Class W 0 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 - DC Servo 0 */
- 0x054A, /* R85 - DC Servo 1 */
- 0x0000, /* R86 */
- 0x0000, /* R87 - DC Servo 3 */
- 0x0000, /* R88 - DC Servo Readback 0 */
- 0x0000, /* R89 - DC Servo Readback 1 */
- 0x0000, /* R90 - DC Servo Readback 2 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 */
- 0x0000, /* R95 */
- 0x0100, /* R96 - Analogue HP 0 */
- 0x0000, /* R97 */
- 0x0000, /* R98 - EQ1 */
- 0x000C, /* R99 - EQ2 */
- 0x000C, /* R100 - EQ3 */
- 0x000C, /* R101 - EQ4 */
- 0x000C, /* R102 - EQ5 */
- 0x000C, /* R103 - EQ6 */
- 0x0FCA, /* R104 - EQ7 */
- 0x0400, /* R105 - EQ8 */
- 0x00D8, /* R106 - EQ9 */
- 0x1EB5, /* R107 - EQ10 */
- 0xF145, /* R108 - EQ11 */
- 0x0B75, /* R109 - EQ12 */
- 0x01C5, /* R110 - EQ13 */
- 0x1C58, /* R111 - EQ14 */
- 0xF373, /* R112 - EQ15 */
- 0x0A54, /* R113 - EQ16 */
- 0x0558, /* R114 - EQ17 */
- 0x168E, /* R115 - EQ18 */
- 0xF829, /* R116 - EQ19 */
- 0x07AD, /* R117 - EQ20 */
- 0x1103, /* R118 - EQ21 */
- 0x0564, /* R119 - EQ22 */
- 0x0559, /* R120 - EQ23 */
- 0x4000, /* R121 - EQ24 */
- 0x0000, /* R122 - Digital Pulls */
- 0x0F08, /* R123 - DRC Control 1 */
- 0x0000, /* R124 - DRC Control 2 */
- 0x0080, /* R125 - DRC Control 3 */
- 0x0000, /* R126 - DRC Control 4 */
+static struct reg_default wm8993_reg_defaults[] = {
+ { 1, 0x0000 }, /* R1 - Power Management (1) */
+ { 2, 0x6000 }, /* R2 - Power Management (2) */
+ { 3, 0x0000 }, /* R3 - Power Management (3) */
+ { 4, 0x4050 }, /* R4 - Audio Interface (1) */
+ { 5, 0x4000 }, /* R5 - Audio Interface (2) */
+ { 6, 0x01C8 }, /* R6 - Clocking 1 */
+ { 7, 0x0000 }, /* R7 - Clocking 2 */
+ { 8, 0x0000 }, /* R8 - Audio Interface (3) */
+ { 9, 0x0040 }, /* R9 - Audio Interface (4) */
+ { 10, 0x0004 }, /* R10 - DAC CTRL */
+ { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */
+ { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */
+ { 13, 0x0000 }, /* R13 - Digital Side Tone */
+ { 14, 0x0300 }, /* R14 - ADC CTRL */
+ { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */
+ { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */
+ { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */
+ { 19, 0x0010 }, /* R19 - GPIO1 */
+ { 20, 0x0000 }, /* R20 - IRQ_DEBOUNCE */
+ { 21, 0x0000 }, /* R21 - Inputs Clamp */
+ { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */
+ { 23, 0x0800 }, /* R23 - GPIO_POL */
+ { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 28, 0x006D }, /* R28 - Left Output Volume */
+ { 29, 0x006D }, /* R29 - Right Output Volume */
+ { 30, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 31, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 32, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 33, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 34, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 35, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 36, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 37, 0x0100 }, /* R37 - SPKOUT Boost */
+ { 38, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 39, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 40, 0x0000 }, /* R40 - Input Mixer2 */
+ { 41, 0x0000 }, /* R41 - Input Mixer3 */
+ { 42, 0x0000 }, /* R42 - Input Mixer4 */
+ { 43, 0x0000 }, /* R43 - Input Mixer5 */
+ { 44, 0x0000 }, /* R44 - Input Mixer6 */
+ { 45, 0x0000 }, /* R45 - Output Mixer1 */
+ { 46, 0x0000 }, /* R46 - Output Mixer2 */
+ { 47, 0x0000 }, /* R47 - Output Mixer3 */
+ { 48, 0x0000 }, /* R48 - Output Mixer4 */
+ { 49, 0x0000 }, /* R49 - Output Mixer5 */
+ { 50, 0x0000 }, /* R50 - Output Mixer6 */
+ { 51, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 52, 0x0000 }, /* R52 - Line Mixer1 */
+ { 53, 0x0000 }, /* R53 - Line Mixer2 */
+ { 54, 0x0000 }, /* R54 - Speaker Mixer */
+ { 55, 0x0000 }, /* R55 - Additional Control */
+ { 56, 0x0000 }, /* R56 - AntiPOP1 */
+ { 57, 0x0000 }, /* R57 - AntiPOP2 */
+ { 58, 0x0000 }, /* R58 - MICBIAS */
+ { 60, 0x0000 }, /* R60 - FLL Control 1 */
+ { 61, 0x0000 }, /* R61 - FLL Control 2 */
+ { 62, 0x0000 }, /* R62 - FLL Control 3 */
+ { 63, 0x2EE0 }, /* R63 - FLL Control 4 */
+ { 64, 0x0002 }, /* R64 - FLL Control 5 */
+ { 65, 0x2287 }, /* R65 - Clocking 3 */
+ { 66, 0x025F }, /* R66 - Clocking 4 */
+ { 67, 0x0000 }, /* R67 - MW Slave Control */
+ { 69, 0x0002 }, /* R69 - Bus Control 1 */
+ { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
+ { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
+ { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
+ { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
+ { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
+ { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
+ { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
+ { 81, 0x0000 }, /* R81 - Class W 0 */
+ { 85, 0x054A }, /* R85 - DC Servo 1 */
+ { 87, 0x0000 }, /* R87 - DC Servo 3 */
+ { 96, 0x0100 }, /* R96 - Analogue HP 0 */
+ { 98, 0x0000 }, /* R98 - EQ1 */
+ { 99, 0x000C }, /* R99 - EQ2 */
+ { 100, 0x000C }, /* R100 - EQ3 */
+ { 101, 0x000C }, /* R101 - EQ4 */
+ { 102, 0x000C }, /* R102 - EQ5 */
+ { 103, 0x000C }, /* R103 - EQ6 */
+ { 104, 0x0FCA }, /* R104 - EQ7 */
+ { 105, 0x0400 }, /* R105 - EQ8 */
+ { 106, 0x00D8 }, /* R106 - EQ9 */
+ { 107, 0x1EB5 }, /* R107 - EQ10 */
+ { 108, 0xF145 }, /* R108 - EQ11 */
+ { 109, 0x0B75 }, /* R109 - EQ12 */
+ { 110, 0x01C5 }, /* R110 - EQ13 */
+ { 111, 0x1C58 }, /* R111 - EQ14 */
+ { 112, 0xF373 }, /* R112 - EQ15 */
+ { 113, 0x0A54 }, /* R113 - EQ16 */
+ { 114, 0x0558 }, /* R114 - EQ17 */
+ { 115, 0x168E }, /* R115 - EQ18 */
+ { 116, 0xF829 }, /* R116 - EQ19 */
+ { 117, 0x07AD }, /* R117 - EQ20 */
+ { 118, 0x1103 }, /* R118 - EQ21 */
+ { 119, 0x0564 }, /* R119 - EQ22 */
+ { 120, 0x0559 }, /* R120 - EQ23 */
+ { 121, 0x4000 }, /* R121 - EQ24 */
+ { 122, 0x0000 }, /* R122 - Digital Pulls */
+ { 123, 0x0F08 }, /* R123 - DRC Control 1 */
+ { 124, 0x0000 }, /* R124 - DRC Control 2 */
+ { 125, 0x0080 }, /* R125 - DRC Control 3 */
+ { 126, 0x0000 }, /* R126 - DRC Control 4 */
};
static struct {
@@ -225,9 +205,11 @@ static struct {
struct wm8993_priv {
struct wm_hubs_data hubs_data;
+ struct device *dev;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
struct wm8993_platform_data pdata;
- enum snd_soc_control_type control_type;
+ struct completion fll_lock;
int master;
int sysclk_source;
int tdm_slots;
@@ -242,17 +224,137 @@ struct wm8993_priv {
int fll_src;
};
-static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8993_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8993_SOFTWARE_RESET:
+ case WM8993_GPIO_CTRL_1:
case WM8993_DC_SERVO_0:
case WM8993_DC_SERVO_READBACK_0:
case WM8993_DC_SERVO_READBACK_1:
case WM8993_DC_SERVO_READBACK_2:
- return 1;
+ return true;
default:
- return 0;
+ return false;
+ }
+}
+
+static bool wm8993_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8993_SOFTWARE_RESET:
+ case WM8993_POWER_MANAGEMENT_1:
+ case WM8993_POWER_MANAGEMENT_2:
+ case WM8993_POWER_MANAGEMENT_3:
+ case WM8993_AUDIO_INTERFACE_1:
+ case WM8993_AUDIO_INTERFACE_2:
+ case WM8993_CLOCKING_1:
+ case WM8993_CLOCKING_2:
+ case WM8993_AUDIO_INTERFACE_3:
+ case WM8993_AUDIO_INTERFACE_4:
+ case WM8993_DAC_CTRL:
+ case WM8993_LEFT_DAC_DIGITAL_VOLUME:
+ case WM8993_RIGHT_DAC_DIGITAL_VOLUME:
+ case WM8993_DIGITAL_SIDE_TONE:
+ case WM8993_ADC_CTRL:
+ case WM8993_LEFT_ADC_DIGITAL_VOLUME:
+ case WM8993_RIGHT_ADC_DIGITAL_VOLUME:
+ case WM8993_GPIO_CTRL_1:
+ case WM8993_GPIO1:
+ case WM8993_IRQ_DEBOUNCE:
+ case WM8993_GPIOCTRL_2:
+ case WM8993_GPIO_POL:
+ case WM8993_LEFT_LINE_INPUT_1_2_VOLUME:
+ case WM8993_LEFT_LINE_INPUT_3_4_VOLUME:
+ case WM8993_RIGHT_LINE_INPUT_1_2_VOLUME:
+ case WM8993_RIGHT_LINE_INPUT_3_4_VOLUME:
+ case WM8993_LEFT_OUTPUT_VOLUME:
+ case WM8993_RIGHT_OUTPUT_VOLUME:
+ case WM8993_LINE_OUTPUTS_VOLUME:
+ case WM8993_HPOUT2_VOLUME:
+ case WM8993_LEFT_OPGA_VOLUME:
+ case WM8993_RIGHT_OPGA_VOLUME:
+ case WM8993_SPKMIXL_ATTENUATION:
+ case WM8993_SPKMIXR_ATTENUATION:
+ case WM8993_SPKOUT_MIXERS:
+ case WM8993_SPKOUT_BOOST:
+ case WM8993_SPEAKER_VOLUME_LEFT:
+ case WM8993_SPEAKER_VOLUME_RIGHT:
+ case WM8993_INPUT_MIXER2:
+ case WM8993_INPUT_MIXER3:
+ case WM8993_INPUT_MIXER4:
+ case WM8993_INPUT_MIXER5:
+ case WM8993_INPUT_MIXER6:
+ case WM8993_OUTPUT_MIXER1:
+ case WM8993_OUTPUT_MIXER2:
+ case WM8993_OUTPUT_MIXER3:
+ case WM8993_OUTPUT_MIXER4:
+ case WM8993_OUTPUT_MIXER5:
+ case WM8993_OUTPUT_MIXER6:
+ case WM8993_HPOUT2_MIXER:
+ case WM8993_LINE_MIXER1:
+ case WM8993_LINE_MIXER2:
+ case WM8993_SPEAKER_MIXER:
+ case WM8993_ADDITIONAL_CONTROL:
+ case WM8993_ANTIPOP1:
+ case WM8993_ANTIPOP2:
+ case WM8993_MICBIAS:
+ case WM8993_FLL_CONTROL_1:
+ case WM8993_FLL_CONTROL_2:
+ case WM8993_FLL_CONTROL_3:
+ case WM8993_FLL_CONTROL_4:
+ case WM8993_FLL_CONTROL_5:
+ case WM8993_CLOCKING_3:
+ case WM8993_CLOCKING_4:
+ case WM8993_MW_SLAVE_CONTROL:
+ case WM8993_BUS_CONTROL_1:
+ case WM8993_WRITE_SEQUENCER_0:
+ case WM8993_WRITE_SEQUENCER_1:
+ case WM8993_WRITE_SEQUENCER_2:
+ case WM8993_WRITE_SEQUENCER_3:
+ case WM8993_WRITE_SEQUENCER_4:
+ case WM8993_WRITE_SEQUENCER_5:
+ case WM8993_CHARGE_PUMP_1:
+ case WM8993_CLASS_W_0:
+ case WM8993_DC_SERVO_0:
+ case WM8993_DC_SERVO_1:
+ case WM8993_DC_SERVO_3:
+ case WM8993_DC_SERVO_READBACK_0:
+ case WM8993_DC_SERVO_READBACK_1:
+ case WM8993_DC_SERVO_READBACK_2:
+ case WM8993_ANALOGUE_HP_0:
+ case WM8993_EQ1:
+ case WM8993_EQ2:
+ case WM8993_EQ3:
+ case WM8993_EQ4:
+ case WM8993_EQ5:
+ case WM8993_EQ6:
+ case WM8993_EQ7:
+ case WM8993_EQ8:
+ case WM8993_EQ9:
+ case WM8993_EQ10:
+ case WM8993_EQ11:
+ case WM8993_EQ12:
+ case WM8993_EQ13:
+ case WM8993_EQ14:
+ case WM8993_EQ15:
+ case WM8993_EQ16:
+ case WM8993_EQ17:
+ case WM8993_EQ18:
+ case WM8993_EQ19:
+ case WM8993_EQ20:
+ case WM8993_EQ21:
+ case WM8993_EQ22:
+ case WM8993_EQ23:
+ case WM8993_EQ24:
+ case WM8993_DIGITAL_PULLS:
+ case WM8993_DRC_CONTROL_1:
+ case WM8993_DRC_CONTROL_2:
+ case WM8993_DRC_CONTROL_3:
+ case WM8993_DRC_CONTROL_4:
+ return true;
+ default:
+ return false;
}
}
@@ -369,8 +471,10 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
unsigned int Fref, unsigned int Fout)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
u16 reg1, reg4, reg5;
struct _fll_div fll_div;
+ unsigned int timeout;
int ret;
/* Any change? */
@@ -441,14 +545,22 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5);
+ /* If we've got an interrupt wired up make sure we get it */
+ if (i2c->irq)
+ timeout = msecs_to_jiffies(20);
+ else if (Fref < 1000000)
+ timeout = msecs_to_jiffies(3);
+ else
+ timeout = msecs_to_jiffies(1);
+
+ try_wait_for_completion(&wm8993->fll_lock);
+
/* Enable the FLL */
snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
- /* Both overestimates */
- if (Fref < 1000000)
- msleep(3);
- else
- msleep(1);
+ timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout);
+ if (i2c->irq && !timeout)
+ dev_warn(codec->dev, "Timed out waiting for FLL\n");
dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
@@ -946,6 +1058,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int ret;
+ wm_hubs_set_bias_level(codec, level);
+
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
@@ -963,12 +1077,10 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
if (ret != 0)
return ret;
- snd_soc_cache_sync(codec);
+ regcache_cache_only(wm8993->regmap, false);
+ regcache_sync(wm8993->regmap);
- /* Tune DC servo configuration */
- snd_soc_write(codec, 0x44, 3);
- snd_soc_write(codec, 0x56, 3);
- snd_soc_write(codec, 0x44, 0);
+ wm_hubs_vmid_ena(codec);
/* Bring up VMID with fast soft start */
snd_soc_update_bits(codec, WM8993_ANTIPOP2,
@@ -1024,14 +1136,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
WM8993_VMID_RAMP_MASK |
WM8993_BIAS_SRC, 0);
-#ifdef CONFIG_REGULATOR
- /* Post 2.6.34 we will be able to get a callback when
- * the regulators are disabled which we can use but
- * for now just assume that the power will be cut if
- * the regulator API is in use.
- */
- codec->cache_sync = 1;
-#endif
+ regcache_cache_only(wm8993->regmap, true);
+ regcache_mark_dirty(wm8993->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
@@ -1378,6 +1484,45 @@ out:
return 0;
}
+static irqreturn_t wm8993_irq(int irq, void *data)
+{
+ struct wm8993_priv *wm8993 = data;
+ int mask, val, ret;
+
+ ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val);
+ if (ret != 0) {
+ dev_err(wm8993->dev, "Failed to read interrupt status: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask);
+ if (ret != 0) {
+ dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ /* The IRQ pin status is visible in the register too */
+ val &= ~(mask | WM8993_IRQ);
+ if (!val)
+ return IRQ_NONE;
+
+ if (val & WM8993_TEMPOK_EINT)
+ dev_crit(wm8993->dev, "Thermal warning\n");
+
+ if (val & WM8993_FLL_LOCK_EINT) {
+ dev_dbg(wm8993->dev, "FLL locked\n");
+ complete(&wm8993->fll_lock);
+ }
+
+ ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val);
+ if (ret != 0)
+ dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret);
+
+ return IRQ_HANDLED;
+}
+
static const struct snd_soc_dai_ops wm8993_ops = {
.set_sysclk = wm8993_set_sysclk,
.set_fmt = wm8993_set_dai_fmt,
@@ -1402,6 +1547,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
.channels_max = 2,
.rates = WM8993_RATES,
.formats = WM8993_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "Capture",
@@ -1409,6 +1555,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
.channels_max = 2,
.rates = WM8993_RATES,
.formats = WM8993_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8993_ops,
.symmetric_rates = 1,
@@ -1418,49 +1565,20 @@ static int wm8993_probe(struct snd_soc_codec *codec)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret, i, val;
+ int ret;
wm8993->hubs_data.hp_startup_mode = 1;
wm8993->hubs_data.dcs_codes_l = -2;
wm8993->hubs_data.dcs_codes_r = -2;
wm8993->hubs_data.series_startup = 1;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ codec->control_data = wm8993->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
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];
-
- 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;
- }
-
- 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;
@@ -1489,15 +1607,15 @@ static int wm8993_probe(struct snd_soc_codec *codec)
ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
if (ret != 0)
- goto err_enable;
+ return ret;
- snd_soc_add_controls(codec, wm8993_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8993_snd_controls,
ARRAY_SIZE(wm8993_snd_controls));
if (wm8993->pdata.num_retune_configs != 0) {
dev_dbg(codec->dev, "Using ReTune Mobile\n");
} else {
dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
- snd_soc_add_controls(codec, wm8993_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8993_eq_controls,
ARRAY_SIZE(wm8993_eq_controls));
}
@@ -1509,13 +1627,14 @@ static int wm8993_probe(struct snd_soc_codec *codec)
wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
wm8993->pdata.lineout2_diff);
+ /* If the line outputs are differential then we aren't presenting
+ * VMID as an output and can disable it.
+ */
+ if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
+ codec->dapm.idle_bias_off = 1;
+
return 0;
-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 snd_soc_codec *codec)
@@ -1578,41 +1697,149 @@ static int wm8993_resume(struct snd_soc_codec *codec)
#define wm8993_resume NULL
#endif
+/* Tune DC servo configuration */
+static struct reg_default wm8993_regmap_patch[] = {
+ { 0x44, 3 },
+ { 0x56, 3 },
+ { 0x44, 0 },
+};
+
+static const struct regmap_config wm8993_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM8993_MAX_REGISTER,
+ .volatile_reg = wm8993_volatile,
+ .readable_reg = wm8993_readable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8993_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults),
+};
+
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,
};
-#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;
- int ret;
+ unsigned int reg;
+ int ret, i;
wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv),
GFP_KERNEL);
if (wm8993 == NULL)
return -ENOMEM;
+ wm8993->dev = &i2c->dev;
+ init_completion(&wm8993->fll_lock);
+
+ wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+ if (IS_ERR(wm8993->regmap)) {
+ ret = PTR_ERR(wm8993->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8993);
+ for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+ wm8993->supplies[i].supply = wm8993_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+ wm8993->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->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(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
+
+ ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+ goto err_enable;
+ }
+
+ if (reg != 0x8993) {
+ dev_err(&i2c->dev, "Invalid ID register value %x\n", reg);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff);
+ if (ret != 0)
+ goto err_enable;
+
+ ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
+ ARRAY_SIZE(wm8993_regmap_patch));
+ if (ret != 0)
+ dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
+ ret);
+
+ if (i2c->irq) {
+ /* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */
+ ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
+ WM8993_GPIO1_PD |
+ WM8993_GPIO1_SEL_MASK, 7);
+ if (ret != 0)
+ goto err_enable;
+
+ ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wm8993", wm8993);
+ if (ret != 0)
+ goto err_enable;
+
+ }
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
+ regcache_cache_only(wm8993->regmap, true);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8993, &wm8993_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_irq;
+ }
+
+ return 0;
+
+err_irq:
+ if (i2c->irq)
+ free_irq(i2c->irq, wm8993);
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err:
+ regmap_exit(wm8993->regmap);
return ret;
}
-static __devexit int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm8993);
+ regmap_exit(wm8993->regmap);
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
return 0;
}
@@ -1631,30 +1858,8 @@ static struct i2c_driver wm8993_i2c_driver = {
.remove = __devexit_p(wm8993_i2c_remove),
.id_table = wm8993_i2c_id,
};
-#endif
-
-static int __init wm8993_modinit(void)
-{
- 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);
- }
-#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);
+module_i2c_driver(wm8993_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8993 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 2184617b9611..4478b40c86e3 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -31,6 +31,7 @@
#define WM8993_GPIO_CTRL_1 0x12
#define WM8993_GPIO1 0x13
#define WM8993_IRQ_DEBOUNCE 0x14
+#define WM8993_INPUTS_CLAMP_REG 0x15
#define WM8993_GPIOCTRL_2 0x16
#define WM8993_GPIO_POL 0x17
#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18
@@ -656,6 +657,14 @@
#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */
/*
+ * R21 (0x15) - Inputs Clamp
+ */
+#define WM8993_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_SHIFT 7 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */
+
+/*
* R22 (0x16) - GPIOCTRL 2
*/
#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 93d27b660257..15fcb1bb7148 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -686,14 +686,23 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ if (!wm8994->jackdet || !wm8994->jack_cb)
+ return;
+
if (wm8994->active_refcount)
mode = WM1811_JACKDET_MODE_AUDIO;
+ if (mode == wm8994->jackdet_mode)
+ return;
+
+ wm8994->jackdet_mode = mode;
+
+ /* Always use audio mode to detect while the system is active */
+ if (mode != WM1811_JACKDET_MODE_NONE)
+ mode = WM1811_JACKDET_MODE_AUDIO;
+
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK, mode);
-
- if (mode == WM1811_JACKDET_MODE_MIC)
- msleep(2);
}
static void active_reference(struct snd_soc_codec *codec)
@@ -707,15 +716,8 @@ static void active_reference(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Active refcount incremented, now %d\n",
wm8994->active_refcount);
- if (wm8994->active_refcount == 1) {
- /* If we're using jack detection go into audio mode */
- if (wm8994->jackdet && wm8994->jack_cb) {
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM1811_JACKDET_MODE_MASK,
- WM1811_JACKDET_MODE_AUDIO);
- msleep(2);
- }
- }
+ /* If we're using jack detection go into audio mode */
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_AUDIO);
mutex_unlock(&wm8994->accdet_lock);
}
@@ -734,16 +736,12 @@ static void active_dereference(struct snd_soc_codec *codec)
if (wm8994->active_refcount == 0) {
/* Go into appropriate detection only mode */
- if (wm8994->jackdet && wm8994->jack_cb) {
- if (wm8994->jack_mic || wm8994->mic_detecting)
- mode = WM1811_JACKDET_MODE_MIC;
- else
- mode = WM1811_JACKDET_MODE_JACK;
+ if (wm8994->jack_mic || wm8994->mic_detecting)
+ mode = WM1811_JACKDET_MODE_MIC;
+ else
+ mode = WM1811_JACKDET_MODE_JACK;
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM1811_JACKDET_MODE_MASK,
- mode);
- }
+ wm1811_jackdet_set_mode(codec, mode);
}
mutex_unlock(&wm8994->accdet_lock);
@@ -770,20 +768,33 @@ static void vmid_reference(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ pm_runtime_get_sync(codec->dev);
+
wm8994->vmid_refcount++;
dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
wm8994->vmid_refcount);
if (wm8994->vmid_refcount == 1) {
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT_VMID_BUF_ENA |
+ WM8994_LINEOUT1_DISCH |
+ WM8994_LINEOUT2_DISCH,
+ WM8994_LINEOUT_VMID_BUF_ENA);
+
+ wm_hubs_vmid_ena(codec);
+
/* Startup bias, VMID ramp & buffer */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK,
+ WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
- (0x11 << WM8994_VMID_RAMP_SHIFT));
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -791,7 +802,11 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_VMID_SEL_MASK,
WM8994_BIAS_ENA | 0x2);
- msleep(20);
+ msleep(50);
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_RAMP_MASK | WM8994_BIAS_SRC,
+ 0);
}
}
@@ -821,6 +836,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_BIAS_ENA |
WM8994_VMID_SEL_MASK, 0);
+ /* Discharge VMID */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_DISCH, WM8994_VMID_DISCH);
+
/* Discharge line */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT1_DISCH |
@@ -837,6 +856,8 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK, 0);
}
+
+ pm_runtime_put(codec->dev);
}
static int vmid_event(struct snd_soc_dapm_widget *w,
@@ -1450,17 +1471,17 @@ SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0,
WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux),
SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
-SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
@@ -1575,6 +1596,14 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "TOCLK", NULL, "CLK_SYS" },
+ { "AIF1DACDAT", NULL, "AIF1 Playback" },
+ { "AIF2DACDAT", NULL, "AIF2 Playback" },
+ { "AIF3DACDAT", NULL, "AIF3 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1ADCDAT" },
+ { "AIF2 Capture", NULL, "AIF2ADCDAT" },
+ { "AIF3 Capture", NULL, "AIF3ADCDAT" },
+
/* AIF1 outputs */
{ "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" },
{ "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" },
@@ -1887,7 +1916,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
WM8994_FLL1_OUTDIV_MASK |
WM8994_FLL1_FRATIO_MASK, reg);
- snd_soc_write(codec, WM8994_FLL1_CONTROL_3 + reg_offset, fll.k);
+ snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_3 + reg_offset,
+ WM8994_FLL1_K_MASK, fll.k);
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset,
WM8994_FLL1_N_MASK,
@@ -2065,6 +2095,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
+ wm_hubs_set_bias_level(codec, level);
+
switch (level) {
case SND_SOC_BIAS_ON:
break;
@@ -2159,6 +2191,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
wm8994->cur_fw = NULL;
break;
}
+
codec->dapm.bias_level = level;
return 0;
@@ -2645,6 +2678,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF1 Capture",
@@ -2652,6 +2686,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8994_aif1_dai_ops,
},
@@ -2664,6 +2699,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF2 Capture",
@@ -2671,6 +2707,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.probe = wm8994_aif2_probe,
.ops = &wm8994_aif2_dai_ops,
@@ -2684,6 +2721,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF3 Capture",
@@ -2691,13 +2729,14 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
- },
+ .sig_bits = 24,
+ },
.ops = &wm8994_aif3_dai_ops,
}
};
#ifdef CONFIG_PM
-static int wm8994_suspend(struct snd_soc_codec *codec)
+static int wm8994_codec_suspend(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
@@ -2731,7 +2770,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec)
return 0;
}
-static int wm8994_resume(struct snd_soc_codec *codec)
+static int wm8994_codec_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
@@ -2753,13 +2792,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
codec->cache_only = 0;
}
- /* Restore the registers */
- ret = snd_soc_cache_sync(codec);
- if (ret != 0)
- dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
-
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
if (!wm8994->fll_suspend[i].out)
continue;
@@ -2797,8 +2829,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
return 0;
}
#else
-#define wm8994_suspend NULL
-#define wm8994_resume NULL
+#define wm8994_codec_suspend NULL
+#define wm8994_codec_resume NULL
#endif
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
@@ -2861,7 +2893,7 @@ 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_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2914,7 +2946,7 @@ 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_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2930,7 +2962,7 @@ 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_codec_controls(wm8994->codec, wm8994_eq_controls,
ARRAY_SIZE(wm8994_eq_controls));
for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
@@ -2947,8 +2979,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* @codec: WM8994 codec
* @jack: jack to report detection events on
* @micbias: microphone bias to detect on
- * @det: value to report for presence detection
- * @shrt: value to report for short detection
*
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
* being used to bring out signals to the processor then only platform
@@ -2959,43 +2989,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* and micbias2_lvl platform data members.
*/
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt)
+ int micbias)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994_micdet *micdet;
struct wm8994 *control = wm8994->wm8994;
- int reg;
+ int reg, ret;
- if (control->type != WM8994)
+ if (control->type != WM8994) {
+ dev_warn(codec->dev, "Not a WM8994\n");
return -EINVAL;
+ }
switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
case 2:
micdet = &wm8994->micdet[1];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
default:
+ dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
return -EINVAL;
- }
+ }
+
+ if (ret != 0)
+ dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
+ micbias, ret);
- dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
- micbias, det, shrt);
+ dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
+ micbias, jack);
/* Store the configuration */
micdet->jack = jack;
- micdet->det = det;
- micdet->shrt = shrt;
+ micdet->detecting = true;
/* If either of the jacks is set up then enable detection */
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
reg = WM8994_MICD_ENA;
- else
+ else
reg = 0;
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
+ snd_soc_dapm_sync(&codec->dapm);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -3021,20 +3071,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
dev_dbg(codec->dev, "Microphone status: %x\n", reg);
report = 0;
- if (reg & WM8994_MIC1_DET_STS)
- report |= priv->micdet[0].det;
- if (reg & WM8994_MIC1_SHRT_STS)
- report |= priv->micdet[0].shrt;
+ if (reg & WM8994_MIC1_DET_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC1_SHRT_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[0].detecting = false;
+ else
+ priv->micdet[0].detecting = true;
+
snd_soc_jack_report(priv->micdet[0].jack, report,
- priv->micdet[0].det | priv->micdet[0].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
report = 0;
- if (reg & WM8994_MIC2_DET_STS)
- report |= priv->micdet[1].det;
- if (reg & WM8994_MIC2_SHRT_STS)
- report |= priv->micdet[1].shrt;
+ if (reg & WM8994_MIC2_DET_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC2_SHRT_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[1].detecting = false;
+ else
+ priv->micdet[1].detecting = true;
+
snd_soc_jack_report(priv->micdet[1].jack, report,
- priv->micdet[1].det | priv->micdet[1].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
return IRQ_HANDLED;
}
@@ -3083,7 +3155,7 @@ static void wm8958_default_micdet(u16 status, void *data)
}
- if (wm8994->mic_detecting && status & 0x4) {
+ if (wm8994->mic_detecting && status & 0xfc) {
dev_dbg(codec->dev, "Detected headphone\n");
wm8994->mic_detecting = false;
@@ -3094,11 +3166,23 @@ static void wm8958_default_micdet(u16 status, void *data)
/* If we have jackdet that will detect removal */
if (wm8994->jackdet) {
+ mutex_lock(&wm8994->accdet_lock);
+
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
wm1811_jackdet_set_mode(codec,
WM1811_JACKDET_MODE_JACK);
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
}
}
@@ -3133,6 +3217,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
struct wm8994_priv *wm8994 = data;
struct snd_soc_codec *codec = wm8994->codec;
int reg;
+ bool present;
mutex_lock(&wm8994->accdet_lock);
@@ -3145,11 +3230,17 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
dev_dbg(codec->dev, "JACKDET %x\n", reg);
- if (reg & WM1811_JACKDET_LVL) {
+ present = reg & WM1811_JACKDET_LVL;
+
+ if (present) {
dev_dbg(codec->dev, "Jack detected\n");
- snd_soc_jack_report(wm8994->micdet[0].jack,
- SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, 0);
+
+ /* Disable debounce while inserted */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, 0);
/*
* Start off measument of microphone impedence to find
@@ -3157,14 +3248,18 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
*/
wm8994->mic_detecting = true;
wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, WM8958_MICD_ENA);
} else {
dev_dbg(codec->dev, "Jack not detected\n");
- snd_soc_jack_report(wm8994->micdet[0].jack, 0,
- SND_JACK_MECHANICAL | SND_JACK_HEADSET |
- wm8994->btn_mask);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
+
+ /* Enable debounce while removed */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, WM1811_JACKDET_DB);
wm8994->mic_detecting = false;
wm8994->jack_mic = false;
@@ -3175,6 +3270,28 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
mutex_unlock(&wm8994->accdet_lock);
+ /* If required for an external cap force MICBIAS on */
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+
+ if (present)
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
+
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
+
+ if (present)
+ snd_soc_jack_report(wm8994->micdet[0].jack,
+ SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+ else
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+ SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+ wm8994->btn_mask);
+
return IRQ_HANDLED;
}
@@ -3217,6 +3334,7 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
}
snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
wm8994->micdet[0].jack = jack;
wm8994->jack_cb = cb;
@@ -3247,6 +3365,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
* otherwise jump straight to microphone detection.
*/
if (wm8994->jackdet) {
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH,
+ WM8958_MICB2_DISCH);
snd_soc_update_bits(codec, WM8994_LDO_1,
WM8994_LDO1_DISCH, 0);
wm1811_jackdet_set_mode(codec,
@@ -3259,7 +3380,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
} else {
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE);
snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
}
return 0;
@@ -3272,17 +3395,13 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
struct snd_soc_codec *codec = wm8994->codec;
int reg, count;
- mutex_lock(&wm8994->accdet_lock);
-
/*
* Jack detection may have detected a removal simulataneously
* with an update of the MICDET status; if so it will have
* stopped detection and we can ignore this interrupt.
*/
- if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) {
- mutex_unlock(&wm8994->accdet_lock);
+ if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
return IRQ_HANDLED;
- }
/* We may occasionally read a detection without an impedence
* range being provided - if that happens loop again.
@@ -3291,7 +3410,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
do {
reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
if (reg < 0) {
- mutex_unlock(&wm8994->accdet_lock);
dev_err(codec->dev,
"Failed to read mic detect status: %d\n",
reg);
@@ -3322,8 +3440,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
dev_warn(codec->dev, "Accessory detection with no callback\n");
out:
- mutex_unlock(&wm8994->accdet_lock);
-
return IRQ_HANDLED;
}
@@ -3357,23 +3473,16 @@ static irqreturn_t wm8994_temp_shut(int irq, void *data)
static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
struct wm8994 *control = dev_get_drvdata(codec->dev->parent);
- struct wm8994_priv *wm8994;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
unsigned int reg;
int ret, i;
+ wm8994->codec = codec;
codec->control_data = control->regmap;
- wm8994 = devm_kzalloc(codec->dev, sizeof(struct wm8994_priv),
- GFP_KERNEL);
- if (wm8994 == NULL)
- return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, wm8994);
-
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- wm8994->wm8994 = dev_get_drvdata(codec->dev->parent);
- wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec;
mutex_init(&wm8994->accdet_lock);
@@ -3388,12 +3497,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
WM8994_IRQ_MIC1_DET;
pm_runtime_enable(codec->dev);
- pm_runtime_resume(codec->dev);
+ pm_runtime_idle(codec->dev);
+
+ /* By default use idle_bias_off, will override for WM8994 */
+ codec->dapm.idle_bias_off = 1;
/* Set revision-specific configuration */
wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
switch (control->type) {
case WM8994:
+ /* Single ended line outputs should have VMID on. */
+ if (!wm8994->pdata->lineout1_diff ||
+ !wm8994->pdata->lineout2_diff)
+ codec->dapm.idle_bias_off = 0;
+
switch (wm8994->revision) {
case 2:
case 3:
@@ -3411,11 +3528,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
+ wm8994->hubs.hp_startup_mode = 1;
break;
case WM1811:
wm8994->hubs.dcs_readback_mode = 2;
wm8994->hubs.no_series_update = 1;
+ wm8994->hubs.hp_startup_mode = 1;
+ wm8994->hubs.no_cache_class_w = true;
switch (wm8994->revision) {
case 0:
@@ -3532,6 +3652,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->fll_locked_irq = false;
}
+ /* Make sure we can read from the GPIOs if they're inputs */
+ pm_runtime_get_sync(codec->dev);
+
/* Remember if AIFnLRCLK is configured as a GPIO. This should be
* configured on init - if a system wants to do this dynamically
* at runtime we can deal with that then.
@@ -3560,7 +3683,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->lrclk_shared[1] = 0;
}
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ pm_runtime_put(codec->dev);
/* Latch volume updates (right only; we always do left then right). */
snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
@@ -3638,7 +3761,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994_handle_pdata(wm8994);
wm_hubs_add_analogue_controls(codec);
- snd_soc_add_controls(codec, wm8994_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8994_snd_controls,
ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
ARRAY_SIZE(wm8994_dapm_widgets));
@@ -3664,7 +3787,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
}
break;
case WM8958:
- snd_soc_add_controls(codec, wm8958_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
ARRAY_SIZE(wm8958_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3686,7 +3809,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
break;
case WM1811:
- snd_soc_add_controls(codec, wm8958_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
ARRAY_SIZE(wm8958_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3815,24 +3938,27 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
return 0;
}
-static int wm8994_soc_volatile(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
- .suspend = wm8994_suspend,
- .resume = wm8994_resume,
+ .suspend = wm8994_codec_suspend,
+ .resume = wm8994_codec_resume,
.set_bias_level = wm8994_set_bias_level,
- .reg_cache_size = WM8994_MAX_REGISTER,
- .volatile_register = wm8994_soc_volatile,
};
static int __devinit wm8994_probe(struct platform_device *pdev)
{
+ struct wm8994_priv *wm8994;
+
+ wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
+ GFP_KERNEL);
+ if (wm8994 == NULL)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, wm8994);
+
+ wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
+ wm8994->pdata = dev_get_platdata(pdev->dev.parent);
+
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
@@ -3843,11 +3969,43 @@ static int __devexit wm8994_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int wm8994_suspend(struct device *dev)
+{
+ struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+ /* Drop down to power saving mode when system is suspended */
+ if (wm8994->jackdet && !wm8994->active_refcount)
+ regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK,
+ wm8994->jackdet_mode);
+
+ return 0;
+}
+
+static int wm8994_resume(struct device *dev)
+{
+ struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+ if (wm8994->jackdet && wm8994->jack_cb)
+ regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK,
+ WM1811_JACKDET_MODE_AUDIO);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops wm8994_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
+};
+
static struct platform_driver wm8994_codec_driver = {
.driver = {
- .name = "wm8994-codec",
- .owner = THIS_MODULE,
- },
+ .name = "wm8994-codec",
+ .owner = THIS_MODULE,
+ .pm = &wm8994_pm_ops,
+ },
.probe = wm8994_probe,
.remove = __devexit_p(wm8994_remove),
};
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index c3a42474ab19..2f4d2d12a452 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -35,7 +35,7 @@
typedef void (*wm8958_micdet_cb)(u16 status, void *data);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt);
+ int micbias);
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8958_micdet_cb cb, void *cb_data);
@@ -46,8 +46,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
struct wm8994_micdet {
struct snd_soc_jack *jack;
- int det;
- int shrt;
+ bool detecting;
};
/* codec private data */
@@ -123,6 +122,7 @@ struct wm8994_priv {
bool jack_mic;
int btn_mask;
bool jackdet;
+ int jackdet_mode;
wm8958_micdet_cb jack_cb;
void *jack_cb_data;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index c8aada597d70..28c89b094c6e 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2047,7 +2047,6 @@ static int wm8995_probe(struct snd_soc_codec *codec)
int i;
int ret;
- codec->dapm.idle_bias_off = 1;
wm8995 = snd_soc_codec_get_drvdata(codec);
wm8995->codec = codec;
@@ -2137,7 +2136,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
wm8995_update_class_w(codec);
- snd_soc_add_controls(codec, wm8995_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8995_snd_controls,
ARRAY_SIZE(wm8995_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets,
ARRAY_SIZE(wm8995_dapm_widgets));
@@ -2241,6 +2240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.suspend = wm8995_suspend,
.resume = wm8995_resume,
.set_bias_level = wm8995_set_bias_level,
+ .idle_bias_off = true,
};
static struct regmap_config wm8995_regmap = {
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 13aa2bdaa7d7..40a124c9f15d 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -73,7 +73,6 @@ struct wm8996_priv {
struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
- struct regulator *cpvdd;
int bg_ena;
struct wm8996_pdata pdata;
@@ -90,6 +89,7 @@ struct wm8996_priv {
struct snd_soc_jack *jack;
bool detecting;
bool jack_mic;
+ int jack_flips;
wm8996_polarity_fn polarity_cb;
#ifdef CONFIG_GPIOLIB
@@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- regcache_cache_only(wm8996->regmap, true); \
+ regcache_mark_dirty(wm8996->regmap); \
} \
return 0; \
}
@@ -118,7 +118,6 @@ WM8996_REGULATOR_EVENT(1)
WM8996_REGULATOR_EVENT(2)
static struct reg_default wm8996_reg[] = {
- { WM8996_SOFTWARE_RESET, 0x8996 },
{ WM8996_POWER_MANAGEMENT_1, 0x0 },
{ WM8996_POWER_MANAGEMENT_2, 0x0 },
{ WM8996_POWER_MANAGEMENT_3, 0x0 },
@@ -153,7 +152,6 @@ static struct reg_default wm8996_reg[] = {
{ WM8996_CHARGE_PUMP_1, 0x1f25 },
{ WM8996_CHARGE_PUMP_2, 0xab19 },
{ WM8996_DC_SERVO_1, 0x0 },
- { WM8996_DC_SERVO_2, 0x0 },
{ WM8996_DC_SERVO_3, 0x0 },
{ WM8996_DC_SERVO_5, 0x2a2a },
{ WM8996_DC_SERVO_6, 0x0 },
@@ -716,10 +714,16 @@ SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5,
+ WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA |
+ WM8996_DSP1TXR_DRC_ENA),
SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5,
+ WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA |
+ WM8996_DSP2TXR_DRC_ENA),
};
static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -792,29 +796,18 @@ static int bg_event(struct snd_soc_dapm_widget *w,
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = w->codec;
- struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(wm8996->cpvdd);
- if (ret != 0)
- dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
- ret);
- break;
case SND_SOC_DAPM_POST_PMU:
msleep(5);
break;
- case SND_SOC_DAPM_POST_PMD:
- regulator_disable_deferred(wm8996->cpvdd, 20);
- break;
default:
BUG();
ret = -EINVAL;
}
- return ret;
+ return 0;
}
static int rmv_short_event(struct snd_soc_dapm_widget *w,
@@ -897,8 +890,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT1L) {
- val |= WM8996_HPOUT1L_RMV_SHORT;
- mask |= WM8996_HPOUT1L_RMV_SHORT;
+ val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
+ mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
} else {
mask |= WM8996_HPOUT1L_RMV_SHORT |
WM8996_HPOUT1L_OUTP |
@@ -906,8 +899,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT1R) {
- val |= WM8996_HPOUT1R_RMV_SHORT;
- mask |= WM8996_HPOUT1R_RMV_SHORT;
+ val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
+ mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
} else {
mask |= WM8996_HPOUT1R_RMV_SHORT |
WM8996_HPOUT1R_OUTP |
@@ -919,8 +912,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT2L) {
- val |= WM8996_HPOUT2L_RMV_SHORT;
- mask |= WM8996_HPOUT2L_RMV_SHORT;
+ val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
+ mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
} else {
mask |= WM8996_HPOUT2L_RMV_SHORT |
WM8996_HPOUT2L_OUTP |
@@ -928,8 +921,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT2R) {
- val |= WM8996_HPOUT2R_RMV_SHORT;
- mask |= WM8996_HPOUT2R_RMV_SHORT;
+ val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
+ mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
} else {
mask |= WM8996_HPOUT2R_RMV_SHORT |
WM8996_HPOUT2R_OUTP |
@@ -1116,12 +1109,12 @@ SND_SOC_DAPM_INPUT("IN2RP"),
SND_SOC_DAPM_INPUT("DMIC1DAT"),
SND_SOC_DAPM_INPUT("DMIC2DAT"),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -1180,41 +1173,25 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0),
SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0),
SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
- WM8996_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 8, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
- WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
- WM8996_POWER_MANAGEMENT_4, 5, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
- WM8996_POWER_MANAGEMENT_4, 4, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
- WM8996_POWER_MANAGEMENT_4, 3, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
- WM8996_POWER_MANAGEMENT_4, 2, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 1, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
- WM8996_POWER_MANAGEMENT_4, 0, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
- WM8996_POWER_MANAGEMENT_6, 5, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
- WM8996_POWER_MANAGEMENT_6, 4, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
- WM8996_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
- WM8996_POWER_MANAGEMENT_6, 2, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
- WM8996_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0),
/* We route as stereo pairs so define some dummy widgets to squash
* things down for now. RXA = 0,1, RXB = 2,3 and so on */
@@ -1237,7 +1214,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1246,7 +1222,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1255,7 +1230,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1264,7 +1238,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1280,6 +1253,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "AIFCLK", NULL, "SYSCLK" },
{ "SYSDSPCLK", NULL, "SYSCLK" },
{ "Charge Pump", NULL, "SYSCLK" },
+ { "Charge Pump", NULL, "CPVDD" },
{ "MICB1", NULL, "LDO2" },
{ "MICB1", NULL, "MICB1 Audio" },
@@ -1288,6 +1262,26 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "MICB2", NULL, "MICB2 Audio" },
{ "MICB2", NULL, "Bandgap" },
+ { "AIF1RX0", NULL, "AIF1 Playback" },
+ { "AIF1RX1", NULL, "AIF1 Playback" },
+ { "AIF1RX2", NULL, "AIF1 Playback" },
+ { "AIF1RX3", NULL, "AIF1 Playback" },
+ { "AIF1RX4", NULL, "AIF1 Playback" },
+ { "AIF1RX5", NULL, "AIF1 Playback" },
+
+ { "AIF2RX0", NULL, "AIF2 Playback" },
+ { "AIF2RX1", NULL, "AIF2 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1TX0" },
+ { "AIF1 Capture", NULL, "AIF1TX1" },
+ { "AIF1 Capture", NULL, "AIF1TX2" },
+ { "AIF1 Capture", NULL, "AIF1TX3" },
+ { "AIF1 Capture", NULL, "AIF1TX4" },
+ { "AIF1 Capture", NULL, "AIF1TX5" },
+
+ { "AIF2 Capture", NULL, "AIF2TX0" },
+ { "AIF2 Capture", NULL, "AIF2TX1" },
+
{ "IN1L PGA", NULL, "IN2LN" },
{ "IN1L PGA", NULL, "IN2LP" },
{ "IN1L PGA", NULL, "IN1LN" },
@@ -1436,32 +1430,28 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "HPOUT2L PGA", NULL, "DAC2L" },
{ "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
{ "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
- { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
- { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
+ { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" },
{ "HPOUT2R PGA", NULL, "Charge Pump" },
{ "HPOUT2R PGA", NULL, "Bandgap" },
{ "HPOUT2R PGA", NULL, "DAC2R" },
{ "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
{ "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
- { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
- { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
+ { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" },
{ "HPOUT1L PGA", NULL, "Charge Pump" },
{ "HPOUT1L PGA", NULL, "Bandgap" },
{ "HPOUT1L PGA", NULL, "DAC1L" },
{ "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
{ "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
- { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
- { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
+ { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" },
{ "HPOUT1R PGA", NULL, "Charge Pump" },
{ "HPOUT1R PGA", NULL, "Bandgap" },
{ "HPOUT1R PGA", NULL, "DAC1R" },
{ "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
{ "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
- { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
- { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
+ { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" },
{ "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
{ "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
@@ -1720,6 +1710,7 @@ static int wm8996_reset(struct wm8996_priv *wm8996)
{
if (wm8996->pdata.ldo_ena > 0) {
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
return 0;
} else {
return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
@@ -2438,6 +2429,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996->jack = jack;
wm8996->detecting = true;
wm8996->polarity_cb = polarity_cb;
+ wm8996->jack_flips = 0;
if (wm8996->polarity_cb)
wm8996->polarity_cb(codec, 0);
@@ -2553,6 +2545,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
WM8996_HP_POLL, WM8996_HP_POLL);
}
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+ dev_dbg(codec->dev, "Headphone detected\n");
+ wm8996_hpdet_start(codec);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+ WM8996_MICD_RATE_MASK |
+ WM8996_MICD_BIAS_STARTTIME_MASK,
+ 7 << WM8996_MICD_RATE_SHIFT |
+ 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
static void wm8996_micd(struct snd_soc_codec *codec)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2572,6 +2577,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Jack removal detected\n");
wm8996->jack_mic = false;
wm8996->detecting = true;
+ wm8996->jack_flips = 0;
snd_soc_jack_report(wm8996->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0);
@@ -2612,9 +2618,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
/* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of
- * plain headphones.
+ * plain headphones. If both polarities report a low
+ * impedence then give up and report headphones.
*/
if (wm8996->detecting && (val & 0x3f0)) {
+ wm8996->jack_flips++;
+
+ if (wm8996->jack_flips > 1) {
+ wm8996_report_headphone(codec);
+ return;
+ }
+
reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
WM8996_MICD_BIAS_SRC;
@@ -2641,17 +2655,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
} else if (wm8996->detecting) {
- dev_dbg(codec->dev, "Headphone detected\n");
- wm8996_hpdet_start(codec);
-
- /* Increase the detection rate a bit for
- * responsiveness.
- */
- snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
- WM8996_MICD_RATE_MASK |
- WM8996_MICD_BIAS_STARTTIME_MASK,
- 7 << WM8996_MICD_RATE_SHIFT |
- 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+ wm8996_report_headphone(codec);
}
}
}
@@ -2768,7 +2772,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile controls: %d\n", ret);
@@ -2791,7 +2795,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
int ret;
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = to_i2c_client(codec->dev);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int i, irq_flags;
wm8996->codec = codec;
@@ -2799,8 +2802,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
init_completion(&wm8996->dcs_done);
init_completion(&wm8996->fll_lock);
- dapm->idle_bias_off = true;
-
codec->control_data = wm8996->regmap;
ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
@@ -2966,7 +2967,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
if (wm8996->pdata.num_retune_mobile_cfgs)
wm8996_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8996_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8996_eq_controls,
ARRAY_SIZE(wm8996_eq_controls));
/* If the TX LRCLK pins are not in LRCLK mode configure the
@@ -3038,22 +3039,16 @@ static int wm8996_remove(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
regulator_unregister_notifier(wm8996->supplies[i].consumer,
&wm8996->disable_nb[i]);
- regulator_put(wm8996->cpvdd);
regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
return 0;
}
-static int wm8996_soc_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
.probe = wm8996_probe,
.remove = wm8996_remove,
.set_bias_level = wm8996_set_bias_level,
+ .idle_bias_off = true,
.seq_notifier = wm8996_seq_notifier,
.controls = wm8996_snd_controls,
.num_controls = ARRAY_SIZE(wm8996_snd_controls),
@@ -3062,8 +3057,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
.dapm_routes = wm8996_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes),
.set_pll = wm8996_set_fll,
- .reg_cache_size = WM8996_MAX_REGISTER,
- .volatile_register = wm8996_soc_volatile_register,
};
#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
@@ -3087,6 +3080,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 6,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF1 Capture",
@@ -3094,6 +3088,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 6,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8996_dai_ops,
},
@@ -3105,6 +3100,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 2,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF2 Capture",
@@ -3112,6 +3108,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 2,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8996_dai_ops,
},
@@ -3149,25 +3146,18 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
wm8996->supplies[i].supply = wm8996_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
- wm8996->supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+ wm8996->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
goto err_gpio;
}
- wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
- if (IS_ERR(wm8996->cpvdd)) {
- ret = PTR_ERR(wm8996->cpvdd);
- dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
- goto err_get;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
wm8996->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_cpvdd;
+ goto err_gpio;
}
if (wm8996->pdata.ldo_ena > 0) {
@@ -3188,7 +3178,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
goto err_regmap;
}
if (reg != 0x8915) {
- dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+ dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg);
ret = -EINVAL;
goto err_regmap;
}
@@ -3229,10 +3219,6 @@ err_enable:
if (wm8996->pdata.ldo_ena > 0)
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_cpvdd:
- regulator_put(wm8996->cpvdd);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
err_gpio:
if (wm8996->pdata.ldo_ena > 0)
gpio_free(wm8996->pdata.ldo_ena);
@@ -3247,8 +3233,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
snd_soc_unregister_codec(&client->dev);
wm8996_free_gpio(wm8996);
- regulator_put(wm8996->cpvdd);
- regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
regmap_exit(wm8996->regmap);
if (wm8996->pdata.ldo_ena > 0) {
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
@@ -3273,25 +3257,7 @@ static struct i2c_driver wm8996_i2c_driver = {
.id_table = wm8996_i2c_id,
};
-static int __init wm8996_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&wm8996_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
- ret);
- }
-
- return ret;
-}
-module_init(wm8996_modinit);
-
-static void __exit wm8996_exit(void)
-{
- i2c_del_driver(&wm8996_i2c_driver);
-}
-module_exit(wm8996_exit);
+module_i2c_driver(wm8996_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8996 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index a6bab392700e..076c126ed9b1 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -824,6 +824,8 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
static int wm9081_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+
switch (level) {
case SND_SOC_BIAS_ON:
break;
@@ -841,6 +843,9 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
/* Initial cold start */
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(wm9081->regmap, false);
+ regcache_sync(wm9081->regmap);
+
/* Disable LINEOUT discharge */
snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
WM9081_LINEOUT_DISCH, 0);
@@ -892,6 +897,8 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
WM9081_LINEOUT_DISCH,
WM9081_LINEOUT_DISCH);
+
+ regcache_cache_only(wm9081->regmap, true);
break;
}
@@ -1258,7 +1265,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
{
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
int ret;
- u16 reg;
codec->control_data = wm9081->regmap;
@@ -1268,16 +1274,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
return ret;
}
- reg = 0;
- if (wm9081->pdata.irq_high)
- reg |= WM9081_IRQ_POL;
- if (!wm9081->pdata.irq_cmos)
- reg |= WM9081_IRQ_OP_CTRL;
- snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
- WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
/* Enable zero cross by default */
snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
WM9081_LINEOUTZC, WM9081_LINEOUTZC);
@@ -1287,7 +1283,7 @@ static int wm9081_probe(struct snd_soc_codec *codec)
if (!wm9081->pdata.num_retune_configs) {
dev_dbg(codec->dev,
"No ReTune Mobile data, using normal EQ\n");
- snd_soc_add_controls(codec, wm9081_eq_controls,
+ snd_soc_add_codec_controls(codec, wm9081_eq_controls,
ARRAY_SIZE(wm9081_eq_controls));
}
@@ -1300,38 +1296,15 @@ static int wm9081_remove(struct snd_soc_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec)
-{
- wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int wm9081_resume(struct snd_soc_codec *codec)
-{
- struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
-
- regcache_sync(wm9081->regmap);
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- return 0;
-}
-#else
-#define wm9081_suspend NULL
-#define wm9081_resume NULL
-#endif
-
static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
.probe = wm9081_probe,
.remove = wm9081_remove,
- .suspend = wm9081_suspend,
- .resume = wm9081_resume,
.set_sysclk = wm9081_set_sysclk,
.set_bias_level = wm9081_set_bias_level,
+ .idle_bias_off = true,
+
.controls = wm9081_snd_controls,
.num_controls = ARRAY_SIZE(wm9081_snd_controls),
.dapm_widgets = wm9081_dapm_widgets,
@@ -1395,6 +1368,16 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
sizeof(wm9081->pdata));
+ reg = 0;
+ if (wm9081->pdata.irq_high)
+ reg |= WM9081_IRQ_POL;
+ if (!wm9081->pdata.irq_cmos)
+ reg |= WM9081_IRQ_OP_CTRL;
+ regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
+ WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
+ regcache_cache_only(wm9081->regmap, true);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9081, &wm9081_dai, 1);
if (ret < 0)
@@ -1435,28 +1418,7 @@ static struct i2c_driver wm9081_i2c_driver = {
};
#endif
-static int __init wm9081_modinit(void)
-{
- 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);
-
+module_i2c_driver(wm9081_i2c_driver);
MODULE_DESCRIPTION("ASoC WM9081 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 41ebe0dce772..4b263b6edf13 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -25,6 +25,7 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/initval.h>
#include <sound/soc.h>
@@ -33,116 +34,51 @@
#include "wm9090.h"
-static const u16 wm9090_reg_defaults[] = {
- 0x9093, /* R0 - Software Reset */
- 0x0006, /* R1 - Power Management (1) */
- 0x6000, /* R2 - Power Management (2) */
- 0x0000, /* R3 - Power Management (3) */
- 0x0000, /* R4 */
- 0x0000, /* R5 */
- 0x01C0, /* R6 - Clocking 1 */
- 0x0000, /* R7 */
- 0x0000, /* R8 */
- 0x0000, /* R9 */
- 0x0000, /* R10 */
- 0x0000, /* R11 */
- 0x0000, /* R12 */
- 0x0000, /* R13 */
- 0x0000, /* R14 */
- 0x0000, /* R15 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 */
- 0x0003, /* R22 - IN1 Line Control */
- 0x0003, /* R23 - IN2 Line Control */
- 0x0083, /* R24 - IN1 Line Input A Volume */
- 0x0083, /* R25 - IN1 Line Input B Volume */
- 0x0083, /* R26 - IN2 Line Input A Volume */
- 0x0083, /* R27 - IN2 Line Input B Volume */
- 0x002D, /* R28 - Left Output Volume */
- 0x002D, /* R29 - Right Output Volume */
- 0x0000, /* R30 */
- 0x0000, /* R31 */
- 0x0000, /* R32 */
- 0x0000, /* R33 */
- 0x0100, /* R34 - SPKMIXL Attenuation */
- 0x0000, /* R35 */
- 0x0010, /* R36 - SPKOUT Mixers */
- 0x0140, /* R37 - ClassD3 */
- 0x0039, /* R38 - Speaker Volume Left */
- 0x0000, /* R39 */
- 0x0000, /* R40 */
- 0x0000, /* R41 */
- 0x0000, /* R42 */
- 0x0000, /* R43 */
- 0x0000, /* R44 */
- 0x0000, /* R45 - Output Mixer1 */
- 0x0000, /* R46 - Output Mixer2 */
- 0x0100, /* R47 - Output Mixer3 */
- 0x0100, /* R48 - Output Mixer4 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 - Speaker Mixer */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x000D, /* R57 - AntiPOP2 */
- 0x0000, /* R58 */
- 0x0000, /* R59 */
- 0x0000, /* R60 */
- 0x0000, /* R61 */
- 0x0000, /* R62 */
- 0x0000, /* R63 */
- 0x0000, /* R64 */
- 0x0000, /* R65 */
- 0x0000, /* R66 */
- 0x0000, /* R67 */
- 0x0000, /* R68 */
- 0x0000, /* R69 */
- 0x0000, /* R70 - Write Sequencer 0 */
- 0x0000, /* R71 - Write Sequencer 1 */
- 0x0000, /* R72 - Write Sequencer 2 */
- 0x0000, /* R73 - Write Sequencer 3 */
- 0x0000, /* R74 - Write Sequencer 4 */
- 0x0000, /* R75 - Write Sequencer 5 */
- 0x1F25, /* R76 - Charge Pump 1 */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 - DC Servo 0 */
- 0x054A, /* R85 - DC Servo 1 */
- 0x0000, /* R86 */
- 0x0000, /* R87 - DC Servo 3 */
- 0x0000, /* R88 - DC Servo Readback 0 */
- 0x0000, /* R89 - DC Servo Readback 1 */
- 0x0000, /* R90 - DC Servo Readback 2 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 */
- 0x0000, /* R95 */
- 0x0100, /* R96 - Analogue HP 0 */
- 0x0000, /* R97 */
- 0x8640, /* R98 - AGC Control 0 */
- 0xC000, /* R99 - AGC Control 1 */
- 0x0200, /* R100 - AGC Control 2 */
+static const struct reg_default wm9090_reg_defaults[] = {
+ { 1, 0x0006 }, /* R1 - Power Management (1) */
+ { 2, 0x6000 }, /* R2 - Power Management (2) */
+ { 3, 0x0000 }, /* R3 - Power Management (3) */
+ { 6, 0x01C0 }, /* R6 - Clocking 1 */
+ { 22, 0x0003 }, /* R22 - IN1 Line Control */
+ { 23, 0x0003 }, /* R23 - IN2 Line Control */
+ { 24, 0x0083 }, /* R24 - IN1 Line Input A Volume */
+ { 25, 0x0083 }, /* R25 - IN1 Line Input B Volume */
+ { 26, 0x0083 }, /* R26 - IN2 Line Input A Volume */
+ { 27, 0x0083 }, /* R27 - IN2 Line Input B Volume */
+ { 28, 0x002D }, /* R28 - Left Output Volume */
+ { 29, 0x002D }, /* R29 - Right Output Volume */
+ { 34, 0x0100 }, /* R34 - SPKMIXL Attenuation */
+ { 35, 0x0010 }, /* R36 - SPKOUT Mixers */
+ { 37, 0x0140 }, /* R37 - ClassD3 */
+ { 38, 0x0039 }, /* R38 - Speaker Volume Left */
+ { 45, 0x0000 }, /* R45 - Output Mixer1 */
+ { 46, 0x0000 }, /* R46 - Output Mixer2 */
+ { 47, 0x0100 }, /* R47 - Output Mixer3 */
+ { 48, 0x0100 }, /* R48 - Output Mixer4 */
+ { 54, 0x0000 }, /* R54 - Speaker Mixer */
+ { 57, 0x000D }, /* R57 - AntiPOP2 */
+ { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
+ { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
+ { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
+ { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
+ { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
+ { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
+ { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
+ { 85, 0x054A }, /* R85 - DC Servo 1 */
+ { 87, 0x0000 }, /* R87 - DC Servo 3 */
+ { 96, 0x0100 }, /* R96 - Analogue HP 0 */
+ { 98, 0x8640 }, /* R98 - AGC Control 0 */
+ { 99, 0xC000 }, /* R99 - AGC Control 1 */
+ { 100, 0x0200 }, /* R100 - AGC Control 2 */
};
/* This struct is used to save the context */
struct wm9090_priv {
struct wm9090_platform_data pdata;
+ struct regmap *regmap;
};
-static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9090_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM9090_SOFTWARE_RESET:
@@ -150,10 +86,60 @@ static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
case WM9090_DC_SERVO_READBACK_0:
case WM9090_DC_SERVO_READBACK_1:
case WM9090_DC_SERVO_READBACK_2:
- return 1;
+ return true;
default:
- return 0;
+ return false;
+ }
+}
+
+static bool wm9090_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM9090_SOFTWARE_RESET:
+ case WM9090_POWER_MANAGEMENT_1:
+ case WM9090_POWER_MANAGEMENT_2:
+ case WM9090_POWER_MANAGEMENT_3:
+ case WM9090_CLOCKING_1:
+ case WM9090_IN1_LINE_CONTROL:
+ case WM9090_IN2_LINE_CONTROL:
+ case WM9090_IN1_LINE_INPUT_A_VOLUME:
+ case WM9090_IN1_LINE_INPUT_B_VOLUME:
+ case WM9090_IN2_LINE_INPUT_A_VOLUME:
+ case WM9090_IN2_LINE_INPUT_B_VOLUME:
+ case WM9090_LEFT_OUTPUT_VOLUME:
+ case WM9090_RIGHT_OUTPUT_VOLUME:
+ case WM9090_SPKMIXL_ATTENUATION:
+ case WM9090_SPKOUT_MIXERS:
+ case WM9090_CLASSD3:
+ case WM9090_SPEAKER_VOLUME_LEFT:
+ case WM9090_OUTPUT_MIXER1:
+ case WM9090_OUTPUT_MIXER2:
+ case WM9090_OUTPUT_MIXER3:
+ case WM9090_OUTPUT_MIXER4:
+ case WM9090_SPEAKER_MIXER:
+ case WM9090_ANTIPOP2:
+ case WM9090_WRITE_SEQUENCER_0:
+ case WM9090_WRITE_SEQUENCER_1:
+ case WM9090_WRITE_SEQUENCER_2:
+ case WM9090_WRITE_SEQUENCER_3:
+ case WM9090_WRITE_SEQUENCER_4:
+ case WM9090_WRITE_SEQUENCER_5:
+ case WM9090_CHARGE_PUMP_1:
+ case WM9090_DC_SERVO_0:
+ case WM9090_DC_SERVO_1:
+ case WM9090_DC_SERVO_3:
+ case WM9090_DC_SERVO_READBACK_0:
+ case WM9090_DC_SERVO_READBACK_1:
+ case WM9090_DC_SERVO_READBACK_2:
+ case WM9090_ANALOGUE_HP_0:
+ case WM9090_AGC_CONTROL_0:
+ case WM9090_AGC_CONTROL_1:
+ case WM9090_AGC_CONTROL_2:
+ return true;
+
+ default:
+ return false;
}
}
@@ -447,7 +433,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_add_controls(codec, wm9090_controls,
+ snd_soc_add_codec_controls(codec, wm9090_controls,
ARRAY_SIZE(wm9090_controls));
if (wm9090->pdata.lin1_diff) {
@@ -456,7 +442,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
ARRAY_SIZE(audio_map_in1_se));
- snd_soc_add_controls(codec, wm9090_in1_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in1_se_controls,
ARRAY_SIZE(wm9090_in1_se_controls));
}
@@ -466,7 +452,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
ARRAY_SIZE(audio_map_in2_se));
- snd_soc_add_controls(codec, wm9090_in2_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in2_se_controls,
ARRAY_SIZE(wm9090_in2_se_controls));
}
@@ -492,8 +478,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
static int wm9090_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 *reg_cache = codec->reg_cache;
- int i, ret;
+ struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
@@ -513,7 +498,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Restore the register cache */
- snd_soc_cache_sync(codec);
+ regcache_sync(wm9090->regmap);
}
/* We keep VMID off during standby since the combination of
@@ -537,26 +522,16 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
static int wm9090_probe(struct snd_soc_codec *codec)
{
+ struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ codec->control_data = wm9090->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- 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.
*/
@@ -624,16 +599,27 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
.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,
};
+static const struct regmap_config wm9090_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM9090_MAX_REGISTER,
+ .volatile_reg = wm9090_volatile,
+ .readable_reg = wm9090_readable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm9090_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
+};
+
+
static int wm9090_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm9090_priv *wm9090;
+ unsigned int reg;
int ret;
wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
@@ -642,6 +628,26 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
+ wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+ if (IS_ERR(wm9090->regmap)) {
+ ret = PTR_ERR(wm9090->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
+ if (ret < 0)
+ goto err;
+ if (reg != 0x9093) {
+ dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
+ if (ret < 0)
+ goto err;
+
if (i2c->dev.platform_data)
memcpy(&wm9090->pdata, i2c->dev.platform_data,
sizeof(wm9090->pdata));
@@ -650,6 +656,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9090, NULL, 0);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regmap_exit(wm9090->regmap);
return ret;
}
@@ -658,6 +673,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm9090->regmap);
return 0;
}
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 40c92ead85a3..cacc6a86b46f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -351,7 +351,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
if (ret)
goto reset_err;
- snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls,
ARRAY_SIZE(wm9705_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index b7b31f84c10b..b342ae50bcd6 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -20,10 +20,9 @@
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#include "wm9712.h"
-#define WM9712_VERSION "0.4"
-
static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg);
static int ac97_write(struct snd_soc_codec *codec,
@@ -71,6 +70,9 @@ static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
static const char *wm9712_diff_sel[] = {"Mic", "Line"};
+static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0);
+
static const struct soc_enum wm9712_enum[] = {
SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
@@ -149,9 +151,9 @@ SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
-SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
-SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
-SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv),
};
/* We have to create a fake left and right HP mixers because
@@ -619,8 +621,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
@@ -637,7 +637,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls,
ARRAY_SIZE(wm9712_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2b8479bfcd93..2d22cc70d536 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1216,7 +1216,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
reg = ac97_read(codec, AC97_CD) & 0x7fff;
ac97_write(codec, AC97_CD, reg);
- snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
ARRAY_SIZE(wm9713_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2a61094075f8..c08d1c2f346f 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -172,7 +172,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
break;
default:
WARN(1, "Unknown DCS readback method\n");
- break;
+ return;
}
dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
@@ -207,7 +207,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
/* Save the callibrated offset if we're in class W mode and
* therefore don't have any analogue signal mixed in. */
- if (hubs->class_w)
+ if (hubs->class_w && !hubs->no_cache_class_w)
hubs->class_w_dcs = dcs_cfg;
}
@@ -500,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int lineout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *control, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ bool *flag;
+
+ switch (w->shift) {
+ case WM8993_LINEOUT1N_ENA_SHIFT:
+ flag = &hubs->lineout1n_ena;
+ break;
+ case WM8993_LINEOUT1P_ENA_SHIFT:
+ flag = &hubs->lineout1p_ena;
+ break;
+ case WM8993_LINEOUT2N_ENA_SHIFT:
+ flag = &hubs->lineout2n_ena;
+ break;
+ case WM8993_LINEOUT2P_ENA_SHIFT:
+ flag = &hubs->lineout2p_ena;
+ break;
+ default:
+ WARN(1, "Unknown line output");
+ return -EINVAL;
+ }
+
+ *flag = SND_SOC_DAPM_EVENT_ON(event);
+
+ return 0;
+}
+
static const struct snd_kcontrol_new in1l_pga[] = {
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -586,14 +616,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
};
static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
};
static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
};
static const struct snd_kcontrol_new line2p_mix[] = {
@@ -613,6 +643,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)),
SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -638,9 +670,8 @@ SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
- NULL, 0,
- hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
@@ -654,10 +685,10 @@ SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
- NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+ NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+ NULL, 0),
SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
line1_mix, ARRAY_SIZE(line1_mix)),
@@ -673,14 +704,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
line2p_mix, ARRAY_SIZE(line2p_mix)),
-SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
- NULL, 0),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -834,9 +869,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+ { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -844,8 +881,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
- { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
- { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+ { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+ { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -853,9 +890,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+ { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
@@ -895,7 +934,7 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
- snd_soc_add_controls(codec, analogue_snd_controls,
+ snd_soc_add_codec_controls(codec, analogue_snd_controls,
ARRAY_SIZE(analogue_snd_controls));
snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
@@ -943,6 +982,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
int jd_scthr, int jd_thr, int micbias1_lvl,
int micbias2_lvl)
{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+ hubs->lineout1_se = !lineout1_diff;
+ hubs->lineout2_se = !lineout2_diff;
+
if (!lineout1_diff)
snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
WM8993_LINEOUT1_MODE,
@@ -952,12 +996,6 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
WM8993_LINEOUT2_MODE,
WM8993_LINEOUT2_MODE);
- /* If the line outputs are differential then we aren't presenting
- * VMID as an output and can disable it.
- */
- if (lineout1_diff && lineout2_diff)
- codec->dapm.idle_bias_off = 1;
-
if (lineout1fb)
snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
@@ -978,6 +1016,74 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
+void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val = 0;
+
+ if (hubs->lineout1_se)
+ val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se)
+ val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
+
+ /* Enable the line outputs while we power up */
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
+
+void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ /* Clamp the inputs to VMID while we ramp to charge caps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
+ break;
+
+ case SND_SOC_BIAS_ON:
+ /* Turn off any unneded single ended outputs */
+ val = 0;
+
+ if (hubs->lineout1_se && hubs->lineout1n_ena)
+ val |= WM8993_LINEOUT1N_ENA;
+
+ if (hubs->lineout1_se && hubs->lineout1p_ena)
+ val |= WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2n_ena)
+ val |= WM8993_LINEOUT2N_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2p_ena)
+ val |= WM8993_LINEOUT2P_ENA;
+
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
+ WM8993_LINEOUT1N_ENA |
+ WM8993_LINEOUT1P_ENA |
+ WM8993_LINEOUT2N_ENA |
+ WM8993_LINEOUT2P_ENA,
+ val);
+
+ if (!hubs->lineout1n_ena && !hubs->lineout1p_ena &&
+ !hubs->lineout2n_ena && !hubs->lineout2p_ena)
+ snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+ WM8993_LINEOUT_VMID_BUF_ENA, 0);
+
+ /* Remove the input clamps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, 0);
+ break;
+
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
+
MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index c674c7a502a6..5705276f4943 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -30,9 +30,18 @@ struct wm_hubs_data {
int series_startup;
int no_series_update;
+ bool no_cache_class_w;
bool class_w;
u16 class_w_dcs;
+ bool lineout1_se;
+ bool lineout1n_ena;
+ bool lineout1p_ena;
+
+ bool lineout2_se;
+ bool lineout2n_ena;
+ bool lineout2p_ena;
+
bool dcs_done_irq;
struct completion dcs_done;
};
@@ -46,5 +55,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
int micbias1_lvl, int micbias2_lvl);
extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
+extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level);
#endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index b26401f87b85..97d77b298968 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -826,7 +826,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
}
}
-static u64 davinci_pcm_dmamask = 0xffffffff;
+static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
@@ -837,7 +837,7 @@ static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &davinci_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = davinci_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 91a28de94109..88143db7e753 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -1,6 +1,7 @@
config SND_EP93XX_SOC
tristate "SoC Audio support for the Cirrus Logic EP93xx series"
depends on ARCH_EP93XX && SND_SOC
+ select SND_SOC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the EP93xx I2S or AC97 interfaces.
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
index bae5cbbbd2b2..e01cb02abd3a 100644
--- a/sound/soc/ep93xx/edb93xx.c
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -85,9 +85,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
struct snd_soc_card *card = &snd_soc_edb93xx;
int ret;
- ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
- EP93XX_SYSCON_I2SCLKDIV_ORIDE |
- EP93XX_SYSCON_I2SCLKDIV_SPOL);
+ ret = ep93xx_i2s_acquire();
if (ret)
return ret;
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index de8390449873..162dbb74f4cc 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -23,6 +23,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include <mach/hardware.h>
@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
.fifo_size = 32,
};
-struct ep93xx_runtime_data
-{
- int pointer_bytes;
- int periods;
- int period_bytes;
- struct dma_chan *dma_chan;
- struct ep93xx_dma_data dma_data;
-};
-
-static void ep93xx_pcm_dma_callback(void *data)
-{
- struct snd_pcm_substream *substream = data;
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
- rtd->pointer_bytes += rtd->period_bytes;
- rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
-
- snd_pcm_period_elapsed(substream);
-}
-
static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
{
struct ep93xx_dma_data *data = filter_param;
@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
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->cpu_dai;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct ep93xx_pcm_dma_params *dma_params;
- struct ep93xx_runtime_data *rtd;
- dma_cap_mask_t mask;
+ struct ep93xx_dma_data *dma_data;
int ret;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- return ret;
-
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
- rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
- if (!rtd)
+ dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
+ if (!dma_data)
return -ENOMEM;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_CYCLIC, mask);
-
dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
- rtd->dma_data.port = dma_params->dma_port;
- rtd->dma_data.name = dma_params->name;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- rtd->dma_data.direction = DMA_MEM_TO_DEV;
- else
- rtd->dma_data.direction = DMA_DEV_TO_MEM;
-
- rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
- &rtd->dma_data);
- if (!rtd->dma_chan) {
- kfree(rtd);
- return -EINVAL;
- }
-
- substream->runtime->private_data = rtd;
- return 0;
-}
+ dma_data->port = dma_params->dma_port;
+ dma_data->name = dma_params->name;
+ dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
-static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
+ ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
+ if (ret) {
+ kfree(dma_data);
+ return ret;
+ }
- dma_release_channel(rtd->dma_chan);
- kfree(rtd);
- return 0;
-}
+ snd_dmaengine_pcm_set_data(substream, dma_data);
-static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
- struct dma_chan *chan = rtd->dma_chan;
- struct dma_device *dma_dev = chan->device;
- struct dma_async_tx_descriptor *desc;
-
- rtd->pointer_bytes = 0;
- desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
- rtd->period_bytes * rtd->periods,
- rtd->period_bytes,
- rtd->dma_data.direction);
- if (!desc)
- return -EINVAL;
-
- desc->callback = ep93xx_pcm_dma_callback;
- desc->callback_param = substream;
-
- dmaengine_submit(desc);
return 0;
}
-static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream)
+static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
+ struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
- dmaengine_terminate_all(rtd->dma_chan);
+ snd_dmaengine_pcm_close(substream);
+ kfree(dma_data);
+ return 0;
}
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- rtd->periods = params_periods(params);
- rtd->period_bytes = params_period_bytes(params);
return 0;
}
@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- int ret;
-
- ret = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ret = ep93xx_pcm_dma_submit(substream);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ep93xx_pcm_dma_flush(substream);
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
- /* FIXME: implement this with sub-period granularity */
- return bytes_to_frames(runtime, rtd->pointer_bytes);
-}
-
static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free,
- .trigger = ep93xx_pcm_trigger,
- .pointer = ep93xx_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = ep93xx_pcm_mmap,
};
@@ -281,7 +177,7 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
}
-static u64 ep93xx_pcm_dmamask = 0xffffffff;
+static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
@@ -292,7 +188,7 @@ static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &ep93xx_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index ccae34a3f280..a193cea3cf3c 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -103,9 +103,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
struct snd_soc_card *card = &snd_soc_snappercl15;
int ret;
- ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
- EP93XX_SYSCON_I2SCLKDIV_ORIDE |
- EP93XX_SYSCON_I2SCLKDIV_SPOL);
+ ret = ep93xx_i2s_acquire();
if (ret)
return ret;
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 4f59bbaba48f..96bb92dd174c 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -311,23 +311,23 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
* should allocate a DMA buffer only for the streams that are valid.
*/
- if (pcm->streams[0].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[0].substream->dma_buffer);
+ &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
if (ret) {
dev_err(card->dev, "can't alloc playback dma buffer\n");
return ret;
}
}
- if (pcm->streams[1].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[1].substream->dma_buffer);
+ &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
if (ret) {
dev_err(card->dev, "can't alloc capture dma buffer\n");
- snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+ snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
return ret;
}
}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 3e066966d878..2eb407fa3b48 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -716,12 +716,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
}
/* Trigger the machine driver's probe function. The platform driver
- * name of the machine driver is taken from the /model property of the
+ * name of the machine driver is taken from /compatible 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. */
+ sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
+ /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
p = strrchr(sprop, ',');
if (p)
sprop = p + 1;
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index e7803d34c425..9a3f7c5ab687 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/of_platform.h>
@@ -298,7 +299,7 @@ static struct snd_pcm_ops psc_dma_ops = {
.hw_params = psc_dma_hw_params,
};
-static u64 psc_dma_dmamask = 0xffffffff;
+static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
@@ -314,18 +315,18 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &psc_dma_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (pcm->streams[0].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[0].substream->dma_buffer);
+ size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
if (rc)
goto playback_alloc_err;
}
- if (pcm->streams[1].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[1].substream->dma_buffer);
+ size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
if (rc)
goto capture_alloc_err;
}
@@ -336,8 +337,8 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
return 0;
capture_alloc_err:
- if (pcm->streams[0].substream)
- snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+ snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
playback_alloc_err:
dev_err(card->dev, "Cannot allocate buffer(s)\n");
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 0ea4a5a96e06..afbabf427f27 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -245,7 +245,7 @@ static int get_parent_cell_index(struct device_node *np)
* '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".
+ * example, "cs4270.0-004f".
*/
static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
{
@@ -267,13 +267,13 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
if (!i2c)
return -ENODEV;
- snprintf(buf, len, "%s-codec.%u-%04x", temp, i2c->adapter->nr, addr);
+ snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
return 0;
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -283,7 +283,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
@@ -336,12 +336,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
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");
+ /* Find the codec node for this SSI. */
+ codec_np = of_parse_phandle(np, "codec-handle", 0);
if (!codec_np) {
dev_err(dev, "invalid codec node\n");
return -EINVAL;
@@ -550,7 +546,7 @@ static struct platform_driver mpc8610_hpcd_driver = {
.probe = mpc8610_hpcd_probe,
.remove = __devexit_p(mpc8610_hpcd_remove),
.driver = {
- /* The name must match the 'model' property in the device tree,
+ /* The name must match 'compatible' property in the device tree,
* in lowercase letters.
*/
.name = "snd-soc-mpc8610hpcd",
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index a5d4e80a9cf4..b88987083475 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -276,7 +276,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -286,7 +286,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
@@ -543,6 +543,11 @@ static struct platform_driver p1022_ds_driver = {
.probe = p1022_ds_probe,
.remove = __devexit_p(p1022_ds_remove),
.driver = {
+ /*
+ * The name must match 'compatible' property in the device tree,
+ * in lowercase letters.
+ */
+ .name = "snd-soc-p1022ds",
.owner = THIS_MODULE,
},
};
@@ -556,33 +561,6 @@ static int __init p1022_ds_init(void)
{
struct device_node *guts_np;
struct resource res;
- const char *sprop;
-
- /*
- * Check if we're actually running on a P1022DS. Older device trees
- * have a model of "fsl,P1022" and newer ones use "fsl,P1022DS", so we
- * need to support both. The SSI driver uses that property to link to
- * the machine driver, so have to match it.
- */
- sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
- if (!sprop) {
- pr_err("snd-soc-p1022ds: missing /model node");
- return -ENODEV;
- }
-
- pr_debug("snd-soc-p1022ds: board model name is %s\n", sprop);
-
- /*
- * The name of this board, taken from the device tree. Normally, this is a*
- * fixed string, but some P1022DS device trees have a /model property of
- * "fsl,P1022", and others have "fsl,P1022DS".
- */
- if (strcasecmp(sprop, "fsl,p1022ds") == 0)
- p1022_ds_driver.driver.name = "snd-soc-p1022ds";
- else if (strcasecmp(sprop, "fsl,p1022") == 0)
- p1022_ds_driver.driver.name = "snd-soc-p1022";
- else
- return -ENODEV;
/* Get the physical address of the global utilities registers */
guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 738391757f2c..810acaa09009 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,9 +1,6 @@
menuconfig SND_IMX_SOC
tristate "SoC Audio for Freescale i.MX CPUs"
depends on ARCH_MXC
- select SND_PCM
- select FIQ
- select SND_SOC_AC97_BUS
help
Say Y or M if you want to add support for codecs attached to
the i.MX SSI interface.
@@ -11,10 +8,23 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
+config SND_SOC_IMX_SSI
+ tristate
+
+config SND_SOC_IMX_PCM
+ tristate
+
config SND_MXC_SOC_FIQ
tristate
+ select FIQ
+ select SND_SOC_IMX_PCM
config SND_MXC_SOC_MX2
+ select SND_SOC_DMAENGINE_PCM
+ tristate
+ select SND_SOC_IMX_PCM
+
+config SND_SOC_IMX_AUDMUX
tristate
config SND_MXC_SOC_WM1133_EV1
@@ -22,6 +32,8 @@ config SND_MXC_SOC_WM1133_EV1
depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
select SND_SOC_WM8350
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Enable support for audio on the i.MX31ADS with the WM1133-EV1
PMIC board with WM8835x fitted.
@@ -31,6 +43,8 @@ config SND_SOC_MX27VIS_AIC32X4
depends on MACH_IMX27_VISSTRIM_M10 && I2C
select SND_SOC_TLV320AIC32X4
select SND_MXC_SOC_MX2
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Say Y if you want to add support for SoC audio on Visstrim SM10
board with TLV320AIC32X4 codec.
@@ -38,8 +52,11 @@ config SND_SOC_MX27VIS_AIC32X4
config SND_SOC_PHYCORE_AC97
tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
depends on MACH_PCM043 || MACH_PCA100
+ select SND_SOC_AC97_BUS
select SND_SOC_WM9712
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Say Y if you want to add support for SoC audio on Phytec phyCORE
and phyCARD boards in AC97 mode
@@ -53,6 +70,8 @@ config SND_SOC_EUKREA_TLV320
depends on I2C
select SND_SOC_TLV320AIC23
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Enable I2S based access to the TLV320AIC23B codec attached
to the SSI interface
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index d6d609ba7e24..f5db3e92d0d1 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -1,11 +1,14 @@
# i.MX Platform Support
-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
+snd-soc-imx-ssi-objs := imx-ssi.o
+snd-soc-imx-audmux-objs := imx-audmux.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
+obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
+obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
+
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
+snd-soc-imx-pcm-y := imx-pcm.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o
# i.MX Machine Support
snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index 1c1fdd10f73f..7d4475cfdb24 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -26,6 +26,7 @@
#include "../codecs/tlv320aic23.h"
#include "imx-ssi.h"
+#include "imx-audmux.h"
#define CODEC_CLOCK 12000000
@@ -97,12 +98,43 @@ static struct platform_device *eukrea_tlv320_snd_device;
static int __init eukrea_tlv320_init(void)
{
int ret;
-
- if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()
- && !machine_is_eukrea_cpuimx35sd()
- && !machine_is_eukrea_cpuimx51sd())
+ int int_port = 0, ext_port;
+
+ if (machine_is_eukrea_cpuimx27()) {
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_TCLKDIR |
+ IMX_AUDMUX_V1_PCR_RFSDIR |
+ IMX_AUDMUX_V1_PCR_RCLKDIR |
+ IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+ IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
+ );
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+ );
+ } else if (machine_is_eukrea_cpuimx25sd() ||
+ machine_is_eukrea_cpuimx35sd() ||
+ machine_is_eukrea_cpuimx51sd()) {
+ ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3;
+ imx_audmux_v2_configure_port(int_port,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(ext_port),
+ IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)
+ );
+ imx_audmux_v2_configure_port(ext_port,
+ IMX_AUDMUX_V2_PTCR_SYN,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)
+ );
+ } else {
/* return happy. We might run on a totally different machine */
return 0;
+ }
eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
if (!eukrea_tlv320_snd_device)
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/sound/soc/imx/imx-audmux.c
index 8cced35009bd..a839494c5ea8 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/sound/soc/imx/imx-audmux.c
@@ -1,4 +1,6 @@
/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
* Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
*
* Initial development of this code was funded by
@@ -15,20 +17,25 @@
* GNU General Public License for more details.
*/
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <mach/audmux.h>
-#include <mach/hardware.h>
+
+#include "imx-audmux.h"
+
+#define DRIVER_NAME "imx-audmux"
static struct clk *audmux_clk;
static void __iomem *audmux_base;
-#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8)
-#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
+#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8)
+#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
#ifdef CONFIG_DEBUG_FS
static struct dentry *audmux_debugfs_root;
@@ -75,8 +82,8 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
if (audmux_clk)
clk_enable(audmux_clk);
- ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port));
- pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port));
+ ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
+ pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
if (audmux_clk)
clk_disable(audmux_clk);
@@ -84,7 +91,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
pdcr, ptcr);
- if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR)
+ if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"TxFS output from %s, ",
audmux_port_string((ptcr >> 27) & 0x7));
@@ -92,7 +99,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"TxFS input, ");
- if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR)
+ if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"TxClk output from %s",
audmux_port_string((ptcr >> 22) & 0x7));
@@ -102,11 +109,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
- if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) {
+ if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"Port is symmetric");
} else {
- if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR)
+ if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"RxFS output from %s, ",
audmux_port_string((ptcr >> 17) & 0x7));
@@ -114,7 +121,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"RxFS input, ");
- if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR)
+ if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
"RxClk output from %s",
audmux_port_string((ptcr >> 12) & 0x7));
@@ -140,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = {
.llseek = default_llseek,
};
-static void audmux_debugfs_init(void)
+static void __init audmux_debugfs_init(void)
{
int i;
char buf[20];
@@ -159,61 +166,149 @@ static void audmux_debugfs_init(void)
i);
}
}
+
+static void __devexit audmux_debugfs_remove(void)
+{
+ debugfs_remove_recursive(audmux_debugfs_root);
+}
#else
static inline void audmux_debugfs_init(void)
{
}
+
+static inline void audmux_debugfs_remove(void)
+{
+}
#endif
-int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+enum imx_audmux_type {
+ IMX21_AUDMUX,
+ IMX31_AUDMUX,
+} audmux_type;
+
+static struct platform_device_id imx_audmux_ids[] = {
+ {
+ .name = "imx21-audmux",
+ .driver_data = IMX21_AUDMUX,
+ }, {
+ .name = "imx31-audmux",
+ .driver_data = IMX31_AUDMUX,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_audmux_ids);
+
+static const struct of_device_id imx_audmux_dt_ids[] = {
+ { .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], },
+ { .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids);
+
+static const uint8_t port_mapping[] = {
+ 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
+};
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
+{
+ if (audmux_type != IMX21_AUDMUX)
+ return -EINVAL;
+
+ if (!audmux_base)
+ return -ENOSYS;
+
+ if (port >= ARRAY_SIZE(port_mapping))
+ return -EINVAL;
+
+ writel(pcr, audmux_base + port_mapping[port]);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
unsigned int pdcr)
{
+ if (audmux_type != IMX31_AUDMUX)
+ return -EINVAL;
+
if (!audmux_base)
return -ENOSYS;
if (audmux_clk)
clk_enable(audmux_clk);
- writel(ptcr, audmux_base + MXC_AUDMUX_V2_PTCR(port));
- writel(pdcr, audmux_base + MXC_AUDMUX_V2_PDCR(port));
+ writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
+ writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
if (audmux_clk)
clk_disable(audmux_clk);
return 0;
}
-EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
+EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
-static int mxc_audmux_v2_init(void)
+static int __devinit imx_audmux_probe(struct platform_device *pdev)
{
- int ret;
- if (cpu_is_mx51()) {
- audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
- } else if (cpu_is_mx31()) {
- audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
- } else if (cpu_is_mx35()) {
- audmux_clk = clk_get(NULL, "audmux");
- if (IS_ERR(audmux_clk)) {
- ret = PTR_ERR(audmux_clk);
- printk(KERN_ERR "%s: cannot get clock: %d\n", __func__,
- ret);
- return ret;
- }
- audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
- } else if (cpu_is_mx25()) {
- audmux_clk = clk_get(NULL, "audmux");
- if (IS_ERR(audmux_clk)) {
- ret = PTR_ERR(audmux_clk);
- printk(KERN_ERR "%s: cannot get clock: %d\n", __func__,
- ret);
- return ret;
- }
- audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
+ struct resource *res;
+ const struct of_device_id *of_id =
+ of_match_device(imx_audmux_dt_ids, &pdev->dev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ audmux_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!audmux_base)
+ return -EADDRNOTAVAIL;
+
+ audmux_clk = clk_get(&pdev->dev, "audmux");
+ if (IS_ERR(audmux_clk)) {
+ dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
+ PTR_ERR(audmux_clk));
+ audmux_clk = NULL;
}
- audmux_debugfs_init();
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ audmux_type = pdev->id_entry->driver_data;
+ if (audmux_type == IMX31_AUDMUX)
+ audmux_debugfs_init();
+
+ return 0;
+}
+
+static int __devexit imx_audmux_remove(struct platform_device *pdev)
+{
+ if (audmux_type == IMX31_AUDMUX)
+ audmux_debugfs_remove();
+ clk_put(audmux_clk);
return 0;
}
-postcore_initcall(mxc_audmux_v2_init);
+static struct platform_driver imx_audmux_driver = {
+ .probe = imx_audmux_probe,
+ .remove = __devexit_p(imx_audmux_remove),
+ .id_table = imx_audmux_ids,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = imx_audmux_dt_ids,
+ }
+};
+
+static int __init imx_audmux_init(void)
+{
+ return platform_driver_register(&imx_audmux_driver);
+}
+subsys_initcall(imx_audmux_init);
+
+static void __exit imx_audmux_exit(void)
+{
+ platform_driver_unregister(&imx_audmux_driver);
+}
+module_exit(imx_audmux_exit);
+
+MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h
new file mode 100644
index 000000000000..04ebbab8d7b9
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.h
@@ -0,0 +1,60 @@
+#ifndef __IMX_AUDMUX_H
+#define __IMX_AUDMUX_H
+
+#define MX27_AUDMUX_HPCR1_SSI0 0
+#define MX27_AUDMUX_HPCR2_SSI1 1
+#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
+#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
+#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
+#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
+
+#define MX31_AUDMUX_PORT1_SSI0 0
+#define MX31_AUDMUX_PORT2_SSI1 1
+#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
+#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
+#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
+#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
+
+#define MX51_AUDMUX_PORT1_SSI0 0
+#define MX51_AUDMUX_PORT2_SSI1 1
+#define MX51_AUDMUX_PORT3 2
+#define MX51_AUDMUX_PORT4 3
+#define MX51_AUDMUX_PORT5 4
+#define MX51_AUDMUX_PORT6 5
+#define MX51_AUDMUX_PORT7 6
+
+/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
+#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
+#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
+#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
+#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
+#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
+#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
+#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
+#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
+#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
+#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
+
+/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
+#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
+#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
+#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
+#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
+#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
+#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
+#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
+#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
+
+#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
+#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
+#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
+#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+ unsigned int pdcr);
+
+#endif /* __IMX_AUDMUX_H */
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 5780c9b9d569..e43c8fa2788b 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -27,212 +27,54 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
-#include "imx-ssi.h"
-
-struct imx_pcm_runtime_data {
- int period_bytes;
- int periods;
- int dma;
- unsigned long offset;
- unsigned long size;
- void *buf;
- int period_time;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *dma_chan;
- struct imx_dma_data dma_data;
-};
-
-static void audio_dma_irq(void *data)
-{
- struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- iprtd->offset += iprtd->period_bytes;
- iprtd->offset %= iprtd->period_bytes * iprtd->periods;
-
- snd_pcm_period_elapsed(substream);
-}
+#include "imx-pcm.h"
static bool filter(struct dma_chan *chan, void *param)
{
- struct imx_pcm_runtime_data *iprtd = param;
-
if (!imx_dma_is_general_purpose(chan))
return false;
- chan->private = &iprtd->dma_data;
+ chan->private = param;
- return true;
+ return true;
}
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
+static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct imx_pcm_dma_params *dma_params;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
struct dma_slave_config slave_config;
- dma_cap_mask_t mask;
- enum dma_slave_buswidth buswidth;
int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
- iprtd->dma_data.priority = DMA_PRIO_HIGH;
- iprtd->dma_data.dma_request = dma_params->dma;
-
- /* Try to grab a DMA channel */
- if (!iprtd->dma_chan) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
- }
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- default:
- return 0;
- }
+ ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
+ if (ret)
+ return ret;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = dma_params->dma_addr;
- slave_config.dst_addr_width = buswidth;
slave_config.dst_maxburst = dma_params->burstsize;
} else {
- slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = dma_params->dma_addr;
- slave_config.src_addr_width = buswidth;
slave_config.src_maxburst = dma_params->burstsize;
}
- ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+ ret = dmaengine_slave_config(chan, &slave_config);
if (ret)
return ret;
- return 0;
-}
-
-static int snd_imx_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_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- struct imx_pcm_dma_params *dma_params;
- int ret;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- ret = imx_ssi_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
-
- iprtd->size = params_buffer_bytes(params);
- iprtd->periods = params_periods(params);
- iprtd->period_bytes = params_period_bytes(params);
- iprtd->offset = 0;
- iprtd->period_time = HZ / (params_rate(params) /
- params_period_size(params));
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- dma_addr = runtime->dma_addr;
-
- iprtd->buf = (unsigned int *)substream->dma_buffer.area;
-
- iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
- iprtd->period_bytes * iprtd->periods,
- iprtd->period_bytes,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- if (!iprtd->desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return -EINVAL;
- }
-
- iprtd->desc->callback = audio_dma_irq;
- iprtd->desc->callback_param = substream;
-
- return 0;
-}
-
-static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- if (iprtd->dma_chan) {
- dma_release_channel(iprtd->dma_chan);
- iprtd->dma_chan = NULL;
- }
-
- return 0;
-}
-
-static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct imx_pcm_dma_params *dma_params;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
return 0;
}
-static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(iprtd->desc);
-
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dmaengine_terminate_all(iprtd->dma_chan);
-
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
- bytes_to_frames(substream->runtime, iprtd->offset));
-
- return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
static struct snd_pcm_hardware snd_imx_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -254,33 +96,37 @@ static struct snd_pcm_hardware snd_imx_hardware = {
static int snd_imx_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_pcm_dma_params *dma_params;
+ struct imx_dma_data *dma_data;
int ret;
- iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
- if (iprtd == NULL)
- return -ENOMEM;
- runtime->private_data = iprtd;
+ snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0) {
- kfree(iprtd);
- return ret;
+ dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
+ dma_data->peripheral_type = IMX_DMATYPE_SSI;
+ dma_data->priority = DMA_PRIO_HIGH;
+ dma_data->dma_request = dma_params->dma;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
+ if (ret) {
+ kfree(dma_data);
+ return 0;
}
- snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+ snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+ struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
- kfree(iprtd);
+ snd_dmaengine_pcm_close(substream);
+ kfree(dma_data);
return 0;
}
@@ -290,10 +136,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
- .hw_free = snd_imx_pcm_hw_free,
- .prepare = snd_imx_pcm_prepare,
- .trigger = snd_imx_pcm_trigger,
- .pointer = snd_imx_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
};
@@ -305,11 +149,6 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
{
- struct imx_ssi *ssi = platform_get_drvdata(pdev);
-
- ssi->dma_params_tx.burstsize = 6;
- ssi->dma_params_rx.burstsize = 4;
-
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
}
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c
new file mode 100644
index 000000000000..93dc360b1777
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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/dma-mapping.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include "imx-pcm.h"
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+
+ pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
+ runtime->dma_area,
+ runtime->dma_addr,
+ 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)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = IMX_SSI_DMABUF_SIZE;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+
+ return 0;
+}
+
+static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
+
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &imx_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(imx_pcm_new);
+
+void imx_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(imx_pcm_free);
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
new file mode 100644
index 000000000000..b5f5c3acf34d
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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 _IMX_PCM_H
+#define _IMX_PCM_H
+
+/*
+ * Do not change this as the FIQ handler depends on this size
+ */
+#define IMX_SSI_DMABUF_SIZE (64 * 1024)
+
+struct imx_pcm_dma_params {
+ int dma;
+ unsigned long dma_addr;
+ int burstsize;
+};
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma);
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void imx_pcm_free(struct snd_pcm *pcm);
+
+#endif /* _IMX_PCM_H */
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 01d1f749cf02..4f81ed456325 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -112,7 +112,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
break;
case SND_SOC_DAIFMT_DSP_A:
/* data on rising edge of bclk, frame high 1clk before data */
- strcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
+ strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
break;
}
@@ -233,6 +233,23 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}
+static int imx_ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+ struct imx_pcm_dma_params *dma_data;
+
+ /* Tx/Rx config */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &ssi->dma_params_tx;
+ else
+ dma_data = &ssi->dma_params_rx;
+
+ snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+ return 0;
+}
+
/*
* Should only be called when port is inactive (i.e. SSIEN = 0),
* although can be called multiple times by upper layers.
@@ -242,23 +259,17 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
- struct imx_pcm_dma_params *dma_data;
u32 reg, sccr;
/* Tx/Rx config */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = SSI_STCCR;
- dma_data = &ssi->dma_params_tx;
- } else {
+ else
reg = SSI_SRCCR;
- dma_data = &ssi->dma_params_rx;
- }
if (ssi->flags & IMX_SSI_SYN)
reg = SSI_STCCR;
- snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
/* DAI data (word) size */
@@ -343,6 +354,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}
static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+ .startup = imx_ssi_startup,
.hw_params = imx_ssi_hw_params,
.set_fmt = imx_ssi_set_dai_fmt,
.set_clkdiv = imx_ssi_set_dai_clkdiv,
@@ -351,94 +363,6 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
.trigger = imx_ssi_trigger,
};
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
-
- ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
-
- pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
- runtime->dma_area,
- runtime->dma_addr,
- 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)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = IMX_SSI_DMABUF_SIZE;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
-
- return 0;
-}
-
-static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &imx_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(imx_pcm_new);
-
-void imx_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(imx_pcm_free);
-
static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
{
struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
@@ -656,7 +580,7 @@ static int imx_ssi_probe(struct platform_device *pdev)
ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
- ssi->dma_params_tx.burstsize = 4;
+ ssi->dma_params_tx.burstsize = 6;
ssi->dma_params_rx.burstsize = 4;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 1072dfb53e47..5744e86ca878 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -187,12 +187,7 @@
#include <linux/dmaengine.h>
#include <mach/dma.h>
-
-struct imx_pcm_dma_params {
- int dma;
- unsigned long dma_addr;
- int burstsize;
-};
+#include "imx-pcm.h"
struct imx_ssi {
struct platform_device *ac97_dev;
@@ -218,13 +213,4 @@ struct imx_ssi {
struct platform_device *soc_platform_pdev_fiq;
};
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
-void imx_pcm_free(struct snd_pcm *pcm);
-
-/*
- * Do not change this as the FIQ handler depends on this size
- */
-#define IMX_SSI_DMABUF_SIZE (64 * 1024)
-
#endif /* _IMX_SSI_H */
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c
index 3c2eed9094d5..f6d04ad4bb39 100644
--- a/sound/soc/imx/mx27vis-aic32x4.c
+++ b/sound/soc/imx/mx27vis-aic32x4.c
@@ -25,15 +25,36 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
#include <asm/mach-types.h>
-#include <mach/audmux.h>
+#include <mach/iomux-mx27.h>
#include "../codecs/tlv320aic32x4.h"
#include "imx-ssi.h"
+#include "imx-audmux.h"
+
+#define MX27VIS_AMP_GAIN 0
+#define MX27VIS_AMP_MUTE 1
+
+#define MX27VIS_PIN_G0 (GPIO_PORTF + 9)
+#define MX27VIS_PIN_G1 (GPIO_PORTF + 8)
+#define MX27VIS_PIN_SDL (GPIO_PORTE + 5)
+#define MX27VIS_PIN_SDR (GPIO_PORTF + 7)
+
+static int mx27vis_amp_gain;
+static int mx27vis_amp_mute;
+
+static const int mx27vis_amp_pins[] = {
+ MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT,
+};
static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -74,6 +95,76 @@ static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
.hw_params = mx27vis_aic32x4_hw_params,
};
+static int mx27vis_amp_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int value = ucontrol->value.integer.value[0];
+ unsigned int reg = mc->reg;
+ int max = mc->max;
+
+ if (value > max)
+ return -EINVAL;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ gpio_set_value(MX27VIS_PIN_G0, value & 1);
+ gpio_set_value(MX27VIS_PIN_G1, value >> 1);
+ mx27vis_amp_gain = value;
+ break;
+ case MX27VIS_AMP_MUTE:
+ gpio_set_value(MX27VIS_PIN_SDL, value & 1);
+ gpio_set_value(MX27VIS_PIN_SDR, value >> 1);
+ mx27vis_amp_mute = value;
+ break;
+ }
+ return 0;
+}
+
+static int mx27vis_amp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ ucontrol->value.integer.value[0] = mx27vis_amp_gain;
+ break;
+ case MX27VIS_AMP_MUTE:
+ ucontrol->value.integer.value[0] = mx27vis_amp_mute;
+ break;
+ }
+ return 0;
+}
+
+/* From 6dB to 24dB in steps of 6dB */
+static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
+
+static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = {
+ SOC_DAPM_PIN_SWITCH("External Mic"),
+ SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0,
+ mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv),
+ SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0,
+ mx27vis_amp_get, mx27vis_amp_set),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("External Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+ {"Mic Bias", NULL, "External Mic"},
+ {"IN1_R", NULL, "Mic Bias"},
+ {"IN2_R", NULL, "Mic Bias"},
+ {"IN3_R", NULL, "Mic Bias"},
+ {"IN1_L", NULL, "Mic Bias"},
+ {"IN2_L", NULL, "Mic Bias"},
+ {"IN3_L", NULL, "Mic Bias"},
+};
+
static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
.name = "tlv320aic32x4",
.stream_name = "TLV320AIC32X4",
@@ -89,50 +180,66 @@ static struct snd_soc_card mx27vis_aic32x4 = {
.owner = THIS_MODULE,
.dai_link = &mx27vis_aic32x4_dai,
.num_links = 1,
+ .controls = mx27vis_aic32x4_controls,
+ .num_controls = ARRAY_SIZE(mx27vis_aic32x4_controls),
+ .dapm_widgets = aic32x4_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets),
+ .dapm_routes = aic32x4_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
-static struct platform_device *mx27vis_aic32x4_snd_device;
-
-static int __init mx27vis_aic32x4_init(void)
+static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
{
int ret;
- mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1);
- if (!mx27vis_aic32x4_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4);
- ret = platform_device_add(mx27vis_aic32x4_snd_device);
-
+ mx27vis_aic32x4.dev = &pdev->dev;
+ ret = snd_soc_register_card(&mx27vis_aic32x4);
if (ret) {
- printk(KERN_ERR "ASoC: Platform device allocation failed\n");
- platform_device_put(mx27vis_aic32x4_snd_device);
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ return ret;
}
/* Connect SSI0 as clock slave to SSI1 external pins */
- mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_TFSDIR |
- MXC_AUDMUX_V1_PCR_TCLKDIR |
- MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_TCLKDIR |
+ IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
);
- mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+ imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
);
+ ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
+ ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP");
+ if (ret)
+ printk(KERN_ERR "ASoC: unable to setup gpios\n");
+
return ret;
}
-static void __exit mx27vis_aic32x4_exit(void)
+static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
{
- platform_device_unregister(mx27vis_aic32x4_snd_device);
+ snd_soc_unregister_card(&mx27vis_aic32x4);
+
+ return 0;
}
-module_init(mx27vis_aic32x4_init);
-module_exit(mx27vis_aic32x4_exit);
+static struct platform_driver mx27vis_aic32x4_audio_driver = {
+ .driver = {
+ .name = "mx27vis",
+ .owner = THIS_MODULE,
+ },
+ .probe = mx27vis_aic32x4_probe,
+ .remove = __devexit_p(mx27vis_aic32x4_remove),
+};
+
+module_platform_driver(mx27vis_aic32x4_audio_driver);
MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mx27vis");
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c
index 6ac12111de6a..f8da6dd115ed 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/imx/phycore-ac97.c
@@ -19,6 +19,8 @@
#include <sound/soc.h>
#include <asm/mach-types.h>
+#include "imx-audmux.h"
+
static struct snd_soc_card imx_phycore;
static struct snd_soc_ops imx_phycore_hifi_ops = {
@@ -50,9 +52,32 @@ static int __init imx_phycore_init(void)
{
int ret;
- if (!machine_is_pcm043() && !machine_is_pca100())
+ if (machine_is_pca100()) {
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V1_PCR_TFCSEL(3) |
+ IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
+ IMX_AUDMUX_V1_PCR_RXDSEL(3));
+ imx_audmux_v1_configure_port(3,
+ IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V1_PCR_TFCSEL(0) |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_RXDSEL(0));
+ } else if (machine_is_pcm043()) {
+ imx_audmux_v2_configure_port(3,
+ IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V2_PTCR_TFSEL(0) |
+ IMX_AUDMUX_V2_PTCR_TFSDIR,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(0));
+ imx_audmux_v2_configure_port(0,
+ IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V2_PTCR_TCSEL(3) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
+ IMX_AUDMUX_V2_PDCR_RXDSEL(3));
+ } else {
/* return happy. We might run on a totally different machine */
return 0;
+ }
imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
if (!imx_phycore_snd_ac97_device)
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
index 37480c90e997..fe54a69073e5 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -21,10 +21,9 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <mach/audmux.h>
-
#include "imx-ssi.h"
#include "../codecs/wm8350.h"
+#include "imx-audmux.h"
/* There is a silicon mic on the board optionally connected via a solder pad
* SP1. Define this to enable it.
@@ -268,17 +267,17 @@ static int __init wm1133_ev1_audio_init(void)
unsigned int ptcr, pdcr;
/* SSI0 mastered by port 5 */
- ptcr = MXC_AUDMUX_V2_PTCR_SYN |
- MXC_AUDMUX_V2_PTCR_TFSDIR |
- MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
- MXC_AUDMUX_V2_PTCR_TCLKDIR |
- MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
- pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
- mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
-
- ptcr = MXC_AUDMUX_V2_PTCR_SYN;
- pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
- mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
+
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN;
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
if (!wm1133_ev1_snd_device)
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index 0097c3b13a1a..e8aaff18d7cc 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -91,56 +91,52 @@ static struct snd_soc_card qi_lb60 = {
.num_dapm_routes = ARRAY_SIZE(qi_lb60_routes),
};
-static struct platform_device *qi_lb60_snd_device;
-
static const struct gpio qi_lb60_gpios[] = {
{ QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" },
{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
};
-static int __init qi_lb60_init(void)
+static int __devinit qi_lb60_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &qi_lb60;
int ret;
- qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
-
- if (!qi_lb60_snd_device)
- return -ENOMEM;
-
ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
- if (ret) {
- pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret);
- goto err_device_put;
- }
+ if (ret)
+ return ret;
- platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
+ card->dev = &pdev->dev;
- ret = platform_device_add(qi_lb60_snd_device);
+ ret = snd_soc_register_card(card);
if (ret) {
- pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
- goto err_unset_pdata;
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
}
-
- return 0;
-
-err_unset_pdata:
- platform_set_drvdata(qi_lb60_snd_device, NULL);
-/*err_gpio_free_array:*/
- gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-err_device_put:
- platform_device_put(qi_lb60_snd_device);
-
return ret;
}
-module_init(qi_lb60_init);
-static void __exit qi_lb60_exit(void)
+static int __devexit qi_lb60_remove(struct platform_device *pdev)
{
- platform_device_unregister(qi_lb60_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
+ return 0;
}
-module_exit(qi_lb60_exit);
+
+static struct platform_driver qi_lb60_driver = {
+ .driver = {
+ .name = "qi-lb60-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = qi_lb60_probe,
+ .remove = __devexit_p(qi_lb60_remove),
+};
+
+module_platform_driver(qi_lb60_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qi-lb60-audio");
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index d03854027128..b9f16598324c 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -55,7 +55,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
.fifo_size = 0,
};
-static u64 kirkwood_dma_dmamask = 0xFFFFFFFFUL;
+static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
{
@@ -324,7 +324,7 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &kirkwood_dma_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = kirkwood_dma_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 55d2ed3df30d..80bd59c33be4 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -71,41 +71,41 @@ static struct snd_soc_card openrd_client = {
.num_links = ARRAY_SIZE(openrd_client_dai),
};
-static struct platform_device *openrd_client_snd_device;
-
-static int __init openrd_client_init(void)
+static int __devinit openrd_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &openrd_client;
int ret;
- if (!machine_is_openrd_client() && !machine_is_openrd_ultimate())
- return 0;
-
- openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
- if (!openrd_client_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(openrd_client_snd_device,
- &openrd_client);
-
- ret = platform_device_add(openrd_client_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(openrd_client_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-static void __exit openrd_client_exit(void)
+static int __devexit openrd_remove(struct platform_device *pdev)
{
- platform_device_unregister(openrd_client_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(openrd_client_init);
-module_exit(openrd_client_exit);
+static struct platform_driver openrd_driver = {
+ .driver = {
+ .name = "openrd-client-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = openrd_probe,
+ .remove = __devexit_p(openrd_remove),
+};
+
+module_platform_driver(openrd_driver);
/* Module information */
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:soc-audio");
+MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index b47cc4e9b746..f8983635f7ef 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -80,7 +80,6 @@ static struct snd_soc_dai_link t5325_dai[] = {
},
};
-
static struct snd_soc_card t5325 = {
.name = "t5325",
.owner = THIS_MODULE,
@@ -93,38 +92,40 @@ static struct snd_soc_card t5325 = {
.num_dapm_routes = ARRAY_SIZE(t5325_route),
};
-static struct platform_device *t5325_snd_device;
-
-static int __init t5325_init(void)
+static int __devinit t5325_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &t5325;
int ret;
- if (!machine_is_t5325())
- return 0;
-
- t5325_snd_device = platform_device_alloc("soc-audio", -1);
- if (!t5325_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(t5325_snd_device,
- &t5325);
-
- ret = platform_device_add(t5325_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(t5325_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-module_init(t5325_init);
-static void __exit t5325_exit(void)
+static int __devexit t5325_remove(struct platform_device *pdev)
{
- platform_device_unregister(t5325_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_exit(t5325_exit);
+
+static struct platform_driver t5325_driver = {
+ .driver = {
+ .name = "t5325-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = t5325_probe,
+ .remove = __devexit_p(t5325_remove),
+};
+
+module_platform_driver(t5325_driver);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 6f77eef0f131..2937e54da49e 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -235,7 +235,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
snd_soc_dapm_enable_pin(dapm, "Headphones");
snd_soc_dapm_enable_pin(dapm, "Mic");
- ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+ ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls,
ARRAY_SIZE(mfld_snd_controls));
if (ret_val) {
pr_err("soc_add_controls failed %d", ret_val);
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index e4ba8d5f25fa..99a997f19bb9 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,7 +1,7 @@
menuconfig SND_MXS_SOC
tristate "SoC Audio for Freescale MXS CPUs"
depends on ARCH_MXS
- select SND_PCM
+ select SND_SOC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 105f42a394df..6ca1f46d84a4 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -34,10 +34,16 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include "mxs-pcm.h"
+struct mxs_pcm_dma_data {
+ struct mxs_dma_data dma_data;
+ struct mxs_pcm_dma_params *dma_params;
+};
+
static struct snd_pcm_hardware snd_mxs_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -58,21 +64,10 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
};
-static void audio_dma_irq(void *data)
-{
- struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- iprtd->offset += iprtd->period_bytes;
- iprtd->offset %= iprtd->period_bytes * iprtd->periods;
- snd_pcm_period_elapsed(substream);
-}
-
static bool filter(struct dma_chan *chan, void *param)
{
- struct mxs_pcm_runtime_data *iprtd = param;
- struct mxs_pcm_dma_params *dma_params = iprtd->dma_params;
+ struct mxs_pcm_dma_data *pcm_dma_data = param;
+ struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
if (!mxs_dma_is_apbx(chan))
return false;
@@ -80,150 +75,51 @@ static bool filter(struct dma_chan *chan, void *param)
if (chan->chan_id != dma_params->chan_num)
return false;
- chan->private = &iprtd->dma_data;
+ chan->private = &pcm_dma_data->dma_data;
return true;
}
-static int mxs_dma_alloc(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
- dma_cap_mask_t mask;
-
- iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq;
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
-
- return 0;
-}
-
static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- int ret;
-
- ret = mxs_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
-
- iprtd->size = params_buffer_bytes(params);
- iprtd->periods = params_periods(params);
- iprtd->period_bytes = params_period_bytes(params);
- iprtd->offset = 0;
- iprtd->period_time = HZ / (params_rate(params) /
- params_period_size(params));
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- dma_addr = runtime->dma_addr;
-
- iprtd->buf = substream->dma_buffer.area;
-
- iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
- iprtd->period_bytes * iprtd->periods,
- iprtd->period_bytes,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- if (!iprtd->desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return -EINVAL;
- }
-
- iprtd->desc->callback = audio_dma_irq;
- iprtd->desc->callback_param = substream;
-
- return 0;
-}
-
-static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- if (iprtd->dma_chan) {
- dma_release_channel(iprtd->dma_chan);
- iprtd->dma_chan = NULL;
- }
-
- return 0;
-}
-
-static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(iprtd->desc);
-
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dmaengine_terminate_all(iprtd->dma_chan);
-
- break;
- default:
- return -EINVAL;
- }
-
return 0;
}
-static snd_pcm_uframes_t snd_mxs_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
static int snd_mxs_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mxs_pcm_dma_data *pcm_dma_data;
int ret;
- iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
- if (iprtd == NULL)
+ pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
+ if (pcm_dma_data == NULL)
return -ENOMEM;
- runtime->private_data = iprtd;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0) {
- kfree(iprtd);
+ pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
+ if (ret) {
+ kfree(pcm_dma_data);
return ret;
}
snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
+ snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
+
return 0;
}
static int snd_mxs_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
+ struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
- kfree(iprtd);
+ snd_dmaengine_pcm_close(substream);
+ kfree(pcm_dma_data);
return 0;
}
@@ -244,9 +140,8 @@ static struct snd_pcm_ops mxs_pcm_ops = {
.close = snd_mxs_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_mxs_pcm_hw_params,
- .hw_free = snd_mxs_pcm_hw_free,
- .trigger = snd_mxs_pcm_trigger,
- .pointer = snd_mxs_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = snd_mxs_pcm_mmap,
};
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index f55ac4f7a76a..5f01a9124b3d 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,25 +19,9 @@
#ifndef _MXS_PCM_H
#define _MXS_PCM_H
-#include <mach/dma.h>
-
struct mxs_pcm_dma_params {
int chan_irq;
int chan_num;
};
-struct mxs_pcm_runtime_data {
- int period_bytes;
- int periods;
- int dma;
- unsigned long offset;
- unsigned long size;
- void *buf;
- int period_time;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *dma_chan;
- struct mxs_dma_data dma_data;
- struct mxs_pcm_dma_params *dma_params;
-};
-
#endif
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index f204dbac11d4..12be05b16880 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -630,7 +630,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
if (pdev->id >= ARRAY_SIZE(mxs_saif))
return -EINVAL;
- saif = kzalloc(sizeof(*saif), GFP_KERNEL);
+ saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
if (!saif)
return -ENOMEM;
@@ -655,29 +655,16 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = PTR_ERR(saif->clk);
dev_err(&pdev->dev, "Cannot get the clock: %d\n",
ret);
- goto failed_clk;
+ return ret;
}
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores) {
- ret = -ENODEV;
- dev_err(&pdev->dev, "failed to get io resource: %d\n",
- ret);
- goto failed_get_resource;
- }
- if (!request_mem_region(iores->start, resource_size(iores),
- "mxs-saif")) {
- dev_err(&pdev->dev, "request_mem_region failed\n");
- ret = -EBUSY;
- goto failed_get_resource;
- }
-
- saif->base = ioremap(iores->start, resource_size(iores));
+ saif->base = devm_request_and_ioremap(&pdev->dev, iores);
if (!saif->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENODEV;
- goto failed_ioremap;
+ goto failed_get_resource;
}
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -685,7 +672,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = -ENODEV;
dev_err(&pdev->dev, "failed to get dma resource: %d\n",
ret);
- goto failed_ioremap;
+ goto failed_get_resource;
}
saif->dma_param.chan_num = dmares->start;
@@ -694,14 +681,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = saif->irq;
dev_err(&pdev->dev, "failed to get irq resource: %d\n",
ret);
- goto failed_get_irq1;
+ goto failed_get_resource;
}
saif->dev = &pdev->dev;
- ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
+ ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0,
+ "mxs-saif", saif);
if (ret) {
dev_err(&pdev->dev, "failed to request irq\n");
- goto failed_get_irq1;
+ goto failed_get_resource;
}
saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
@@ -709,7 +697,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = saif->dma_param.chan_irq;
dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
ret);
- goto failed_get_irq2;
+ goto failed_get_resource;
}
platform_set_drvdata(pdev, saif);
@@ -717,7 +705,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
if (ret) {
dev_err(&pdev->dev, "register DAI failed\n");
- goto failed_register;
+ goto failed_get_resource;
}
saif->soc_platform_pdev = platform_device_alloc(
@@ -740,36 +728,19 @@ failed_pdev_add:
platform_device_put(saif->soc_platform_pdev);
failed_pdev_alloc:
snd_soc_unregister_dai(&pdev->dev);
-failed_register:
-failed_get_irq2:
- free_irq(saif->irq, saif);
-failed_get_irq1:
- iounmap(saif->base);
-failed_ioremap:
- release_mem_region(iores->start, resource_size(iores));
failed_get_resource:
clk_put(saif->clk);
-failed_clk:
- kfree(saif);
return ret;
}
static int __devexit mxs_saif_remove(struct platform_device *pdev)
{
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct mxs_saif *saif = platform_get_drvdata(pdev);
platform_device_unregister(saif->soc_platform_pdev);
-
snd_soc_unregister_dai(&pdev->dev);
-
- iounmap(saif->base);
- release_mem_region(res->start, resource_size(res));
- free_irq(saif->irq, saif);
-
clk_put(saif->clk);
- kfree(saif);
return 0;
}
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index fb1bf2581efb..e00dd0b1139c 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -7,7 +7,6 @@ config SND_OMAP_SOC_DMIC
config SND_OMAP_SOC_MCBSP
tristate
- select OMAP_MCBSP
config SND_OMAP_SOC_MCPDM
tristate
@@ -27,7 +26,6 @@ config SND_OMAP_SOC_N810
config SND_OMAP_SOC_RX51
tristate "SoC Audio support for Nokia RX-51"
depends on SND_OMAP_SOC && MACH_NOKIA_RX51
- select OMAP_MCBSP
select SND_OMAP_SOC_MCBSP
select SND_SOC_TLV320AIC3X
select SND_SOC_TPA6130A2
@@ -97,16 +95,19 @@ config SND_OMAP_SOC_SDP3430
Say Y if you want to add support for SoC audio on Texas Instruments
SDP3430.
-config SND_OMAP_SOC_SDP4430
- tristate "SoC Audio support for Texas Instruments SDP4430"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+config SND_OMAP_SOC_OMAP_ABE_TWL6040
+ tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
+ depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4
select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040
select SND_SOC_DMIC
help
- Say Y if you want to add support for SoC audio on Texas Instruments
- SDP4430.
+ Say Y if you want to add support for SoC audio on OMAP boards using
+ ABE and twl6040 codec. This driver currently supports:
+ - SDP4430/Blaze boards
+ - PandaBoard (4430)
+ - PandaBoardES (4460)
config SND_OMAP_SOC_OMAP4_HDMI
tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 1fd723fb559d..1d656bce01d4 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,7 +1,7 @@
# OMAP Platform Support
snd-soc-omap-objs := omap-pcm.o
snd-soc-omap-dmic-objs := omap-dmic.o
-snd-soc-omap-mcbsp-objs := omap-mcbsp.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
snd-soc-omap-mcpdm-objs := omap-mcpdm.o
snd-soc-omap-hdmi-objs := omap-hdmi.o
@@ -20,7 +20,7 @@ snd-soc-overo-objs := overo.o
snd-soc-omap3evm-objs := omap3evm.o
snd-soc-am3517evm-objs := am3517evm.o
snd-soc-sdp3430-objs := sdp3430.o
-snd-soc-sdp4430-objs := sdp4430.o
+snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
snd-soc-zoom2-objs := zoom2.o
@@ -36,7 +36,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
-obj-$(CONFIG_SND_OMAP_SOC_SDP4430) += snd-soc-sdp4430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index add4866d7e67..009533ab8d18 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -95,7 +95,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
static struct snd_soc_dai_link am3517evm_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
- .cpu_dai_name ="omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "tlv320aic23-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic23-codec.2-001a",
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index a67f4370bc9f..49fe63ce51f7 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -570,7 +570,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "AGCOUT");
/* Add virtual switch */
- ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+ ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
ARRAY_SIZE(ams_delta_audio_controls));
if (ret)
dev_warn(card->dev,
@@ -584,7 +584,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link ams_delta_dai_link = {
.name = "CX20442",
.stream_name = "CX20442",
- .cpu_dai_name ="omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "cx20442-voice",
.init = ams_delta_cx20442_init,
.platform_name = "omap-pcm-audio",
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
index ccae58a1339c..e8357819175b 100644
--- a/sound/soc/omap/igep0020.c
+++ b/sound/soc/omap/igep0020.c
@@ -60,7 +60,7 @@ static struct snd_soc_ops igep2_ops = {
static struct snd_soc_dai_link igep2_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/arch/arm/plat-omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 4b15cd7926d7..e5f44440d1b9 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1,9 +1,11 @@
/*
- * linux/arch/arm/plat-omap/mcbsp.c
+ * sound/soc/omap/mcbsp.c
*
* Copyright (C) 2004 Nokia Corporation
* Author: Samuel Ortiz <samuel.ortiz@nokia.com>
*
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ * Peter Ujfalusi <peter.ujfalusi@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
@@ -24,13 +26,8 @@
#include <linux/slab.h>
#include <plat/mcbsp.h>
-#include <linux/pm_runtime.h>
-struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count;
-
-#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
+#include "mcbsp.h"
static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
{
@@ -80,10 +77,8 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
#define MCBSP_ST_WRITE(mcbsp, reg, val) \
omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
-static void omap_mcbsp_dump_reg(u8 id)
+static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
-
dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n",
MCBSP_READ(mcbsp, DRR2));
@@ -156,16 +151,9 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
* You either call this function or set the McBSP registers
* by yourself before calling omap_mcbsp_start().
*/
-void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+ const struct omap_mcbsp_reg_cfg *config)
{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n",
mcbsp->id, mcbsp->phys_base);
@@ -185,33 +173,10 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
MCBSP_WRITE(mcbsp, XCCR, config->xccr);
MCBSP_WRITE(mcbsp, RCCR, config->rccr);
}
+ /* Enable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
}
-EXPORT_SYMBOL(omap_mcbsp_config);
-
-/**
- * omap_mcbsp_dma_params - returns the dma channel number
- * @id - mcbsp id
- * @stream - indicates the direction of data flow (rx or tx)
- *
- * Returns the dma channel number for the rx channel or tx channel
- * based on the value of @stream for the requested mcbsp given by @id
- */
-int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- if (stream)
- return mcbsp->dma_rx_sync;
- else
- return mcbsp->dma_tx_sync;
-}
-EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
/**
* omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
@@ -222,17 +187,11 @@ EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
* to be used by DMA for transferring/receiving data based on the value of
* @stream for the requested mcbsp given by @id
*/
-int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
+static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp,
+ unsigned int stream)
{
- struct omap_mcbsp *mcbsp;
int data_reg;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
if (mcbsp->pdata->reg_size == 2) {
if (stream)
data_reg = OMAP_MCBSP_REG_DRR1;
@@ -247,7 +206,6 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
}
-EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
static void omap_st_on(struct omap_mcbsp *mcbsp)
{
@@ -316,20 +274,11 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp)
ST_CH1GAIN(st_data->ch1gain));
}
-int omap_st_set_chgain(unsigned int id, int channel, s16 chgain)
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_st_data *st_data;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
int ret = 0;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
- st_data = mcbsp->st_data;
-
if (!st_data)
return -ENOENT;
@@ -347,22 +296,12 @@ int omap_st_set_chgain(unsigned int id, int channel, s16 chgain)
return ret;
}
-EXPORT_SYMBOL(omap_st_set_chgain);
-int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain)
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_st_data *st_data;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
int ret = 0;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
- st_data = mcbsp->st_data;
-
if (!st_data)
return -ENOENT;
@@ -377,13 +316,12 @@ int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain)
return ret;
}
-EXPORT_SYMBOL(omap_st_get_chgain);
static int omap_st_start(struct omap_mcbsp *mcbsp)
{
struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
- if (st_data && st_data->enabled && !st_data->running) {
+ if (st_data->enabled && !st_data->running) {
omap_st_fir_write(mcbsp, st_data->taps);
omap_st_chgain(mcbsp);
@@ -396,18 +334,9 @@ static int omap_st_start(struct omap_mcbsp *mcbsp)
return 0;
}
-int omap_st_enable(unsigned int id)
+int omap_st_enable(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_st_data *st_data;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
- st_data = mcbsp->st_data;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
if (!st_data)
return -ENODEV;
@@ -419,13 +348,12 @@ int omap_st_enable(unsigned int id)
return 0;
}
-EXPORT_SYMBOL(omap_st_enable);
static int omap_st_stop(struct omap_mcbsp *mcbsp)
{
struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
- if (st_data && st_data->running) {
+ if (st_data->running) {
if (!mcbsp->free) {
omap_st_off(mcbsp);
st_data->running = 0;
@@ -435,20 +363,11 @@ static int omap_st_stop(struct omap_mcbsp *mcbsp)
return 0;
}
-int omap_st_disable(unsigned int id)
+int omap_st_disable(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_st_data *st_data;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
int ret = 0;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
- st_data = mcbsp->st_data;
-
if (!st_data)
return -ENODEV;
@@ -459,136 +378,52 @@ int omap_st_disable(unsigned int id)
return ret;
}
-EXPORT_SYMBOL(omap_st_disable);
-int omap_st_is_enabled(unsigned int id)
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
- struct omap_mcbsp_st_data *st_data;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
- st_data = mcbsp->st_data;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
if (!st_data)
return -ENODEV;
-
return st_data->enabled;
}
-EXPORT_SYMBOL(omap_st_is_enabled);
/*
* omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH2 register.
*/
-void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
- mcbsp = id_to_mcbsp_ptr(id);
if (mcbsp->pdata->buffer_size == 0)
return;
if (threshold && threshold <= mcbsp->max_tx_thres)
MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
}
-EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
/*
* omap_mcbsp_set_rx_threshold configures the receive threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH1 register.
*/
-void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
- mcbsp = id_to_mcbsp_ptr(id);
if (mcbsp->pdata->buffer_size == 0)
return;
if (threshold && threshold <= mcbsp->max_rx_thres)
MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
}
-EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
-
-/*
- * omap_mcbsp_get_max_tx_thres just return the current configured
- * maximum threshold for transmission
- */
-u16 omap_mcbsp_get_max_tx_threshold(unsigned int id)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- return mcbsp->max_tx_thres;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold);
-
-/*
- * omap_mcbsp_get_max_rx_thres just return the current configured
- * maximum threshold for reception
- */
-u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- return mcbsp->max_rx_thres;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
-
-u16 omap_mcbsp_get_fifo_size(unsigned int id)
-{
- struct omap_mcbsp *mcbsp;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- return mcbsp->pdata->buffer_size;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_fifo_size);
/*
* omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
*/
-u16 omap_mcbsp_get_tx_delay(unsigned int id)
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
u16 buffstat;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
if (mcbsp->pdata->buffer_size == 0)
return 0;
@@ -598,22 +433,15 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id)
/* Number of slots are different in McBSP ports */
return mcbsp->pdata->buffer_size - buffstat;
}
-EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
/*
* omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
* to reach the threshold value (when the DMA will be triggered to read it)
*/
-u16 omap_mcbsp_get_rx_delay(unsigned int id)
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
u16 buffstat, threshold;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
if (mcbsp->pdata->buffer_size == 0)
return 0;
@@ -628,41 +456,12 @@ u16 omap_mcbsp_get_rx_delay(unsigned int id)
else
return threshold - buffstat;
}
-EXPORT_SYMBOL(omap_mcbsp_get_rx_delay);
-
-/*
- * omap_mcbsp_get_dma_op_mode just return the current configured
- * operating mode for the mcbsp channel
- */
-int omap_mcbsp_get_dma_op_mode(unsigned int id)
-{
- struct omap_mcbsp *mcbsp;
- int dma_op_mode;
-
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- dma_op_mode = mcbsp->dma_op_mode;
-
- return dma_op_mode;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
-int omap_mcbsp_request(unsigned int id)
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
void *reg_cache;
int err;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return -ENODEV;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
if (!reg_cache) {
return -ENOMEM;
@@ -681,13 +480,7 @@ int omap_mcbsp_request(unsigned int id)
spin_unlock(&mcbsp->lock);
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
- mcbsp->pdata->ops->request(id);
-
- pm_runtime_get_sync(mcbsp->dev);
-
- /* Enable wakeup behavior */
- if (mcbsp->pdata->has_wakeup)
- MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
+ mcbsp->pdata->ops->request(mcbsp->id - 1);
/*
* Make sure that transmitter, receiver and sample-rate generator are
@@ -722,14 +515,12 @@ err_free_irq:
free_irq(mcbsp->tx_irq, (void *)mcbsp);
err_clk_disable:
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
- mcbsp->pdata->ops->free(id);
+ mcbsp->pdata->ops->free(mcbsp->id - 1);
/* Disable wakeup behavior */
if (mcbsp->pdata->has_wakeup)
MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
- pm_runtime_put_sync(mcbsp->dev);
-
spin_lock(&mcbsp->lock);
mcbsp->free = true;
mcbsp->reg_cache = NULL;
@@ -739,34 +530,34 @@ err_kfree:
return err;
}
-EXPORT_SYMBOL(omap_mcbsp_request);
-void omap_mcbsp_free(unsigned int id)
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp;
void *reg_cache;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
- mcbsp->pdata->ops->free(id);
+ mcbsp->pdata->ops->free(mcbsp->id - 1);
/* Disable wakeup behavior */
if (mcbsp->pdata->has_wakeup)
MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
- pm_runtime_put_sync(mcbsp->dev);
-
if (mcbsp->rx_irq)
free_irq(mcbsp->rx_irq, (void *)mcbsp);
free_irq(mcbsp->tx_irq, (void *)mcbsp);
reg_cache = mcbsp->reg_cache;
+ /*
+ * Select CLKS source from internal source unconditionally before
+ * marking the McBSP port as free.
+ * If the external clock source via MCBSP_CLKS pin has been selected the
+ * system will refuse to enter idle if the CLKS pin source is not reset
+ * back to internal source.
+ */
+ if (!cpu_class_is_omap1())
+ omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
+
spin_lock(&mcbsp->lock);
if (mcbsp->free)
dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
@@ -778,25 +569,17 @@ void omap_mcbsp_free(unsigned int id)
if (reg_cache)
kfree(reg_cache);
}
-EXPORT_SYMBOL(omap_mcbsp_free);
/*
* Here we start the McBSP, by enabling transmitter, receiver or both.
* If no transmitter or receiver is active prior calling, then sample-rate
* generator and frame sync are started.
*/
-void omap_mcbsp_start(unsigned int id, int tx, int rx)
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx)
{
- struct omap_mcbsp *mcbsp;
int enable_srg = 0;
u16 w;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
if (mcbsp->st_data)
omap_st_start(mcbsp);
@@ -846,23 +629,14 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
}
/* Dump McBSP Regs */
- omap_mcbsp_dump_reg(id);
+ omap_mcbsp_dump_reg(mcbsp);
}
-EXPORT_SYMBOL(omap_mcbsp_start);
-void omap_mcbsp_stop(unsigned int id, int tx, int rx)
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
{
- struct omap_mcbsp *mcbsp;
int idle;
u16 w;
- if (!omap_mcbsp_check_valid_id(id)) {
- printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
- return;
- }
-
- mcbsp = id_to_mcbsp_ptr(id);
-
/* Reset transmitter */
tx &= 1;
if (mcbsp->pdata->has_ccr) {
@@ -895,19 +669,11 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
if (mcbsp->st_data)
omap_st_stop(mcbsp);
}
-EXPORT_SYMBOL(omap_mcbsp_stop);
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
{
- struct omap_mcbsp *mcbsp;
const char *src;
- 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)
src = "clks_ext";
else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
@@ -920,43 +686,37 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
else
return -EINVAL;
}
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
{
- struct omap_mcbsp *mcbsp;
- const char *src;
-
- if (mux == CLKR_SRC_CLKR)
- src = "clkr";
- else if (mux == CLKR_SRC_CLKX)
- src = "clkx";
- else
- return;
+ const char *signal, *src;
- mcbsp = id_to_mcbsp_ptr(0);
if (mcbsp->pdata->mux_signal)
- mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
-
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
- struct omap_mcbsp *mcbsp;
- const char *src;
+ return -EINVAL;
- if (mux == FSR_SRC_FSR)
+ switch (mux) {
+ case CLKR_SRC_CLKR:
+ signal = "clkr";
+ src = "clkr";
+ break;
+ case CLKR_SRC_CLKX:
+ signal = "clkr";
+ src = "clkx";
+ break;
+ case FSR_SRC_FSR:
+ signal = "fsr";
src = "fsr";
- else if (mux == FSR_SRC_FSX)
+ break;
+ case FSR_SRC_FSX:
+ signal = "fsr";
src = "fsx";
- else
- return;
+ break;
+ default:
+ return -EINVAL;
+ }
- mcbsp = id_to_mcbsp_ptr(0);
- if (mcbsp->pdata->mux_signal)
- mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
+ return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src);
}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
#define max_thres(m) (mcbsp->pdata->buffer_size)
#define valid_threshold(m, val) ((val) <= max_thres(m))
@@ -1132,97 +892,56 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
struct omap_mcbsp_st_data *st_data;
int err;
- st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL);
- if (!st_data) {
- err = -ENOMEM;
- goto err1;
- }
+ st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL);
+ if (!st_data)
+ return -ENOMEM;
- st_data->io_base_st = ioremap(res->start, resource_size(res));
- if (!st_data->io_base_st) {
- err = -ENOMEM;
- goto err2;
- }
+ st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
+ resource_size(res));
+ if (!st_data->io_base_st)
+ return -ENOMEM;
err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
if (err)
- goto err3;
+ return err;
mcbsp->st_data = st_data;
return 0;
-
-err3:
- iounmap(st_data->io_base_st);
-err2:
- kfree(st_data);
-err1:
- return err;
-
-}
-
-static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
-{
- struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
-
- sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
- iounmap(st_data->io_base_st);
- kfree(st_data);
}
/*
* McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
* 730 has only 2 McBSP, and both of them are MPU peripherals.
*/
-static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
+int __devinit omap_mcbsp_init(struct platform_device *pdev)
{
- struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
- struct omap_mcbsp *mcbsp;
- int id = pdev->id - 1;
+ struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
struct resource *res;
int ret = 0;
- if (!pdata) {
- dev_err(&pdev->dev, "McBSP device initialized without"
- "platform data\n");
- ret = -EINVAL;
- goto exit;
- }
-
- dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id);
-
- if (id >= omap_mcbsp_count) {
- dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id);
- ret = -EINVAL;
- goto exit;
- }
-
- mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL);
- if (!mcbsp) {
- ret = -ENOMEM;
- goto exit;
- }
-
spin_lock_init(&mcbsp->lock);
- mcbsp->id = id + 1;
mcbsp->free = true;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (!res) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory"
- "resource\n", __func__, pdev->id);
- ret = -ENOMEM;
- goto exit;
+ dev_err(mcbsp->dev, "invalid memory resource\n");
+ return -ENOMEM;
}
}
+ if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(mcbsp->dev, "memory region already claimed\n");
+ return -ENODEV;
+ }
+
mcbsp->phys_base = res->start;
mcbsp->reg_cache_size = resource_size(res);
- mcbsp->io_base = ioremap(res->start, resource_size(res));
- if (!mcbsp->io_base) {
- ret = -ENOMEM;
- goto err_ioremap;
- }
+ mcbsp->io_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!mcbsp->io_base)
+ return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
if (!res)
@@ -1234,40 +953,38 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
/* From OMAP4 there will be a single irq line */
- if (mcbsp->tx_irq == -ENXIO)
+ if (mcbsp->tx_irq == -ENXIO) {
mcbsp->tx_irq = platform_get_irq(pdev, 0);
+ mcbsp->rx_irq = 0;
+ }
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
if (!res) {
- dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n",
- __func__, pdev->id);
- ret = -ENODEV;
- goto err_res;
+ dev_err(&pdev->dev, "invalid rx DMA channel\n");
+ return -ENODEV;
}
- mcbsp->dma_rx_sync = res->start;
+ /* RX DMA request number, and port address configuration */
+ mcbsp->dma_data[1].name = "Audio Capture";
+ mcbsp->dma_data[1].dma_req = res->start;
+ mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
if (!res) {
- dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n",
- __func__, pdev->id);
- ret = -ENODEV;
- goto err_res;
+ dev_err(&pdev->dev, "invalid tx DMA channel\n");
+ return -ENODEV;
}
- mcbsp->dma_tx_sync = res->start;
+ /* TX DMA request number, and port address configuration */
+ mcbsp->dma_data[0].name = "Audio Playback";
+ mcbsp->dma_data[0].dma_req = res->start;
+ mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
mcbsp->fclk = clk_get(&pdev->dev, "fck");
if (IS_ERR(mcbsp->fclk)) {
ret = PTR_ERR(mcbsp->fclk);
- dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
- goto err_res;
+ dev_err(mcbsp->dev, "unable to get fck: %d\n", ret);
+ return ret;
}
- mcbsp->pdata = pdata;
- mcbsp->dev = &pdev->dev;
- mcbsp_ptr[id] = mcbsp;
- platform_set_drvdata(pdev, mcbsp);
- pm_runtime_enable(mcbsp->dev);
-
mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
if (mcbsp->pdata->buffer_size) {
/*
@@ -1307,55 +1024,17 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
err_st:
if (mcbsp->pdata->buffer_size)
- sysfs_remove_group(&mcbsp->dev->kobj,
- &additional_attr_group);
+ sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
err_thres:
clk_put(mcbsp->fclk);
-err_res:
- iounmap(mcbsp->io_base);
-err_ioremap:
- kfree(mcbsp);
-exit:
return ret;
}
-static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
{
- struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
- if (mcbsp) {
-
- if (mcbsp->pdata && mcbsp->pdata->ops &&
- mcbsp->pdata->ops->free)
- mcbsp->pdata->ops->free(mcbsp->id);
-
- if (mcbsp->pdata->buffer_size)
- sysfs_remove_group(&mcbsp->dev->kobj,
- &additional_attr_group);
-
- if (mcbsp->st_data)
- omap_st_remove(mcbsp);
-
- clk_put(mcbsp->fclk);
-
- iounmap(mcbsp->io_base);
- kfree(mcbsp);
- }
-
- return 0;
-}
-
-static struct platform_driver omap_mcbsp_driver = {
- .probe = omap_mcbsp_probe,
- .remove = __devexit_p(omap_mcbsp_remove),
- .driver = {
- .name = "omap-mcbsp",
- },
-};
+ if (mcbsp->pdata->buffer_size)
+ sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
-int __init omap_mcbsp_init(void)
-{
- /* Register the McBSP driver */
- return platform_driver_register(&omap_mcbsp_driver);
+ if (mcbsp->st_data)
+ sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
}
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
new file mode 100644
index 000000000000..a944fcc9073c
--- /dev/null
+++ b/sound/soc/omap/mcbsp.h
@@ -0,0 +1,346 @@
+/*
+ * sound/soc/omap/mcbsp.h
+ *
+ * OMAP Multi-Channel Buffered Serial Port
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ * Peter Ujfalusi <peter.ujfalusi@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
+ *
+ */
+#ifndef __ASOC_MCBSP_H
+#define __ASOC_MCBSP_H
+
+#include "omap-pcm.h"
+
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+ /* Common registers */
+ OMAP_MCBSP_REG_SPCR2 = 4,
+ OMAP_MCBSP_REG_SPCR1,
+ OMAP_MCBSP_REG_RCR2,
+ OMAP_MCBSP_REG_RCR1,
+ OMAP_MCBSP_REG_XCR2,
+ OMAP_MCBSP_REG_XCR1,
+ OMAP_MCBSP_REG_SRGR2,
+ OMAP_MCBSP_REG_SRGR1,
+ OMAP_MCBSP_REG_MCR2,
+ OMAP_MCBSP_REG_MCR1,
+ OMAP_MCBSP_REG_RCERA,
+ OMAP_MCBSP_REG_RCERB,
+ OMAP_MCBSP_REG_XCERA,
+ OMAP_MCBSP_REG_XCERB,
+ OMAP_MCBSP_REG_PCR0,
+ OMAP_MCBSP_REG_RCERC,
+ OMAP_MCBSP_REG_RCERD,
+ OMAP_MCBSP_REG_XCERC,
+ OMAP_MCBSP_REG_XCERD,
+ OMAP_MCBSP_REG_RCERE,
+ OMAP_MCBSP_REG_RCERF,
+ OMAP_MCBSP_REG_XCERE,
+ OMAP_MCBSP_REG_XCERF,
+ OMAP_MCBSP_REG_RCERG,
+ OMAP_MCBSP_REG_RCERH,
+ OMAP_MCBSP_REG_XCERG,
+ OMAP_MCBSP_REG_XCERH,
+
+ /* OMAP1-OMAP2420 registers */
+ OMAP_MCBSP_REG_DRR2 = 0,
+ OMAP_MCBSP_REG_DRR1,
+ OMAP_MCBSP_REG_DXR2,
+ OMAP_MCBSP_REG_DXR1,
+
+ /* OMAP2430 and onwards */
+ OMAP_MCBSP_REG_DRR = 0,
+ OMAP_MCBSP_REG_DXR = 2,
+ OMAP_MCBSP_REG_SYSCON = 35,
+ OMAP_MCBSP_REG_THRSH2,
+ OMAP_MCBSP_REG_THRSH1,
+ OMAP_MCBSP_REG_IRQST = 40,
+ OMAP_MCBSP_REG_IRQEN,
+ OMAP_MCBSP_REG_WAKEUPEN,
+ OMAP_MCBSP_REG_XCCR,
+ OMAP_MCBSP_REG_RCCR,
+ OMAP_MCBSP_REG_XBUFFSTAT,
+ OMAP_MCBSP_REG_RBUFFSTAT,
+ OMAP_MCBSP_REG_SSELCR,
+};
+
+/* OMAP3 sidetone control registers */
+#define OMAP_ST_REG_REV 0x00
+#define OMAP_ST_REG_SYSCONFIG 0x10
+#define OMAP_ST_REG_IRQSTATUS 0x18
+#define OMAP_ST_REG_IRQENABLE 0x1C
+#define OMAP_ST_REG_SGAINCR 0x24
+#define OMAP_ST_REG_SFIRCR 0x28
+#define OMAP_ST_REG_SSELCR 0x2C
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST BIT(0)
+#define RRDY BIT(1)
+#define RFULL BIT(2)
+#define RSYNC_ERR BIT(3)
+#define RINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */
+#define ABIS BIT(6)
+#define DXENA BIT(7)
+#define CLKSTP(value) (((value) & 0x3) << 11) /* bits 11:12 */
+#define RJUST(value) (((value) & 0x3) << 13) /* bits 13:14 */
+#define ALB BIT(15)
+#define DLB BIT(15)
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST BIT(0)
+#define XRDY BIT(1)
+#define XEMPTY BIT(2)
+#define XSYNC_ERR BIT(3)
+#define XINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */
+#define GRST BIT(6)
+#define FRST BIT(7)
+#define SOFT BIT(8)
+#define FREE BIT(9)
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP BIT(0)
+#define CLKXP BIT(1)
+#define FSRP BIT(2)
+#define FSXP BIT(3)
+#define DR_STAT BIT(4)
+#define DX_STAT BIT(5)
+#define CLKS_STAT BIT(6)
+#define SCLKME BIT(7)
+#define CLKRM BIT(8)
+#define CLKXM BIT(9)
+#define FSRM BIT(10)
+#define FSXM BIT(11)
+#define RIOEN BIT(12)
+#define XIOEN BIT(13)
+#define IDLE_EN BIT(14)
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define RFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define XFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value) ((value) & 0x3) /* Bits 0:1 */
+#define RFIG BIT(2)
+#define RCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */
+#define RWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define RFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+#define RPHASE BIT(15)
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value) ((value) & 0x3) /* Bits 0:1 */
+#define XFIG BIT(2)
+#define XCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */
+#define XWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define XFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+#define XPHASE BIT(15)
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value) ((value) & 0x7f) /* Bits 0:7 */
+#define FWID(value) (((value) & 0xff) << 8) /* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value) ((value) & 0x0fff) /* Bits 0:11 */
+#define FSGM BIT(12)
+#define CLKSM BIT(13)
+#define CLKSP BIT(14)
+#define GSYNC BIT(15)
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM BIT(0)
+#define RCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */
+#define RPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */
+#define RPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value) ((value) & 0x3) /* Bits 0:1 */
+#define XCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */
+#define XPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */
+#define XPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */
+
+/*********************** McBSP XCCR bit definitions *************************/
+#define XDISABLE BIT(0)
+#define XDMAEN BIT(3)
+#define DILB BIT(5)
+#define XFULL_CYCLE BIT(11)
+#define DXENDLY(value) (((value) & 0x3) << 12) /* Bits 12:13 */
+#define PPCONNECT BIT(14)
+#define EXTCLKGATE BIT(15)
+
+/********************** McBSP RCCR bit definitions *************************/
+#define RDISABLE BIT(0)
+#define RDMAEN BIT(3)
+#define RFULL_CYCLE BIT(11)
+
+/********************** McBSP SYSCONFIG bit definitions ********************/
+#define SOFTRST BIT(1)
+#define ENAWAKEUP BIT(2)
+#define SIDLEMODE(value) (((value) & 0x3) << 3)
+#define CLOCKACTIVITY(value) (((value) & 0x3) << 8)
+
+/********************** McBSP SSELCR bit definitions ***********************/
+#define SIDETONEEN BIT(10)
+
+/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
+#define ST_AUTOIDLE BIT(0)
+
+/********************** McBSP Sidetone SGAINCR bit definitions *************/
+#define ST_CH0GAIN(value) ((value) & 0xffff) /* Bits 0:15 */
+#define ST_CH1GAIN(value) (((value) & 0xffff) << 16) /* Bits 16:31 */
+
+/********************** McBSP Sidetone SFIRCR bit definitions **************/
+#define ST_FIRCOEFF(value) ((value) & 0xffff) /* Bits 0:15 */
+
+/********************** McBSP Sidetone SSELCR bit definitions **************/
+#define ST_SIDETONEEN BIT(0)
+#define ST_COEFFWREN BIT(1)
+#define ST_COEFFWRDONE BIT(2)
+
+/********************** McBSP DMA operating modes **************************/
+#define MCBSP_DMA_MODE_ELEMENT 0
+#define MCBSP_DMA_MODE_THRESHOLD 1
+#define MCBSP_DMA_MODE_FRAME 2
+
+/********************** McBSP WAKEUPEN bit definitions *********************/
+#define RSYNCERREN BIT(0)
+#define RFSREN BIT(1)
+#define REOFEN BIT(2)
+#define RRDYEN BIT(3)
+#define XSYNCERREN BIT(7)
+#define XFSXEN BIT(8)
+#define XEOFEN BIT(9)
+#define XRDYEN BIT(10)
+#define XEMPTYEOFEN BIT(14)
+
+/* Clock signal muxing options */
+#define CLKR_SRC_CLKR 0 /* CLKR signal is from the CLKR pin */
+#define CLKR_SRC_CLKX 1 /* CLKR signal is from the CLKX pin */
+#define FSR_SRC_FSR 2 /* FSR signal is from the FSR pin */
+#define FSR_SRC_FSX 3 /* FSR signal is from the FSX pin */
+
+/* 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;
+ u16 spcr1;
+ u16 rcr2;
+ u16 rcr1;
+ u16 xcr2;
+ u16 xcr1;
+ u16 srgr2;
+ u16 srgr1;
+ u16 mcr2;
+ u16 mcr1;
+ u16 pcr0;
+ u16 rcerc;
+ u16 rcerd;
+ u16 xcerc;
+ u16 xcerd;
+ u16 rcere;
+ u16 rcerf;
+ u16 xcere;
+ u16 xcerf;
+ u16 rcerg;
+ u16 rcerh;
+ u16 xcerg;
+ u16 xcerh;
+ u16 xccr;
+ u16 rccr;
+};
+
+struct omap_mcbsp_st_data {
+ void __iomem *io_base_st;
+ bool running;
+ bool enabled;
+ s16 taps[128]; /* Sidetone filter coefficients */
+ int nr_taps; /* Number of filter coefficients in use */
+ s16 ch0gain;
+ s16 ch1gain;
+};
+
+struct omap_mcbsp {
+ struct device *dev;
+ struct clk *fclk;
+ spinlock_t lock;
+ unsigned long phys_base;
+ unsigned long phys_dma_base;
+ void __iomem *io_base;
+ u8 id;
+ /*
+ * Flags indicating is the bus already activated and configured by
+ * another substream
+ */
+ int active;
+ int configured;
+ u8 free;
+
+ int rx_irq;
+ int tx_irq;
+
+ /* Protect the field .free, while checking if the mcbsp is in use */
+ struct omap_mcbsp_platform_data *pdata;
+ struct omap_mcbsp_st_data *st_data;
+ struct omap_mcbsp_reg_cfg cfg_regs;
+ struct omap_pcm_dma_data dma_data[2];
+ int dma_op_mode;
+ u16 max_tx_thres;
+ u16 max_rx_thres;
+ void *reg_cache;
+ int reg_cache_size;
+
+ unsigned int fmt;
+ unsigned int in_freq;
+ int clk_div;
+ int wlen;
+};
+
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+ const struct omap_mcbsp_reg_cfg *config);
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp);
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx);
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx);
+
+/* McBSP functional clock source changing function */
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
+
+/* McBSP signal muxing API */
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux);
+
+/* Sidetone specific API */
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain);
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain);
+int omap_st_enable(struct omap_mcbsp *mcbsp);
+int omap_st_disable(struct omap_mcbsp *mcbsp);
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
+
+int __devinit omap_mcbsp_init(struct platform_device *pdev);
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+
+#endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 597be412f1e4..abac4b690750 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -55,9 +55,8 @@ static int n810_spk_func;
static int n810_jack_func;
static int n810_dmic_func;
-static void n810_ext_control(struct snd_soc_codec *codec)
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, line1l = 0;
switch (n810_jack_func) {
@@ -102,7 +101,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- n810_ext_control(codec);
+ n810_ext_control(&codec->dapm);
return clk_enable(sys_clkout2);
}
@@ -142,13 +141,13 @@ static int n810_get_spk(struct snd_kcontrol *kcontrol,
static int n810_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_spk_func == ucontrol->value.integer.value[0])
return 0;
n810_spk_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -164,13 +163,13 @@ static int n810_get_jack(struct snd_kcontrol *kcontrol,
static int n810_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_jack_func == ucontrol->value.integer.value[0])
return 0;
n810_jack_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -186,13 +185,13 @@ static int n810_get_input(struct snd_kcontrol *kcontrol,
static int n810_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_dmic_func == ucontrol->value.integer.value[0])
return 0;
n810_dmic_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -276,7 +275,7 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link n810_dai = {
.name = "TLV320AIC33",
.stream_name = "AIC33",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic3x-codec.2-0018",
.codec_dai_name = "tlv320aic3x-hifi",
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
new file mode 100644
index 000000000000..93bb8eee22b3
--- /dev/null
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -0,0 +1,349 @@
+/*
+ * omap-abe-twl6040.c -- SoC audio for TI OMAP based boards with ABE and
+ * twl6040 codec
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@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
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+#include <plat/hardware.h>
+#include <plat/mux.h>
+
+#include "omap-dmic.h"
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+#include "../codecs/twl6040.h"
+
+static int omap_abe_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_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+ int clk_id, freq;
+ int ret;
+
+ clk_id = twl6040_get_clk_id(rtd->codec);
+ if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
+ freq = pdata->mclk_freq;
+ else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
+ freq = 32768;
+ else
+ return -EINVAL;
+
+ /* set the codec mclk */
+ ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+ return ret;
+}
+
+static struct snd_soc_ops omap_abe_ops = {
+ .hw_params = omap_abe_hw_params,
+};
+
+static int omap_abe_dmic_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;
+ int ret = 0;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
+ 19200000, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set DMIC cpu system clock\n");
+ return ret;
+ }
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set DMIC output clock\n");
+ return ret;
+ }
+ return 0;
+}
+
+static struct snd_soc_ops omap_abe_dmic_ops = {
+ .hw_params = omap_abe_dmic_hw_params,
+};
+
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "Headset Stereophone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+/* SDP4430 machine DAPM */
+static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
+ /* Outputs */
+ SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+ SND_SOC_DAPM_SPK("Earphone Spk", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_SPK("Vibrator", NULL),
+
+ /* Inputs */
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Main Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Sub Handset Mic", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Routings for outputs */
+ {"Headset Stereophone", NULL, "HSOL"},
+ {"Headset Stereophone", NULL, "HSOR"},
+
+ {"Earphone Spk", NULL, "EP"},
+
+ {"Ext Spk", NULL, "HFL"},
+ {"Ext Spk", NULL, "HFR"},
+
+ {"Line Out", NULL, "AUXL"},
+ {"Line Out", NULL, "AUXR"},
+
+ {"Vibrator", NULL, "VIBRAL"},
+ {"Vibrator", NULL, "VIBRAR"},
+
+ /* Routings for inputs */
+ {"HSMIC", NULL, "Headset Mic"},
+ {"Headset Mic", NULL, "Headset Mic Bias"},
+
+ {"MAINMIC", NULL, "Main Handset Mic"},
+ {"Main Handset Mic", NULL, "Main Mic Bias"},
+
+ {"SUBMIC", NULL, "Sub Handset Mic"},
+ {"Sub Handset Mic", NULL, "Main Mic Bias"},
+
+ {"AFML", NULL, "Line In"},
+ {"AFMR", NULL, "Line In"},
+};
+
+static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
+ int connected, char *pin)
+{
+ if (!connected)
+ snd_soc_dapm_disable_pin(dapm, pin);
+}
+
+static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+ int hs_trim;
+ int ret = 0;
+
+ /* Disable not connected paths if not used */
+ twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
+ twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
+ twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
+ twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
+ twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+ twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
+
+ /*
+ * Configure McPDM offset cancellation based on the HSOTRIM value from
+ * twl6040.
+ */
+ hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+ omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+ TWL6040_HSF_TRIM_RIGHT(hs_trim));
+
+ /* Headset jack detection only if it is supported */
+ if (pdata->jack_detection) {
+ ret = snd_soc_jack_new(codec, "Headset Jack",
+ SND_JACK_HEADSET, &hs_jack);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+ hs_jack_pins);
+ twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
+ }
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+ {"DMic", NULL, "Digital Mic"},
+ {"Digital Mic", NULL, "Digital Mic1 Bias"},
+};
+
+static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets,
+ ARRAY_SIZE(dmic_dapm_widgets));
+ if (ret)
+ return ret;
+
+ return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
+ ARRAY_SIZE(dmic_audio_map));
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link twl6040_dmic_dai[] = {
+ {
+ .name = "TWL6040",
+ .stream_name = "TWL6040",
+ .cpu_dai_name = "omap-mcpdm",
+ .codec_dai_name = "twl6040-legacy",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "twl6040-codec",
+ .init = omap_abe_twl6040_init,
+ .ops = &omap_abe_ops,
+ },
+ {
+ .name = "DMIC",
+ .stream_name = "DMIC Capture",
+ .cpu_dai_name = "omap-dmic",
+ .codec_dai_name = "dmic-hifi",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "dmic-codec",
+ .init = omap_abe_dmic_init,
+ .ops = &omap_abe_dmic_ops,
+ },
+};
+
+static struct snd_soc_dai_link twl6040_only_dai[] = {
+ {
+ .name = "TWL6040",
+ .stream_name = "TWL6040",
+ .cpu_dai_name = "omap-mcpdm",
+ .codec_dai_name = "twl6040-legacy",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "twl6040-codec",
+ .init = omap_abe_twl6040_init,
+ .ops = &omap_abe_ops,
+ },
+};
+
+/* Audio machine driver */
+static struct snd_soc_card omap_abe_card = {
+ .owner = THIS_MODULE,
+
+ .dapm_widgets = twl6040_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static __devinit int omap_abe_probe(struct platform_device *pdev)
+{
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
+ struct snd_soc_card *card = &omap_abe_card;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Missing pdata\n");
+ return -ENODEV;
+ }
+
+ if (pdata->card_name) {
+ card->name = pdata->card_name;
+ } else {
+ dev_err(&pdev->dev, "Card name is not provided\n");
+ return -ENODEV;
+ }
+
+ if (!pdata->mclk_freq) {
+ dev_err(&pdev->dev, "MCLK frequency missing\n");
+ return -ENODEV;
+ }
+
+ if (pdata->has_dmic) {
+ card->dai_link = twl6040_dmic_dai;
+ card->num_links = ARRAY_SIZE(twl6040_dmic_dai);
+ } else {
+ card->dai_link = twl6040_only_dai;
+ card->num_links = ARRAY_SIZE(twl6040_only_dai);
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+
+ return ret;
+}
+
+static int __devexit omap_abe_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver omap_abe_driver = {
+ .driver = {
+ .name = "omap-abe-twl6040",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = omap_abe_probe,
+ .remove = __devexit_p(omap_abe_remove),
+};
+
+module_platform_driver(omap_abe_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap-abe-twl6040");
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 0855c1cfa7fd..4dcb5a7e40e8 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -113,12 +113,10 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
mutex_lock(&dmic->mutex);
- if (!dai->active) {
- snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+ if (!dai->active)
dmic->active = 1;
- } else {
+ else
ret = -EBUSY;
- }
mutex_unlock(&dmic->mutex);
@@ -445,6 +443,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
.channels_max = 6,
.rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .sig_bits = 24,
},
.ops = &omap_dmic_dai_ops,
};
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 017371913ec3..6912ac7cb625 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/pm_runtime.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -33,6 +34,7 @@
#include <plat/dma.h>
#include <plat/mcbsp.h>
+#include "mcbsp.h"
#include "omap-mcbsp.h"
#include "omap-pcm.h"
@@ -46,42 +48,31 @@
.private_value = (unsigned long) &(struct soc_mixer_control) \
{.min = xmin, .max = xmax} }
-struct omap_mcbsp_data {
- unsigned int bus_id;
- struct omap_mcbsp_reg_cfg regs;
- unsigned int fmt;
- /*
- * Flags indicating is the bus already activated and configured by
- * another substream
- */
- int active;
- int configured;
- unsigned int in_freq;
- int clk_div;
- int wlen;
+enum {
+ OMAP_MCBSP_WORD_8 = 0,
+ OMAP_MCBSP_WORD_12,
+ OMAP_MCBSP_WORD_16,
+ OMAP_MCBSP_WORD_20,
+ OMAP_MCBSP_WORD_24,
+ OMAP_MCBSP_WORD_32,
};
-static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
-
/*
* Stream DMA parameters. DMA request line and port address are set runtime
* since they are different between OMAP1 and later OMAPs
*/
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][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->cpu_dai;
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = 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->cpu_dai, substream);
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+ if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
/*
* Configure McBSP threshold based on either:
* packet_size, when the sDMA is in packet mode, or
@@ -91,15 +82,15 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
words = dma_data->packet_size;
else
words = snd_pcm_lib_period_bytes(substream) /
- (mcbsp_data->wlen / 8);
+ (mcbsp->wlen / 8);
else
words = 1;
/* Configure McBSP internal buffer usage */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
+ omap_mcbsp_set_tx_threshold(mcbsp, words);
else
- omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
+ omap_mcbsp_set_rx_threshold(mcbsp, words);
}
static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
@@ -109,12 +100,12 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
- struct omap_mcbsp_data *mcbsp_data = rule->private;
+ struct omap_mcbsp *mcbsp = rule->private;
struct snd_interval frames;
int size;
snd_interval_any(&frames);
- size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
+ size = mcbsp->pdata->buffer_size;
frames.min = size / channels->min;
frames.integer = 1;
@@ -124,12 +115,11 @@ 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 *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- int bus_id = mcbsp_data->bus_id;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
int err = 0;
if (!cpu_dai->active)
- err = omap_mcbsp_request(bus_id);
+ err = omap_mcbsp_request(mcbsp);
/*
* OMAP3 McBSP FIFO is word structured.
@@ -146,16 +136,16 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
* 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
* 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
*/
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->buffer_size) {
/*
* Rule for the buffer size. We should not allow
* smaller buffer than the FIFO size to avoid underruns
*/
snd_pcm_hw_rule_add(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
omap_mcbsp_hwrule_min_buffersize,
- mcbsp_data,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
+ mcbsp,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
/* Make sure, that the period size is always even */
snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -168,33 +158,33 @@ 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 *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
if (!cpu_dai->active) {
- omap_mcbsp_free(mcbsp_data->bus_id);
- mcbsp_data->configured = 0;
+ omap_mcbsp_free(mcbsp);
+ mcbsp->configured = 0;
}
}
static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- mcbsp_data->active++;
- omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
+ mcbsp->active++;
+ omap_mcbsp_start(mcbsp, play, !play);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
- mcbsp_data->active--;
+ omap_mcbsp_stop(mcbsp, play, !play);
+ mcbsp->active--;
break;
default:
err = -EINVAL;
@@ -209,14 +199,14 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
{
struct snd_soc_pcm_runtime *rtd = substream->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_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
u16 fifo_use;
snd_pcm_sframes_t delay;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
+ fifo_use = omap_mcbsp_get_tx_delay(mcbsp);
else
- fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
+ fifo_use = omap_mcbsp_get_rx_delay(mcbsp);
/*
* Divide the used locations with the channel count to get the
@@ -232,19 +222,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
struct omap_pcm_dma_data *dma_data;
- int dma, bus_id = mcbsp_data->bus_id;
int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
int pkt_size = 0;
- unsigned long port;
unsigned int format, div, framesize, master;
- dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
-
- dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
- port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
+ dma_data = &mcbsp->dma_data[substream->stream];
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -258,20 +243,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
default:
return -EINVAL;
}
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->buffer_size) {
dma_data->set_threshold = omap_mcbsp_set_threshold;
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (omap_mcbsp_get_dma_op_mode(bus_id) ==
- MCBSP_DMA_MODE_THRESHOLD) {
+ if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
int period_words, max_thrsh;
period_words = params_period_bytes(params) / (wlen / 8);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- max_thrsh = omap_mcbsp_get_max_tx_threshold(
- mcbsp_data->bus_id);
+ max_thrsh = mcbsp->max_tx_thres;
else
- max_thrsh = omap_mcbsp_get_max_rx_threshold(
- mcbsp_data->bus_id);
+ max_thrsh = mcbsp->max_rx_thres;
/*
* If the period contains less or equal number of words,
* we are using the original threshold mode setup:
@@ -304,15 +286,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
}
}
- dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
- dma_data->dma_req = dma;
- dma_data->port_addr = port;
dma_data->sync_mode = sync_mode;
dma_data->packet_size = pkt_size;
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
- if (mcbsp_data->configured) {
+ if (mcbsp->configured) {
/* McBSP already configured by another stream */
return 0;
}
@@ -321,7 +300,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7));
regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7));
- format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
wpf = channels = params_channels(params);
if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
format == SND_SOC_DAIFMT_LEFT_J)) {
@@ -359,10 +338,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
/* In McBSP master modes, FRAME (i.e. sample rate) is generated
* by _counting_ BCLKs. Calculate frame size in BCLKs */
- master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+ master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK;
if (master == SND_SOC_DAIFMT_CBS_CFS) {
- div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
- framesize = (mcbsp_data->in_freq / div) / params_rate(params);
+ div = mcbsp->clk_div ? mcbsp->clk_div : 1;
+ framesize = (mcbsp->in_freq / div) / params_rate(params);
if (framesize < wlen * channels) {
printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
@@ -388,9 +367,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
break;
}
- omap_mcbsp_config(bus_id, &mcbsp_data->regs);
- mcbsp_data->wlen = wlen;
- mcbsp_data->configured = 1;
+ omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs);
+ mcbsp->wlen = wlen;
+ mcbsp->configured = 1;
return 0;
}
@@ -402,14 +381,14 @@ 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 = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
bool inv_fs = false;
- if (mcbsp_data->configured)
+ if (mcbsp->configured)
return 0;
- mcbsp_data->fmt = fmt;
+ mcbsp->fmt = fmt;
memset(regs, 0, sizeof(*regs));
/* Generic McBSP register settings */
regs->spcr2 |= XINTM(3) | FREE;
@@ -504,13 +483,13 @@ 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 = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
if (div_id != OMAP_MCBSP_CLKGDV)
return -ENODEV;
- mcbsp_data->clk_div = div;
+ mcbsp->clk_div = div;
regs->srgr1 &= ~CLKGDV(0xff);
regs->srgr1 |= CLKGDV(div - 1);
@@ -521,28 +500,32 @@ 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 = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
int err = 0;
- if (mcbsp_data->active) {
- if (freq == mcbsp_data->in_freq)
+ if (mcbsp->active) {
+ if (freq == mcbsp->in_freq)
return 0;
else
return -EBUSY;
}
- /* 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;
- regs->srgr2 &= ~CLKSM;
- regs->pcr0 &= ~SCLKME;
+ if (clk_id == OMAP_MCBSP_SYSCLK_CLK ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) {
+ mcbsp->in_freq = freq;
+ regs->srgr2 &= ~CLKSM;
+ regs->pcr0 &= ~SCLKME;
+ } else if (cpu_class_is_omap1()) {
+ /*
+ * McBSP CLKR/FSR signal muxing functions are only available on
+ * OMAP2 or newer versions
+ */
+ return -EINVAL;
+ }
switch (clk_id) {
case OMAP_MCBSP_SYSCLK_CLK:
@@ -553,7 +536,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
err = -EINVAL;
break;
}
- err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ err = omap2_mcbsp_set_clks_src(mcbsp,
MCBSP_CLKS_PRCM_SRC);
break;
case OMAP_MCBSP_SYSCLK_CLKS_EXT:
@@ -561,7 +544,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
err = 0;
break;
}
- err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ err = omap2_mcbsp_set_clks_src(mcbsp,
MCBSP_CLKS_PAD_SRC);
break;
@@ -573,24 +556,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
case OMAP_MCBSP_CLKR_SRC_CLKR:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR);
break;
case OMAP_MCBSP_CLKR_SRC_CLKX:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX);
break;
case OMAP_MCBSP_FSR_SRC_FSR:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR);
break;
case OMAP_MCBSP_FSR_SRC_FSX:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX);
break;
default:
err = -ENODEV;
@@ -610,15 +585,27 @@ static const struct snd_soc_dai_ops mcbsp_dai_ops = {
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
};
-static int mcbsp_dai_probe(struct snd_soc_dai *dai)
+static int omap_mcbsp_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);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_enable(mcbsp->dev);
+
+ return 0;
+}
+
+static int omap_mcbsp_remove(struct snd_soc_dai *dai)
+{
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_disable(mcbsp->dev);
+
return 0;
}
static struct snd_soc_dai_driver omap_mcbsp_dai = {
- .probe = mcbsp_dai_probe,
+ .probe = omap_mcbsp_probe,
+ .remove = omap_mcbsp_remove,
.playback = {
.channels_min = 1,
.channels_max = 16,
@@ -649,11 +636,13 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
return 0;
}
-#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \
static int \
-omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
struct snd_ctl_elem_value *uc) \
{ \
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
struct soc_mixer_control *mc = \
(struct soc_mixer_control *)kc->private_value; \
int max = mc->max; \
@@ -664,46 +653,44 @@ omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
return -EINVAL; \
\
/* OMAP McBSP implementation uses index values 0..4 */ \
- return omap_st_set_chgain((id)-1, channel, val); \
+ return omap_st_set_chgain(mcbsp, channel, val); \
}
-#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \
static int \
-omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
struct snd_ctl_elem_value *uc) \
{ \
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
s16 chgain; \
\
- if (omap_st_get_chgain((id)-1, channel, &chgain)) \
+ if (omap_st_get_chgain(mcbsp, channel, &chgain)) \
return -EAGAIN; \
\
uc->value.integer.value[0] = chgain; \
return 0; \
}
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1)
static int omap_mcbsp_st_put_mode(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_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
u8 value = ucontrol->value.integer.value[0];
- if (value == omap_st_is_enabled(mc->reg))
+ if (value == omap_st_is_enabled(mcbsp))
return 0;
if (value)
- omap_st_enable(mc->reg);
+ omap_st_enable(mcbsp);
else
- omap_st_disable(mc->reg);
+ omap_st_disable(mcbsp);
return 1;
}
@@ -711,10 +698,10 @@ static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
static int omap_mcbsp_st_get_mode(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_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
- ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
+ ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp);
return 0;
}
@@ -723,12 +710,12 @@ static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
-32768, 32767,
- omap_mcbsp2_get_st_ch0_volume,
- omap_mcbsp2_set_st_ch0_volume),
+ omap_mcbsp_get_st_ch0_volume,
+ omap_mcbsp_set_st_ch0_volume),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
-32768, 32767,
- omap_mcbsp2_get_st_ch1_volume,
- omap_mcbsp2_set_st_ch1_volume),
+ omap_mcbsp_get_st_ch1_volume,
+ omap_mcbsp_set_st_ch1_volume),
};
static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
@@ -736,25 +723,30 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
-32768, 32767,
- omap_mcbsp3_get_st_ch0_volume,
- omap_mcbsp3_set_st_ch0_volume),
+ omap_mcbsp_get_st_ch0_volume,
+ omap_mcbsp_set_st_ch0_volume),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
-32768, 32767,
- omap_mcbsp3_get_st_ch1_volume,
- omap_mcbsp3_set_st_ch1_volume),
+ omap_mcbsp_get_st_ch1_volume,
+ omap_mcbsp_set_st_ch1_volume),
};
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
{
- if (!cpu_is_omap34xx())
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+ if (!mcbsp->st_data)
return -ENODEV;
- switch (mcbsp_id) {
- case 1: /* McBSP 2 */
- return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+ switch (cpu_dai->id) {
+ case 2: /* McBSP 2 */
+ return snd_soc_add_dai_controls(cpu_dai,
+ omap_mcbsp2_st_controls,
ARRAY_SIZE(omap_mcbsp2_st_controls));
- case 2: /* McBSP 3 */
- return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+ case 3: /* McBSP 3 */
+ return snd_soc_add_dai_controls(cpu_dai,
+ omap_mcbsp3_st_controls,
ARRAY_SIZE(omap_mcbsp3_st_controls));
default:
break;
@@ -766,18 +758,51 @@ 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);
+ struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct omap_mcbsp *mcbsp;
+ int ret;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "missing platform data.\n");
+ return -EINVAL;
+ }
+ mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL);
+ if (!mcbsp)
+ return -ENOMEM;
+
+ mcbsp->id = pdev->id;
+ mcbsp->pdata = pdata;
+ mcbsp->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mcbsp);
+
+ ret = omap_mcbsp_init(pdev);
+ if (!ret)
+ return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+
+ return ret;
}
static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
{
+ struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+
snd_soc_unregister_dai(&pdev->dev);
+
+ if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+ mcbsp->pdata->ops->free(mcbsp->id);
+
+ omap_mcbsp_sysfs_remove(mcbsp);
+
+ clk_put(mcbsp->fclk);
+
+ platform_set_drvdata(pdev, NULL);
+
return 0;
}
static struct platform_driver asoc_mcbsp_driver = {
.driver = {
- .name = "omap-mcbsp-dai",
+ .name = "omap-mcbsp",
.owner = THIS_MODULE,
},
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 65cde9d3807b..f877b16f19c9 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -59,6 +59,6 @@ enum omap_mcbsp_div {
#define NUM_LINKS 5
#endif
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
#endif
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 0e25df4fa9e5..39705561131a 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -419,12 +419,14 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
.channels_max = 5,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.channels_min = 1,
.channels_max = 3,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
+ .sig_bits = 24,
},
.ops = &omap_mcpdm_dai_ops,
};
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index f95fe3064172..b92248cbd47a 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -25,6 +25,8 @@
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
+struct snd_pcm_substream;
+
struct omap_pcm_dma_data {
char *name; /* stream identifier */
int dma_req; /* DMA request line */
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index 3357dcc47ed4..2830dfd05661 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -91,7 +91,7 @@ static struct snd_soc_ops omap3beagle_ops = {
static struct snd_soc_dai_link omap3beagle_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.platform_name = "omap-pcm-audio",
.codec_dai_name = "twl4030-hifi",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 071fcb09b8b2..3d468c9179d7 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -58,7 +58,7 @@ static struct snd_soc_ops omap3evm_ops = {
static struct snd_soc_dai_link omap3evm_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 07794bd10952..4c3a0978578a 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -208,7 +208,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
{
.name = "PCM1773",
.stream_name = "HiFi Out",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
@@ -219,7 +219,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
}, {
.name = "TWL4030",
.stream_name = "Line/Mic In",
- .cpu_dai_name = "omap-mcbsp-dai.3",
+ .cpu_dai_name = "omap-mcbsp.4",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index d859b597e7ec..b1a9d64cbc56 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -96,7 +96,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
static struct snd_soc_dai_link osk_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
- .cpu_dai_name = "omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "tlv320aic23-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic23-codec",
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index 2ee889c50256..6ac3e0c3c282 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -60,7 +60,7 @@ static struct snd_soc_ops overo_ops = {
static struct snd_soc_dai_link overo_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index fada6ef43eea..2712dd232b6d 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -59,9 +59,8 @@ static int rx51_spk_func;
static int rx51_dmic_func;
static int rx51_jack_func;
-static void rx51_ext_control(struct snd_soc_codec *codec)
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, hs = 0, tvout = 0;
switch (rx51_jack_func) {
@@ -102,11 +101,11 @@ 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->codec;
+ struct snd_soc_card *card = rtd->card;
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 0;
}
@@ -138,13 +137,13 @@ static int rx51_get_spk(struct snd_kcontrol *kcontrol,
static int rx51_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_spk_func == ucontrol->value.integer.value[0])
return 0;
rx51_spk_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -184,13 +183,13 @@ static int rx51_get_input(struct snd_kcontrol *kcontrol,
static int rx51_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_dmic_func == ucontrol->value.integer.value[0])
return 0;
rx51_dmic_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -206,13 +205,13 @@ static int rx51_get_jack(struct snd_kcontrol *kcontrol,
static int rx51_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_jack_func == ucontrol->value.integer.value[0])
return 0;
rx51_jack_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -297,7 +296,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "LINE1R");
/* Add RX-51 specific controls */
- err = snd_soc_add_controls(codec, aic34_rx51_controls,
+ err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
ARRAY_SIZE(aic34_rx51_controls));
if (err < 0)
return err;
@@ -314,7 +313,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
return err;
snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
- err = omap_mcbsp_st_add_controls(codec, 1);
+ err = omap_mcbsp_st_add_controls(rtd);
if (err < 0)
return err;
@@ -335,7 +334,7 @@ static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
{
int err;
- err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+ err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
ARRAY_SIZE(aic34_rx51_controlsb));
if (err < 0)
return err;
@@ -354,7 +353,7 @@ static struct snd_soc_dai_link rx51_dai[] = {
{
.name = "TLV320AIC34",
.stream_name = "AIC34",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "tlv320aic3x-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic3x-codec.2-0018",
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 2c850662ea7e..0e283226e2bf 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -187,7 +187,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
{
.name = "TWL4030 I2S",
.stream_name = "TWL4030 Audio",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
@@ -199,7 +199,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
{
.name = "TWL4030 PCM",
.stream_name = "TWL4030 Voice",
- .cpu_dai_name = "omap-mcbsp-dai.2",
+ .cpu_dai_name = "omap-mcbsp.3",
.codec_dai_name = "twl4030-voice",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
deleted file mode 100644
index 175ba9a04edf..000000000000
--- a/sound/soc/omap/sdp4430.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * sdp4430.c -- SoC audio for TI OMAP4430 SDP
- *
- * Author: 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
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/twl6040.h>
-#include <linux/module.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/jack.h>
-
-#include <asm/mach-types.h>
-#include <plat/hardware.h>
-#include <plat/mux.h>
-
-#include "omap-dmic.h"
-#include "omap-mcpdm.h"
-#include "omap-pcm.h"
-#include "../codecs/twl6040.h"
-
-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->codec_dai;
- int clk_id, freq;
- int ret;
-
- clk_id = twl6040_get_clk_id(rtd->codec);
- if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
- freq = 38400000;
- else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
- freq = 32768;
- else
- return -EINVAL;
-
- /* set the codec mclk */
- ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
- SND_SOC_CLOCK_IN);
- if (ret) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
- return ret;
-}
-
-static struct snd_soc_ops sdp4430_ops = {
- .hw_params = sdp4430_hw_params,
-};
-
-static int sdp4430_dmic_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;
- int ret = 0;
-
- ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
- 19200000, SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set DMIC cpu system clock\n");
- return ret;
- }
- ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
- SND_SOC_CLOCK_OUT);
- if (ret < 0) {
- printk(KERN_ERR "can't set DMIC output clock\n");
- return ret;
- }
- return 0;
-}
-
-static struct snd_soc_ops sdp4430_dmic_ops = {
- .hw_params = sdp4430_dmic_hw_params,
-};
-
-/* Headset jack */
-static struct snd_soc_jack hs_jack;
-
-/*Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin hs_jack_pins[] = {
- {
- .pin = "Headset Mic",
- .mask = SND_JACK_MICROPHONE,
- },
- {
- .pin = "Headset Stereophone",
- .mask = SND_JACK_HEADPHONE,
- },
-};
-
-/* SDP4430 machine DAPM */
-static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Ext Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
- SND_SOC_DAPM_MIC("Headset Mic", NULL),
- SND_SOC_DAPM_HP("Headset Stereophone", NULL),
- SND_SOC_DAPM_SPK("Earphone Spk", NULL),
- SND_SOC_DAPM_INPUT("FM Stereo In"),
-};
-
-static const struct snd_soc_dapm_route audio_map[] = {
- /* External Mics: MAINMIC, SUBMIC with bias*/
- {"MAINMIC", NULL, "Main Mic Bias"},
- {"SUBMIC", NULL, "Main Mic Bias"},
- {"Main Mic Bias", NULL, "Ext Mic"},
-
- /* External Speakers: HFL, HFR */
- {"Ext Spk", NULL, "HFL"},
- {"Ext Spk", NULL, "HFR"},
-
- /* Headset Mic: HSMIC with bias */
- {"HSMIC", NULL, "Headset Mic Bias"},
- {"Headset Mic Bias", NULL, "Headset Mic"},
-
- /* Headset Stereophone (Headphone): HSOL, HSOR */
- {"Headset Stereophone", NULL, "HSOL"},
- {"Headset Stereophone", NULL, "HSOR"},
-
- /* Earphone speaker */
- {"Earphone Spk", NULL, "EP"},
-
- /* Aux/FM Stereo In: AFML, AFMR */
- {"AFML", NULL, "FM Stereo In"},
- {"AFMR", NULL, "FM Stereo In"},
-};
-
-static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- int ret, hs_trim;
-
- /*
- * Configure McPDM offset cancellation based on the HSOTRIM value from
- * twl6040.
- */
- hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
- omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
- TWL6040_HSF_TRIM_RIGHT(hs_trim));
-
- /* Headset jack detection */
- ret = snd_soc_jack_new(codec, "Headset Jack",
- SND_JACK_HEADSET, &hs_jack);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
-
- if (machine_is_omap_4430sdp())
- twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
- else
- snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
-
- return ret;
-}
-
-static const struct snd_soc_dapm_widget sdp4430_dmic_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Digital Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route dmic_audio_map[] = {
- {"DMic", NULL, "Digital Mic1 Bias"},
- {"Digital Mic1 Bias", NULL, "Digital Mic"},
-};
-
-static int sdp4430_dmic_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm, sdp4430_dmic_dapm_widgets,
- ARRAY_SIZE(sdp4430_dmic_dapm_widgets));
- if (ret)
- return ret;
-
- return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
- ARRAY_SIZE(dmic_audio_map));
-}
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai[] = {
- {
- .name = "TWL6040",
- .stream_name = "TWL6040",
- .cpu_dai_name = "omap-mcpdm",
- .codec_dai_name = "twl6040-legacy",
- .platform_name = "omap-pcm-audio",
- .codec_name = "twl6040-codec",
- .init = sdp4430_twl6040_init,
- .ops = &sdp4430_ops,
- },
- {
- .name = "DMIC",
- .stream_name = "DMIC Capture",
- .cpu_dai_name = "omap-dmic",
- .codec_dai_name = "dmic-hifi",
- .platform_name = "omap-pcm-audio",
- .codec_name = "dmic-codec",
- .init = sdp4430_dmic_init,
- .ops = &sdp4430_dmic_ops,
- },
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_sdp4430 = {
- .name = "SDP4430",
- .owner = THIS_MODULE,
- .dai_link = sdp4430_dai,
- .num_links = ARRAY_SIZE(sdp4430_dai),
-
- .dapm_widgets = sdp4430_twl6040_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets),
- .dapm_routes = audio_map,
- .num_dapm_routes = ARRAY_SIZE(audio_map),
-};
-
-static struct platform_device *sdp4430_snd_device;
-
-static int __init sdp4430_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap_4430sdp())
- return -ENODEV;
- printk(KERN_INFO "SDP4430 SoC init\n");
-
- sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
- if (!sdp4430_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
-
- ret = platform_device_add(sdp4430_snd_device);
- if (ret)
- goto err;
-
- return 0;
-
-err:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(sdp4430_snd_device);
- return ret;
-}
-module_init(sdp4430_soc_init);
-
-static void __exit sdp4430_soc_exit(void)
-{
- platform_device_unregister(sdp4430_snd_device);
-}
-module_exit(sdp4430_soc_exit);
-
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
-MODULE_DESCRIPTION("ALSA SoC SDP4430");
-MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 981616d61f67..920e0d9e03db 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link zoom2_dai[] = {
{
.name = "TWL4030 I2S",
.stream_name = "TWL4030 Audio",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
@@ -143,7 +143,7 @@ static struct snd_soc_dai_link zoom2_dai[] = {
{
.name = "TWL4030 PCM",
.stream_name = "TWL4030 Voice",
- .cpu_dai_name = "omap-mcbsp-dai.2",
+ .cpu_dai_name = "omap-mcbsp.3",
.codec_dai_name = "twl4030-voice",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index bc21944851c4..863367ad89ce 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -45,10 +45,8 @@
static int corgi_jack_func;
static int corgi_spk_func;
-static void corgi_ext_control(struct snd_soc_codec *codec)
+static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
switch (corgi_jack_func) {
case CORGI_HP:
@@ -104,7 +102,7 @@ static int corgi_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- corgi_ext_control(codec);
+ corgi_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -173,13 +171,13 @@ static int corgi_get_jack(struct snd_kcontrol *kcontrol,
static int corgi_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_jack_func == ucontrol->value.integer.value[0])
return 0;
corgi_jack_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
@@ -193,13 +191,13 @@ static int corgi_get_spk(struct snd_kcontrol *kcontrol,
static int corgi_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_spk_func == ucontrol->value.integer.value[0])
return 0;
corgi_spk_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 3f7a8ecb9720..aace19e0fe2c 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -411,7 +411,7 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "VINR");
/* Add magician specific controls */
- err = snd_soc_add_controls(codec, uda1380_magician_controls,
+ err = snd_soc_add_codec_controls(codec, uda1380_magician_controls,
ARRAY_SIZE(uda1380_magician_controls));
if (err < 0)
return err;
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index fd0ed10c6fe7..d2cc81735036 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -43,10 +43,8 @@
static int poodle_jack_func;
static int poodle_spk_func;
-static void poodle_ext_control(struct snd_soc_codec *codec)
+static void poodle_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
if (poodle_jack_func == POODLE_HP) {
/* set = unmute headphone */
@@ -81,7 +79,7 @@ static int poodle_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- poodle_ext_control(codec);
+ poodle_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -152,13 +150,13 @@ static int poodle_get_jack(struct snd_kcontrol *kcontrol,
static int poodle_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_jack_func == ucontrol->value.integer.value[0])
return 0;
poodle_jack_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
@@ -172,13 +170,13 @@ static int poodle_get_spk(struct snd_kcontrol *kcontrol,
static int poodle_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_spk_func == ucontrol->value.integer.value[0])
return 0;
poodle_spk_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a57cfbc038e3..a16df0fa6eff 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -764,7 +764,8 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai)
#define PXA_SSP_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_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 837ff341fd6d..4800d5fe568d 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -103,7 +103,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
#define pxa2xx_ac97_resume NULL
#endif
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
}
@@ -179,7 +179,7 @@ static const 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.
*/
-static struct snd_soc_dai_driver pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
{
.name = "pxa2xx-ac97",
.ac97_control = 1,
@@ -244,13 +244,13 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
* driver to do interesting things with the clocking to get us up
* and running.
*/
- return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
- ARRAY_SIZE(pxa_ac97_dai));
+ return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
+ ARRAY_SIZE(pxa_ac97_dai_driver));
}
static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
return 0;
}
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index ba1545188ec6..083706595495 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -232,7 +232,7 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
.cpu_dai_name = "pxa-ssp-dai.0", \
.platform_name = "pxa-pcm-audio", \
.codec_dai_name = "cs4270-hifi", \
- .codec_name = "cs4270-codec.0-0048", \
+ .codec_name = "cs4270.0-0048", \
.ops = &raumfeld_cs4270_ops, \
}
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 90c5245c4742..fc052d8247ff 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -44,10 +44,8 @@ static int spitz_jack_func;
static int spitz_spk_func;
static int spitz_mic_gpio;
-static void spitz_ext_control(struct snd_soc_codec *codec)
+static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
if (spitz_spk_func == SPITZ_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
else
@@ -113,7 +111,7 @@ static int spitz_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- spitz_ext_control(codec);
+ spitz_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -173,13 +171,13 @@ static int spitz_get_jack(struct snd_kcontrol *kcontrol,
static int spitz_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_jack_func == ucontrol->value.integer.value[0])
return 0;
spitz_jack_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
@@ -193,13 +191,13 @@ static int spitz_get_spk(struct snd_kcontrol *kcontrol,
static int spitz_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_spk_func == ucontrol->value.integer.value[0])
return 0;
spitz_spk_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 564ef08a89f2..2aec63f3706a 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -197,7 +197,7 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "MONOOUT");
/* add tosa specific controls */
- err = snd_soc_add_controls(codec, tosa_controls,
+ err = snd_soc_add_codec_controls(codec, tosa_controls,
ARRAY_SIZE(tosa_controls));
if (err < 0)
return err;
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 43c014f362f6..716da861c629 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -435,7 +435,8 @@ 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(runtime->cpu_dai, pcm->streams[0].substream);
+ snd_soc_dai_get_dma_data(runtime->cpu_dai,
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
free_irq(params->irq, pcm);
snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -451,7 +452,7 @@ static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
int res;
params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
- pcm->streams[0].substream);
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
if (!card->dev->dma_mask)
card->dev->dma_mask = &s6000_pcm_dmamask;
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 7b9bf93e3701..3d04c1fa6781 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -4,7 +4,7 @@
* Evolved from s3c2443-ac97.c
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* Credits: Graeme Gregory, Sean Choi
*
* This program is free software; you can redistribute it and/or modify
@@ -511,7 +511,7 @@ static struct platform_driver s3c_ac97_driver = {
module_platform_driver(s3c_ac97_driver);
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-ac97");
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index e4ba17ce6b32..ddc6cde14e2a 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -411,7 +411,7 @@ static int dma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &dma_mask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = preallocate_dma_buffer(pcm,
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 87a874dc7a35..6553b19c70c7 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.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
@@ -761,15 +761,13 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
local_irq_save(flags);
- if (capture)
+ if (capture) {
i2s_rxctrl(i2s, 0);
- else
- i2s_txctrl(i2s, 0);
-
- if (capture)
i2s_fifo(i2s, FIC_RXFLUSH);
- else
+ } else {
+ i2s_txctrl(i2s, 0);
i2s_fifo(i2s, FIC_TXFLUSH);
+ }
local_irq_restore(flags);
break;
@@ -1143,7 +1141,7 @@ static struct platform_driver samsung_i2s_driver = {
module_platform_driver(samsung_i2s_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("Samsung I2S Interface");
MODULE_ALIAS("platform:samsung-i2s");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h
index 8e15f6a616d1..d420a7ca56ca 100644
--- a/sound/soc/samsung/i2s.h
+++ b/sound/soc/samsung/i2s.h
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.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
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index 9dd818bde06f..e7416851bf7d 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -189,6 +189,9 @@ static int littlemill_late_probe(struct snd_soc_card *card)
/* This will check device compatibility itself */
wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+ /* As will this */
+ wm8994_mic_detect(codec, &littlemill_headset, 1);
+
return 0;
}
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 7ac0ba2025c3..321d51134e47 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
/* GTA02 specific routes and controls */
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
static int gta02_speaker_enabled;
static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -298,7 +296,7 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+ ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls,
ARRAY_SIZE(neo1973_gta02_wm8753_controls));
if (ret)
return ret;
@@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
return 0;
}
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
int ret;
/* set up NC codec pins */
- if (machine_is_neo1973_gta01()) {
- snd_soc_dapm_nc_pin(dapm, "LOUT2");
- snd_soc_dapm_nc_pin(dapm, "ROUT2");
- }
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "OUT4");
snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -338,7 +328,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return ret;
/* add neo1973 specific controls */
- ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+ ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls,
ARRAY_SIZE(neo1973_wm8753_controls));
if (ret)
return ret;
@@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
- {"Amp IN", NULL, "ROUT1"},
- {"Amp IN", NULL, "LOUT1"},
-
- {"Handset Spk", NULL, "Amp EP"},
- {"Stereo Out", NULL, "Amp LS"},
- {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
- SND_SOC_DAPM_SPK("Handset Spk", NULL),
- SND_SOC_DAPM_SPK("Stereo Out", NULL),
- SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
- ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
- if (ret)
- return ret;
-
- ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
- ARRAY_SIZE(neo1973_lm4857_routes));
- if (ret)
- return ret;
-
- snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
- snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
- snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
- return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
static struct snd_soc_dai_link neo1973_dai[] = {
{ /* Hifi Playback - for similatious use with voice below */
.name = "WM8753",
@@ -421,7 +367,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.platform_name = "samsung-audio",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "wm8753-hifi",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.init = neo1973_wm8753_init,
.ops = &neo1973_hifi_ops,
},
@@ -430,7 +376,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.stream_name = "Voice",
.cpu_dai_name = "dfbmcs320-pcm",
.codec_dai_name = "wm8753-voice",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.ops = &neo1973_voice_ops,
},
};
@@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {
.name = "dfbmcs320",
.codec_name = "dfbmcs320.0",
},
- {
- .name = "lm4857",
- .codec_name = "lm4857.0-007c",
- .init = neo1973_lm4857_init,
- },
};
static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {
},
};
-#ifdef CONFIG_MACH_NEO1973_GTA02
static const struct gpio neo1973_gta02_gpios[] = {
{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
};
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
static struct snd_soc_card neo1973 = {
.name = "neo1973",
@@ -480,7 +417,7 @@ static int __init neo1973_init(void)
{
int ret;
- if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+ if (!machine_is_neo1973_gta02())
return -ENODEV;
if (machine_is_neo1973_gta02()) {
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 56780206c000..b7b2a1f91425 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - S3C PCM-Controller driver
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* based upon I2S drivers by Ben Dooks.
*
* This program is free software; you can redistribute it and/or modify
@@ -639,7 +639,7 @@ static struct platform_driver s3c_pcm_driver = {
module_platform_driver(s3c_pcm_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("S3C PCM Controller Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index a253bcc1646a..656d5afe4ca9 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -134,18 +134,18 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
if (pdata->amp_gpio > 0) {
pr_debug("%s: adding amp routes\n", __func__);
- snd_soc_add_controls(codec, amp_unmute_controls,
+ snd_soc_add_card_controls(card, amp_unmute_controls,
ARRAY_SIZE(amp_unmute_controls));
}
if (pdata->amp_gain[0] > 0) {
pr_debug("%s: adding amp controls\n", __func__);
- snd_soc_add_controls(codec, amp_gain_controls,
+ snd_soc_add_card_controls(card, amp_gain_controls,
ARRAY_SIZE(amp_gain_controls));
}
}
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index bff8758e7f20..ade2809cf393 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -2,7 +2,7 @@
* smdk_wm8580.c
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@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
@@ -253,6 +253,6 @@ static void __exit smdk_audio_exit(void)
}
module_exit(smdk_audio_exit);
-MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index 8e26a730fcdc..55b2ca7f3290 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -2,7 +2,7 @@
* smdk_wm9713.c -- SoC audio for SMDK
*
* Copyright 2010 Samsung Electronics Co. Ltd.
- * Author: Jaswinder Singh Brar <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh Brar <jassisinghbrar@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
@@ -103,6 +103,6 @@ module_init(smdk_init);
module_exit(smdk_exit);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh Brar, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index db6c89a28bda..378cc5b056d7 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -13,8 +13,11 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/soc.h>
@@ -53,6 +56,7 @@
/* DO_FMT */
/* DI_FMT */
+#define CR_BWS_MASK (0x3 << 20) /* FSI2 */
#define CR_BWS_24 (0x0 << 20) /* FSI2 */
#define CR_BWS_16 (0x1 << 20) /* FSI2 */
#define CR_BWS_20 (0x2 << 20) /* FSI2 */
@@ -68,6 +72,15 @@
#define CR_TDM (0x4 << 4)
#define CR_TDM_D (0x5 << 4)
+/* OUT_DMAC */
+/* IN_DMAC */
+#define VDMD_MASK (0x3 << 4)
+#define VDMD_FRONT (0x0 << 4) /* Package in front */
+#define VDMD_BACK (0x1 << 4) /* Package in back */
+#define VDMD_STREAM (0x2 << 4) /* Stream mode(16bit * 2) */
+
+#define DMA_ON (0x1 << 0)
+
/* DOFF_CTL */
/* DIFF_CTL */
#define IRQ_HALF 0x00100000
@@ -116,7 +129,7 @@
#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
/*
* FSI driver use below type name for variable
@@ -159,22 +172,41 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
* struct
*/
+struct fsi_stream_handler;
struct fsi_stream {
- struct snd_pcm_substream *substream;
+ /*
+ * these are initialized by fsi_stream_init()
+ */
+ struct snd_pcm_substream *substream;
int fifo_sample_capa; /* sample capacity of FSI FIFO */
int buff_sample_capa; /* sample capacity of ALSA buffer */
int buff_sample_pos; /* sample position of ALSA buffer */
int period_samples; /* sample number / 1 period */
int period_pos; /* current period position */
-
+ int sample_width; /* sample width */
int uerr_num;
int oerr_num;
+
+ /*
+ * thse are initialized by fsi_handler_init()
+ */
+ struct fsi_stream_handler *handler;
+ struct fsi_priv *priv;
+
+ /*
+ * these are for DMAEngine
+ */
+ struct dma_chan *chan;
+ struct sh_dmae_slave slave; /* see fsi_handler_init() */
+ struct tasklet_struct tasklet;
+ dma_addr_t dma;
};
struct fsi_priv {
void __iomem *base;
struct fsi_master *master;
+ struct sh_fsi_port_info *info;
struct fsi_stream playback;
struct fsi_stream capture;
@@ -189,6 +221,20 @@ struct fsi_priv {
long rate;
};
+struct fsi_stream_handler {
+ int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+ void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable);
+};
+#define fsi_stream_handler_call(io, func, args...) \
+ (!(io) ? -ENODEV : \
+ !((io)->handler->func) ? 0 : \
+ (io)->handler->func(args))
+
struct fsi_core {
int ver;
@@ -205,10 +251,11 @@ struct fsi_master {
struct fsi_priv fsia;
struct fsi_priv fsib;
struct fsi_core *core;
- struct sh_fsi_platform_info *info;
spinlock_t lock;
};
+static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io);
+
/*
* basic read write function
*/
@@ -295,6 +342,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
return fsi->spdif;
}
+static int fsi_is_play(struct snd_pcm_substream *substream)
+{
+ return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -317,44 +369,25 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
return fsi_get_priv_frm_dai(fsi_get_dai(substream));
}
-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi)
{
- if (!master->info)
+ if (!fsi->info)
return NULL;
- return master->info->set_rate;
+ return fsi->info->set_rate;
}
static u32 fsi_get_info_flags(struct fsi_priv *fsi)
{
- int is_porta = fsi_is_port_a(fsi);
- struct fsi_master *master = fsi_get_master(fsi);
-
- if (!master->info)
+ if (!fsi->info)
return 0;
- return is_porta ? master->info->porta_flags :
- master->info->portb_flags;
-}
-
-static inline int fsi_stream_is_play(int stream)
-{
- return stream == SNDRV_PCM_STREAM_PLAYBACK;
+ return fsi->info->flags;
}
-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 u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
{
+ int is_play = fsi_stream_is_play(fsi, io);
int is_porta = fsi_is_port_a(fsi);
u32 shift;
@@ -376,26 +409,81 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
return samples / fsi->chan_num;
}
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 status;
+ int frames;
+
+ status = is_play ?
+ fsi_reg_read(fsi, DOFF_ST) :
+ fsi_reg_read(fsi, DIFF_ST);
+
+ frames = 0x1ff & (status >> 8);
+
+ return fsi_frame2sample(fsi, frames);
+}
+
+static void fsi_count_fifo_err(struct fsi_priv *fsi)
+{
+ u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
+ u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+
+ if (ostatus & ERR_OVER)
+ fsi->playback.oerr_num++;
+
+ if (ostatus & ERR_UNDER)
+ fsi->playback.uerr_num++;
+
+ if (istatus & ERR_OVER)
+ fsi->capture.oerr_num++;
+
+ if (istatus & ERR_UNDER)
+ fsi->capture.uerr_num++;
+
+ fsi_reg_write(fsi, DOFF_ST, 0);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+}
+
+/*
+ * fsi_stream_xx() function
+ */
+static inline int fsi_stream_is_play(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ return &fsi->playback == io;
+}
+
+static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
+ struct snd_pcm_substream *substream)
+{
+ return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
+}
+
static int fsi_stream_is_working(struct fsi_priv *fsi,
- int is_play)
+ struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
int ret;
spin_lock_irqsave(&master->lock, flags);
- ret = !!io->substream;
+ ret = !!(io->substream && io->substream->runtime);
spin_unlock_irqrestore(&master->lock, flags);
return ret;
}
-static void fsi_stream_push(struct fsi_priv *fsi,
- int is_play,
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+ return io->priv;
+}
+
+static void fsi_stream_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
struct snd_pcm_substream *substream)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -406,14 +494,15 @@ static void fsi_stream_push(struct fsi_priv *fsi,
io->buff_sample_pos = 0;
io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
io->period_pos = 0;
+ io->sample_width = samples_to_bytes(runtime, 1);
io->oerr_num = -1; /* ignore 1st err */
io->uerr_num = -1; /* ignore 1st err */
+ fsi_stream_handler_call(io, init, fsi, io);
spin_unlock_irqrestore(&master->lock, flags);
}
-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
+static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_soc_dai *dai = fsi_get_dai(io->substream);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -426,127 +515,87 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
if (io->uerr_num > 0)
dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
+ fsi_stream_handler_call(io, quit, fsi, io);
io->substream = NULL;
io->buff_sample_capa = 0;
io->buff_sample_pos = 0;
io->period_samples = 0;
io->period_pos = 0;
+ io->sample_width = 0;
io->oerr_num = 0;
io->uerr_num = 0;
spin_unlock_irqrestore(&master->lock, flags);
}
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
+static int fsi_stream_transfer(struct fsi_stream *io)
{
- u32 status;
- int frames;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ if (!fsi)
+ return -EIO;
- status = is_play ?
- fsi_reg_read(fsi, DOFF_ST) :
- fsi_reg_read(fsi, DIFF_ST);
-
- frames = 0x1ff & (status >> 8);
-
- return fsi_frame2sample(fsi, frames);
+ return fsi_stream_handler_call(io, transfer, fsi, io);
}
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
-{
- u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
- u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+#define fsi_stream_start(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 1)
- if (ostatus & ERR_OVER)
- fsi->playback.oerr_num++;
-
- if (ostatus & ERR_UNDER)
- fsi->playback.uerr_num++;
-
- if (istatus & ERR_OVER)
- fsi->capture.oerr_num++;
-
- if (istatus & ERR_UNDER)
- fsi->capture.uerr_num++;
+#define fsi_stream_stop(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 0)
- fsi_reg_write(fsi, DOFF_ST, 0);
- fsi_reg_write(fsi, DIFF_ST, 0);
-}
-
-/*
- * dma function
- */
-
-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
+static int fsi_stream_probe(struct fsi_priv *fsi)
{
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct fsi_stream *io;
+ int ret1, ret2;
- return runtime->dma_area +
- samples_to_bytes(runtime, io->buff_sample_pos);
-}
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, probe, fsi, io);
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
-{
- u16 *start;
- int i;
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, probe, fsi, io);
- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
- 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;
-
- 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);
+ return 0;
}
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+static int fsi_stream_remove(struct fsi_priv *fsi)
{
- u32 *start;
- int i;
-
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ struct fsi_stream *io;
+ int ret1, ret2;
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, remove, fsi, io);
- 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;
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, remove, fsi, io);
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
- for (i = 0; i < num; i++)
- *(start + i) = fsi_reg_read(fsi, DIDT);
+ return 0;
}
/*
* irq function
*/
-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, data);
fsi_core_mask_set(master, iemsk, data, data);
}
-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, 0);
@@ -563,8 +612,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
u32 data = 0;
struct fsi_master *master = fsi_get_master(fsi);
- data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
- data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
/* clear interrupt factor */
fsi_core_mask_set(master, int_st, data, 0);
@@ -600,11 +649,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
int fsi_ver = master->core->ver;
int ret;
- ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+ if (!set_rate)
+ return 0;
+
+ ret = set_rate(dev, rate, enable);
if (ret < 0) /* error */
return ret;
@@ -671,96 +723,64 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
return ret;
}
-#define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1)
-#define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
+/*
+ * pio data transfer handler
+ */
+static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+ u16 *buf = (u16 *)_buf;
+ int i;
- if (enable)
- fsi_irq_enable(fsi, is_play);
- else
- fsi_irq_disable(fsi, is_play);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+}
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u16 *buf = (u16 *)_buf;
+ int i;
+
+ for (i = 0; i < samples; i++)
+ *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
}
-/*
- * ctrl function
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
- int is_play,
- struct device *dev)
+static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- u32 shift, i;
- int frame_capa;
+ u32 *buf = (u32 *)_buf;
+ int i;
- /* get on-chip RAM capacity */
- shift = fsi_master_read(master, FIFO_SZ);
- shift >>= fsi_get_port_shift(fsi, is_play);
- shift &= FIFO_SZ_MASK;
- frame_capa = 256 << shift;
- dev_dbg(dev, "fifo = %d words\n", frame_capa);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, *(buf + i));
+}
- /*
- * The maximum number of sample data varies depending
- * on the number of channels selected for the format.
- *
- * FIFOs are used in 4-channel units in 3-channel mode
- * and in 8-channel units in 5- to 7-channel mode
- * meaning that more FIFOs than the required size of DPRAM
- * are used.
- *
- * ex) if 256 words of DP-RAM is connected
- * 1 channel: 256 (256 x 1 = 256)
- * 2 channels: 128 (128 x 2 = 256)
- * 3 channels: 64 ( 64 x 3 = 192)
- * 4 channels: 64 ( 64 x 4 = 256)
- * 5 channels: 32 ( 32 x 5 = 160)
- * 6 channels: 32 ( 32 x 6 = 192)
- * 7 channels: 32 ( 32 x 7 = 224)
- * 8 channels: 32 ( 32 x 8 = 256)
- */
- for (i = 1; i < fsi->chan_num; i <<= 1)
- frame_capa >>= 1;
- dev_dbg(dev, "%d channel %d store\n",
- fsi->chan_num, frame_capa);
+static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u32 *buf = (u32 *)_buf;
+ int i;
- io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+ for (i = 0; i < samples; i++)
+ *(buf + i) = fsi_reg_read(fsi, DIDT);
+}
- /*
- * set interrupt generation factor
- * clear FIFO
- */
- if (is_play) {
- fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
- } else {
- fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
- }
+static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return runtime->dma_area +
+ samples_to_bytes(runtime, io->buff_sample_pos);
}
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
+static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
+ void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
+ void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
+ int samples)
{
struct snd_pcm_runtime *runtime;
- struct snd_pcm_substream *substream = NULL;
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- int sample_residues;
- int sample_width;
- int samples;
- int samples_max;
+ struct snd_pcm_substream *substream;
+ u8 *buf;
int over_period;
- void (*fn)(struct fsi_priv *fsi, int size);
- if (!fsi ||
- !io->substream ||
- !io->substream->runtime)
+ if (!fsi_stream_is_working(fsi, io))
return -EINVAL;
over_period = 0;
@@ -780,60 +800,19 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
io->buff_sample_pos = 0;
}
- /* get 1 sample data width */
- sample_width = samples_to_bytes(runtime, 1);
-
- /* get number of residue samples */
- sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+ buf = fsi_pio_get_area(fsi, io);
- if (is_play) {
- /*
- * for play-back
- *
- * samples_max : number of FSI fifo free samples space
- * samples : number of ALSA residue samples
- */
- samples_max = io->fifo_sample_capa;
- samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
-
- samples = sample_residues;
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_push16;
- break;
- case 4:
- fn = fsi_dma_soft_push32;
- break;
- default:
- return -EINVAL;
- }
- } else {
- /*
- * for capture
- *
- * samples_max : number of ALSA free samples space
- * samples : number of samples in FSI fifo
- */
- samples_max = sample_residues;
- samples = fsi_get_current_fifo_samples(fsi, is_play);
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_pop16;
- break;
- case 4:
- fn = fsi_dma_soft_pop32;
- break;
- default:
- return -EINVAL;
- }
+ switch (io->sample_width) {
+ case 2:
+ run16(fsi, buf, samples);
+ break;
+ case 4:
+ run32(fsi, buf, samples);
+ break;
+ default:
+ return -EINVAL;
}
- samples = min(samples, samples_max);
-
- fn(fsi, samples);
-
/* update buff_sample_pos */
io->buff_sample_pos += samples;
@@ -843,16 +822,66 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
return 0;
}
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ int sample_residues; /* samples in FSI fifo */
+ int sample_space; /* ALSA free samples space */
+ int samples;
+
+ sample_residues = fsi_get_current_fifo_samples(fsi, io);
+ sample_space = io->buff_sample_capa - io->buff_sample_pos;
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_pop16,
+ fsi_pio_pop32,
+ samples);
+}
+
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ int sample_residues; /* ALSA residue samples */
+ int sample_space; /* FSI fifo free samples space */
+ int samples;
+
+ sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+ sample_space = io->fifo_sample_capa -
+ fsi_get_current_fifo_samples(fsi, io);
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_push16,
+ fsi_pio_push32,
+ samples);
}
-static int fsi_data_push(struct fsi_priv *fsi)
+static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ struct fsi_master *master = fsi_get_master(fsi);
+ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+
+ if (enable)
+ fsi_irq_enable(fsi, io);
+ else
+ fsi_irq_disable(fsi, io);
+
+ if (fsi_is_clk_master(fsi))
+ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
+static struct fsi_stream_handler fsi_pio_push_handler = {
+ .transfer = fsi_pio_push,
+ .start_stop = fsi_pio_start_stop,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+ .transfer = fsi_pio_pop,
+ .start_stop = fsi_pio_start_stop,
+};
+
static irqreturn_t fsi_interrupt(int irq, void *data)
{
struct fsi_master *master = data;
@@ -863,13 +892,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
fsi_master_mask_set(master, SOFT_RST, IR, IR);
if (int_st & AB_IO(1, AO_SHIFT))
- fsi_data_push(&master->fsia);
+ fsi_stream_transfer(&master->fsia.playback);
if (int_st & AB_IO(1, BO_SHIFT))
- fsi_data_push(&master->fsib);
+ fsi_stream_transfer(&master->fsib.playback);
if (int_st & AB_IO(1, AI_SHIFT))
- fsi_data_pop(&master->fsia);
+ fsi_stream_transfer(&master->fsia.capture);
if (int_st & AB_IO(1, BI_SHIFT))
- fsi_data_pop(&master->fsib);
+ fsi_stream_transfer(&master->fsib.capture);
fsi_count_fifo_err(&master->fsia);
fsi_count_fifo_err(&master->fsib);
@@ -881,11 +910,271 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
}
/*
+ * dma data transfer handler
+ */
+static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ io->dma = dma_map_single(dai->dev, runtime->dma_area,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_unmap_single(dai->dev, io->dma,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static void fsi_dma_complete(void *data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_sync_single_for_cpu(dai->dev, io->dma,
+ samples_to_bytes(runtime, io->period_samples), dir);
+
+ io->buff_sample_pos += io->period_samples;
+ io->period_pos++;
+
+ if (io->period_pos >= runtime->periods) {
+ io->period_pos = 0;
+ io->buff_sample_pos = 0;
+ }
+
+ fsi_count_fifo_err(fsi);
+ fsi_stream_transfer(io);
+
+ snd_pcm_period_elapsed(io->substream);
+}
+
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+}
+
+static void fsi_dma_do_tasklet(unsigned long data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct dma_chan *chan;
+ struct snd_soc_dai *dai;
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist sg;
+ struct snd_pcm_runtime *runtime;
+ enum dma_data_direction dir;
+ dma_cookie_t cookie;
+ int is_play = fsi_stream_is_play(fsi, io);
+ int len;
+ dma_addr_t buf;
+
+ if (!fsi_stream_is_working(fsi, io))
+ return;
+
+ dai = fsi_get_dai(io->substream);
+ chan = io->chan;
+ runtime = io->substream->runtime;
+ dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ len = samples_to_bytes(runtime, io->period_samples);
+ buf = fsi_dma_get_area(io);
+
+ dma_sync_single_for_device(dai->dev, io->dma, len, dir);
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+ len , offset_in_page(buf));
+ sg_dma_address(&sg) = buf;
+ sg_dma_len(&sg) = len;
+
+ desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
+ DMA_PREP_INTERRUPT |
+ DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(dai->dev, "device_prep_slave_sg() fail\n");
+ return;
+ }
+
+ desc->callback = fsi_dma_complete;
+ desc->callback_param = io;
+
+ cookie = desc->tx_submit(desc);
+ if (cookie < 0) {
+ dev_err(dai->dev, "tx_submit() fail\n");
+ return;
+ }
+
+ dma_async_issue_pending(chan);
+
+ /*
+ * FIXME
+ *
+ * In DMAEngine case, codec and FSI cannot be started simultaneously
+ * since FSI is using tasklet.
+ * Therefore, in capture case, probably FSI FIFO will have got
+ * overflow error in this point.
+ * in that case, DMA cannot start transfer until error was cleared.
+ */
+ if (!is_play) {
+ if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) {
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+ }
+ }
+}
+
+static bool fsi_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct sh_dmae_slave *slave = param;
+
+ chan->private = slave;
+
+ return true;
+}
+
+static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_schedule(&io->tasklet);
+
+ return 0;
+}
+
+static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int start)
+{
+ u32 bws;
+ u32 dma;
+
+ switch (io->sample_width * start) {
+ case 2:
+ bws = CR_BWS_16;
+ dma = VDMD_STREAM | DMA_ON;
+ break;
+ case 4:
+ bws = CR_BWS_24;
+ dma = VDMD_BACK | DMA_ON;
+ break;
+ default:
+ bws = 0;
+ dma = 0;
+ }
+
+ fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
+ fsi_reg_write(fsi, OUT_DMAC, dma);
+}
+
+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+ if (!io->chan)
+ return -EIO;
+
+ tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+
+ return 0;
+}
+
+static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_kill(&io->tasklet);
+
+ fsi_stream_stop(fsi, io);
+
+ if (io->chan)
+ dma_release_channel(io->chan);
+
+ io->chan = NULL;
+ return 0;
+}
+
+static struct fsi_stream_handler fsi_dma_push_handler = {
+ .init = fsi_dma_init,
+ .quit = fsi_dma_quit,
+ .probe = fsi_dma_probe,
+ .transfer = fsi_dma_transfer,
+ .remove = fsi_dma_remove,
+ .start_stop = fsi_dma_push_start_stop,
+};
+
+/*
* dai ops
*/
+static void fsi_fifo_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
+ struct device *dev)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 shift, i;
+ int frame_capa;
+
+ /* get on-chip RAM capacity */
+ shift = fsi_master_read(master, FIFO_SZ);
+ shift >>= fsi_get_port_shift(fsi, io);
+ shift &= FIFO_SZ_MASK;
+ frame_capa = 256 << shift;
+ dev_dbg(dev, "fifo = %d words\n", frame_capa);
+
+ /*
+ * The maximum number of sample data varies depending
+ * on the number of channels selected for the format.
+ *
+ * FIFOs are used in 4-channel units in 3-channel mode
+ * and in 8-channel units in 5- to 7-channel mode
+ * meaning that more FIFOs than the required size of DPRAM
+ * are used.
+ *
+ * ex) if 256 words of DP-RAM is connected
+ * 1 channel: 256 (256 x 1 = 256)
+ * 2 channels: 128 (128 x 2 = 256)
+ * 3 channels: 64 ( 64 x 3 = 192)
+ * 4 channels: 64 ( 64 x 4 = 256)
+ * 5 channels: 32 ( 32 x 5 = 160)
+ * 6 channels: 32 ( 32 x 6 = 192)
+ * 7 channels: 32 ( 32 x 7 = 224)
+ * 8 channels: 32 ( 32 x 8 = 256)
+ */
+ for (i = 1; i < fsi->chan_num; i <<= 1)
+ frame_capa >>= 1;
+ dev_dbg(dev, "%d channel %d store\n",
+ fsi->chan_num, frame_capa);
+
+ io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+
+ /*
+ * set interrupt generation factor
+ * clear FIFO
+ */
+ if (is_play) {
+ fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
+ } else {
+ fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ }
+}
static int fsi_hw_startup(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
struct fsi_master *master = fsi_get_master(fsi);
@@ -934,17 +1223,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
}
/* irq clear */
- fsi_irq_disable(fsi, is_play);
+ fsi_irq_disable(fsi, io);
fsi_irq_clear_status(fsi);
/* fifo init */
- fsi_fifo_init(fsi, is_play, dev);
+ fsi_fifo_init(fsi, io, dev);
return 0;
}
static void fsi_hw_shutdown(struct fsi_priv *fsi,
- int is_play,
struct device *dev)
{
if (fsi_is_clk_master(fsi))
@@ -955,18 +1243,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
- return fsi_hw_startup(fsi, is_play, dai->dev);
+ return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
}
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 = fsi_is_play(substream);
- fsi_hw_shutdown(fsi, is_play, dai->dev);
+ fsi_hw_shutdown(fsi, dai->dev);
fsi->rate = 0;
}
@@ -974,18 +1260,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- fsi_stream_push(fsi, is_play, substream);
- ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
- fsi_port_start(fsi, is_play);
+ fsi_stream_init(fsi, io, substream);
+ ret = fsi_stream_transfer(io);
+ if (0 == ret)
+ fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
- fsi_port_stop(fsi, is_play);
- fsi_stream_pop(fsi, is_play);
+ fsi_stream_stop(fsi, io);
+ fsi_stream_quit(fsi, io);
break;
}
@@ -1036,8 +1323,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
- struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
u32 flags = fsi_get_info_flags(fsi);
int ret;
@@ -1151,13 +1437,9 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
- int samples_pos = io->buff_sample_pos - 1;
-
- if (samples_pos < 0)
- samples_pos = 0;
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
- return fsi_sample2frame(fsi, samples_pos);
+ return fsi_sample2frame(fsi, io->buff_sample_pos);
}
static struct snd_pcm_ops fsi_pcm_ops = {
@@ -1243,11 +1525,24 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/*
* platform function
*/
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+ fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */
+ fsi->playback.priv = fsi;
+ fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */
+ fsi->capture.priv = fsi;
+
+ if (fsi->info->tx_id) {
+ fsi->playback.slave.slave_id = fsi->info->tx_id;
+ fsi->playback.handler = &fsi_dma_push_handler;
+ }
+}
static int fsi_probe(struct platform_device *pdev)
{
struct fsi_master *master;
const struct platform_device_id *id_entry;
+ struct sh_fsi_platform_info *info = pdev->dev.platform_data;
struct resource *res;
unsigned int irq;
int ret;
@@ -1282,17 +1577,30 @@ static int fsi_probe(struct platform_device *pdev)
/* master setting */
master->irq = irq;
- master->info = pdev->dev.platform_data;
master->core = (struct fsi_core *)id_entry->driver_data;
spin_lock_init(&master->lock);
/* FSI A setting */
master->fsia.base = master->base;
master->fsia.master = master;
+ master->fsia.info = &info->port_a;
+ fsi_handler_init(&master->fsia);
+ ret = fsi_stream_probe(&master->fsia);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIA stream probe failed\n");
+ goto exit_iounmap;
+ }
/* FSI B setting */
master->fsib.base = master->base + 0x40;
master->fsib.master = master;
+ master->fsib.info = &info->port_b;
+ fsi_handler_init(&master->fsib);
+ ret = fsi_stream_probe(&master->fsib);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIB stream probe failed\n");
+ goto exit_fsia;
+ }
pm_runtime_enable(&pdev->dev);
dev_set_drvdata(&pdev->dev, master);
@@ -1301,7 +1609,7 @@ static int fsi_probe(struct platform_device *pdev)
id_entry->name, master);
if (ret) {
dev_err(&pdev->dev, "irq request err\n");
- goto exit_iounmap;
+ goto exit_fsib;
}
ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1323,6 +1631,10 @@ exit_snd_soc:
snd_soc_unregister_platform(&pdev->dev);
exit_free_irq:
free_irq(irq, master);
+exit_fsib:
+ fsi_stream_remove(&master->fsib);
+exit_fsia:
+ fsi_stream_remove(&master->fsia);
exit_iounmap:
iounmap(master->base);
pm_runtime_disable(&pdev->dev);
@@ -1345,6 +1657,9 @@ static int fsi_remove(struct platform_device *pdev)
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
snd_soc_unregister_platform(&pdev->dev);
+ fsi_stream_remove(&master->fsia);
+ fsi_stream_remove(&master->fsib);
+
iounmap(master->base);
kfree(master);
@@ -1352,30 +1667,29 @@ static int fsi_remove(struct platform_device *pdev)
}
static void __fsi_suspend(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_port_stop(fsi, is_play);
- fsi_hw_shutdown(fsi, is_play, dev);
+ fsi_stream_stop(fsi, io);
+ fsi_hw_shutdown(fsi, dev);
}
static void __fsi_resume(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_hw_startup(fsi, is_play, dev);
+ fsi_hw_startup(fsi, io, dev);
if (fsi_is_clk_master(fsi) && fsi->rate)
fsi_set_master_clk(dev, fsi, fsi->rate, 1);
- fsi_port_start(fsi, is_play);
-
+ fsi_stream_start(fsi, io);
}
static int fsi_suspend(struct device *dev)
@@ -1384,11 +1698,11 @@ static int fsi_suspend(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_suspend(fsia, 1, dev);
- __fsi_suspend(fsia, 0, dev);
+ __fsi_suspend(fsia, &fsia->playback, dev);
+ __fsi_suspend(fsia, &fsia->capture, dev);
- __fsi_suspend(fsib, 1, dev);
- __fsi_suspend(fsib, 0, dev);
+ __fsi_suspend(fsib, &fsib->playback, dev);
+ __fsi_suspend(fsib, &fsib->capture, dev);
return 0;
}
@@ -1399,32 +1713,18 @@ static int fsi_resume(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_resume(fsia, 1, dev);
- __fsi_resume(fsia, 0, dev);
+ __fsi_resume(fsia, &fsia->playback, dev);
+ __fsi_resume(fsia, &fsia->capture, dev);
- __fsi_resume(fsib, 1, dev);
- __fsi_resume(fsib, 0, dev);
+ __fsi_resume(fsib, &fsib->playback, dev);
+ __fsi_resume(fsib, &fsib->capture, dev);
return 0;
}
-static int fsi_runtime_nop(struct device *dev)
-{
- /* Runtime PM callback shared between ->runtime_suspend()
- * and ->runtime_resume(). Simply returns success.
- *
- * This driver re-initializes all registers after
- * pm_runtime_get_sync() anyway so there is no need
- * to save and restore registers here.
- */
- return 0;
-}
-
static struct dev_pm_ops fsi_pm_ops = {
.suspend = fsi_suspend,
.resume = fsi_resume,
- .runtime_suspend = fsi_runtime_nop,
- .runtime_resume = fsi_runtime_nop,
};
static struct fsi_core fsi1_core = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b5ecf6d23214..93a0daac5088 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -277,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root = debugfs_create_dir(codec->name,
debugfs_card_root);
if (!codec->debugfs_codec_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create codec debugfs directory\n");
+ dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
return;
}
@@ -291,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root,
codec, &codec_reg_fops);
if (!codec->debugfs_reg)
- printk(KERN_WARNING
- "ASoC: Failed to create codec register debugfs file\n");
+ dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
}
@@ -302,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
debugfs_remove_recursive(codec->debugfs_codec_root);
}
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+ struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+ platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+ debugfs_card_root);
+ if (!platform->debugfs_platform_root) {
+ dev_warn(platform->dev,
+ "Failed to create platform debugfs directory\n");
+ return;
+ }
+
+ snd_soc_dapm_debugfs_init(&platform->dapm,
+ platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+ debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -435,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
{
}
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
static inline void soc_init_card_debugfs(struct snd_soc_card *card)
{
}
@@ -546,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
}
/* suspend all CODECs */
@@ -567,6 +596,17 @@ int snd_soc_suspend(struct device *dev)
if (!codec->suspended && codec->driver->suspend) {
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY:
+ /*
+ * If the CODEC is capable of idle
+ * bias off then being in STANDBY
+ * means it's doing something,
+ * otherwise fall through.
+ */
+ if (codec->dapm.idle_bias_off) {
+ dev_dbg(codec->dev,
+ "idle_bias_off CODEC on over suspend\n");
+ break;
+ }
case SND_SOC_BIAS_OFF:
codec->driver->suspend(codec);
codec->suspended = 1;
@@ -649,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
}
/* unmute any active DACs */
@@ -893,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
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);
+ pr_err("asoc: failed to remove %s: %d\n",
+ codec_dai->name, err);
}
codec_dai->probed = 0;
list_del(&codec_dai->card_list);
@@ -905,12 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ platform->name, err);
}
/* Make sure all DAPM widgets are freed */
snd_soc_dapm_free(&platform->dapm);
+ soc_cleanup_platform_debugfs(platform);
platform->probed = 0;
list_del(&platform->card_list);
module_put(platform->dev->driver->owner);
@@ -927,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
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);
+ pr_err("asoc: failed to remove %s: %d\n",
+ cpu_dai->name, err);
}
cpu_dai->probed = 0;
list_del(&cpu_dai->card_list);
@@ -969,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
{
int ret = 0;
const struct snd_soc_codec_driver *driver = codec->driver;
+ struct snd_soc_dai *dai;
codec->card = card;
codec->dapm.card = card;
@@ -983,6 +1028,14 @@ static int soc_probe_codec(struct snd_soc_card *card,
snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
driver->num_dapm_widgets);
+ /* Create DAPM widgets for each DAI stream */
+ list_for_each_entry(dai, &dai_list, list) {
+ if (dai->dev != codec->dev)
+ continue;
+
+ snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+ }
+
codec->dapm.idle_bias_off = driver->idle_bias_off;
if (driver->probe) {
@@ -996,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
}
if (driver->controls)
- snd_soc_add_controls(codec, driver->controls,
+ snd_soc_add_codec_controls(codec, driver->controls,
driver->num_controls);
if (driver->dapm_routes)
snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -1028,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
+ soc_init_platform_debugfs(platform);
+
if (driver->dapm_widgets)
snd_soc_dapm_new_controls(&platform->dapm,
driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1057,6 +1112,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
return 0;
err_probe:
+ soc_cleanup_platform_debugfs(platform);
module_put(platform->dev->driver->owner);
return ret;
@@ -1172,8 +1228,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
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);
+ pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+ cpu_dai->name, ret);
module_put(cpu_dai->dev->driver->owner);
return ret;
}
@@ -1204,8 +1260,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
- codec_dai->name);
+ pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+ codec_dai->name, ret);
return ret;
}
}
@@ -1225,12 +1281,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
if (ret < 0)
- printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+ pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
/* 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);
+ pr_err("asoc: can't create pcm %s :%d\n",
+ dai_link->stream_name, ret);
return ret;
}
@@ -1263,7 +1320,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
ret = soc_ac97_dev_register(rtd->codec);
if (ret < 0) {
- printk(KERN_ERR "asoc: AC97 device register failed\n");
+ pr_err("asoc: AC97 device register failed:%d\n", ret);
return ret;
}
@@ -1403,8 +1460,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *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);
+ pr_err("asoc: can't create sound card for card %s: %d\n",
+ card->name, ret);
mutex_unlock(&card->mutex);
return;
}
@@ -1457,13 +1514,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
- /* We should have a non-codec control add function but we don't */
+ snd_soc_dapm_link_dai_widgets(card);
+
if (card->controls)
- snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
- struct snd_soc_codec,
- card_list),
- card->controls,
- card->num_controls);
+ snd_soc_add_card_controls(card, card->controls, card->num_controls);
if (card->dapm_routes)
snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
@@ -1477,14 +1531,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
if (dai_link->dai_fmt) {
ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
dai_link->dai_fmt);
- if (ret != 0)
+ if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].codec_dai->dev,
"Failed to set DAI format: %d\n",
ret);
ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
dai_link->dai_fmt);
- if (ret != 0)
+ if (ret != 0 && ret != -ENOTSUPP)
dev_warn(card->rtd[i].cpu_dai->dev,
"Failed to set DAI format: %d\n",
ret);
@@ -1527,7 +1581,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_register(card->snd_card);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+ pr_err("asoc: failed to register soundcard for %s: %d\n",
+ card->name, ret);
goto probe_aux_dev_err;
}
@@ -1536,7 +1591,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
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);
+ pr_err("asoc: failed to register AC97 %s: %d\n",
+ card->name, ret);
while (--i >= 0)
soc_unregister_ac97_dai_link(card->rtd[i].codec);
goto probe_aux_dev_err;
@@ -1589,6 +1645,10 @@ static int soc_probe(struct platform_device *pdev)
if (!card)
return -EINVAL;
+ dev_warn(&pdev->dev,
+ "ASoC machine %s should use snd_soc_register_card()\n",
+ card->name);
+
/* Bodge while we unpick instantiation */
card->dev = &pdev->dev;
@@ -1665,7 +1725,10 @@ EXPORT_SYMBOL_GPL(snd_soc_poweroff);
const struct dev_pm_ops snd_soc_pm_ops = {
.suspend = snd_soc_suspend,
.resume = snd_soc_resume,
+ .freeze = snd_soc_suspend,
+ .thaw = snd_soc_resume,
.poweroff = snd_soc_poweroff,
+ .restore = snd_soc_resume,
};
EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
@@ -1869,23 +1932,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
unsigned int mask, unsigned int value)
{
- int change;
+ bool change;
unsigned int old, new;
int ret;
- ret = snd_soc_read(codec, reg);
- if (ret < 0)
- return ret;
-
- old = ret;
- new = (old & ~mask) | (value & mask);
- change = old != new;
- if (change) {
- ret = snd_soc_write(codec, reg, new);
+ if (codec->using_regmap) {
+ ret = regmap_update_bits_check(codec->control_data, reg,
+ mask, value, &change);
+ } else {
+ ret = snd_soc_read(codec, reg);
if (ret < 0)
return ret;
+
+ old = ret;
+ new = (old & ~mask) | (value & mask);
+ change = old != new;
+ if (change)
+ ret = snd_soc_write(codec, reg, new);
}
+ if (ret < 0)
+ return ret;
+
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_update_bits);
@@ -1976,7 +2044,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
* Returns 0 for success, else error.
*/
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
- void *data, char *long_name,
+ void *data, const char *long_name,
const char *prefix)
{
struct snd_kcontrol_new template;
@@ -2011,9 +2079,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
}
EXPORT_SYMBOL_GPL(snd_soc_cnew);
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+ const struct snd_kcontrol_new *controls, int num_controls,
+ const char *prefix, void *data)
+{
+ 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, data,
+ control->name, prefix));
+ if (err < 0) {
+ dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
/**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
* duplicating this code.
*
* @codec: codec to add controls to
@@ -2022,31 +2109,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
*
* Return 0 for success, else error.
*/
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls)
{
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,
- control->name,
- codec->name_prefix));
- if (err < 0) {
- dev_err(codec->dev, "%s: Failed to add %s: %d\n",
- codec->name, control->name, err);
- return err;
- }
- }
- return 0;
+ return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+ codec->name_prefix, codec);
}
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
/**
* snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
*
* @platform: platform to add controls to
* @controls: array of controls to add
@@ -2058,23 +2133,53 @@ int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = platform->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, platform,
- control->name, NULL));
- if (err < 0) {
- dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
- return err;
- }
- }
- return 0;
+ return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+ NULL, platform);
}
EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = soc_card->snd_card;
+
+ return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+ NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = dai->card->snd_card;
+
+ return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+ NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
+/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
@@ -2640,6 +2745,115 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = params->num_regs * codec->val_bytes;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
+
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret;
+
+ if (codec->using_regmap)
+ ret = regmap_raw_read(codec->control_data, params->base,
+ ucontrol->value.bytes.data,
+ params->num_regs * codec->val_bytes);
+ else
+ ret = -EINVAL;
+
+ /* Hide any masked bytes to ensure consistent data reporting */
+ if (ret == 0 && params->mask) {
+ switch (codec->val_bytes) {
+ case 1:
+ ucontrol->value.bytes.data[0] &= ~params->mask;
+ break;
+ case 2:
+ ((u16 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ case 4:
+ ((u32 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
+
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret, len;
+ unsigned int val;
+ void *data;
+
+ if (!codec->using_regmap)
+ return -EINVAL;
+
+ data = ucontrol->value.bytes.data;
+ len = params->num_regs * codec->val_bytes;
+
+ /*
+ * If we've got a mask then we need to preserve the register
+ * bits. We shouldn't modify the incoming data so take a
+ * copy.
+ */
+ if (params->mask) {
+ ret = regmap_read(codec->control_data, params->base, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= params->mask;
+
+ data = kmemdup(data, len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ switch (codec->val_bytes) {
+ case 1:
+ ((u8 *)data)[0] &= ~params->mask;
+ ((u8 *)data)[0] |= val;
+ break;
+ case 2:
+ ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
+ ((u16 *)data)[0] |= cpu_to_be16(val);
+ break;
+ case 4:
+ ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
+ ((u32 *)data)[0] |= cpu_to_be32(val);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ ret = regmap_raw_write(codec->control_data, params->base,
+ data, len);
+
+ if (params->mask)
+ kfree(data);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
+
/**
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
* @dai: DAI
@@ -2757,10 +2971,11 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->driver && dai->driver->ops->set_fmt)
- return dai->driver->ops->set_fmt(dai, fmt);
- else
+ if (dai->driver == NULL)
return -EINVAL;
+ if (dai->driver->ops->set_fmt == NULL)
+ return -ENOTSUPP;
+ return dai->driver->ops->set_fmt(dai, fmt);
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
@@ -2864,7 +3079,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
*/
if (!!link->codec_name == !!link->codec_of_node) {
dev_err(card->dev,
- "Neither/both codec name/of_node are set\n");
+ "Neither/both codec name/of_node are set for %s\n",
+ link->name);
return -EINVAL;
}
@@ -2874,7 +3090,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
*/
if (link->platform_name && link->platform_of_node) {
dev_err(card->dev,
- "Both platform name/of_node are set\n");
+ "Both platform name/of_node are set for %s\n", link->name);
return -EINVAL;
}
@@ -2884,7 +3100,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
*/
if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) {
dev_err(card->dev,
- "Neither/both cpu_dai name/of_node are set\n");
+ "Neither/both cpu_dai name/of_node are set for %s\n",
+ link->name);
return -EINVAL;
}
}
@@ -2991,7 +3208,7 @@ 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",
+ pr_err("asoc: error - multiple DAI %s registered with no name\n",
dev_name(dev));
return NULL;
}
@@ -3166,6 +3383,7 @@ int snd_soc_register_platform(struct device *dev,
platform->dapm.dev = dev;
platform->dapm.platform = platform;
platform->dapm.stream_event = platform_drv->stream_event;
+ mutex_init(&platform->mutex);
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
@@ -3274,6 +3492,7 @@ int snd_soc_register_codec(struct device *dev,
codec->volatile_register = codec_drv->volatile_register;
codec->readable_register = codec_drv->readable_register;
codec->writable_register = codec_drv->writable_register;
+ codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
codec->dapm.dev = dev;
codec->dapm.codec = codec;
@@ -3462,8 +3681,7 @@ static int __init snd_soc_init(void)
#ifdef CONFIG_DEBUG_FS
snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create debugfs directory\n");
+ pr_warn("ASoC: Failed to create debugfs directory\n");
snd_soc_debugfs_root = NULL;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1f55ded4047f..6241490fff30 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -14,19 +14,13 @@
* dynamic configuration of codec internal audio paths and active
* DACs/ADCs.
* o Platform power domain - can support external components i.e. amps and
- * mic/meadphone insertion events.
+ * mic/headphone insertion events.
* o Automatic Mic Bias support
* o Jack insertion power event initiation - e.g. hp insertion will enable
* sinks, dacs, etc
- * o Delayed powerdown of audio susbsystem to reduce pops between a quick
+ * o Delayed power down of audio subsystem to reduce pops between a quick
* device reopen.
*
- * Todo:
- * o DAPM power change sequencing - allow for configurable per
- * codec sequences.
- * o Support for analogue bias optimisation.
- * o Support for reduced codec oversampling rates.
- * o Support for reduced codec bias currents.
*/
#include <linux/module.h>
@@ -40,6 +34,7 @@
#include <linux/jiffies.h>
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -55,7 +50,9 @@
static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
+ [snd_soc_dapm_regulator_supply] = 1,
[snd_soc_dapm_micbias] = 2,
+ [snd_soc_dapm_dai] = 3,
[snd_soc_dapm_aif_in] = 3,
[snd_soc_dapm_aif_out] = 3,
[snd_soc_dapm_mic] = 4,
@@ -90,6 +87,8 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_value_mux] = 9,
[snd_soc_dapm_aif_in] = 10,
[snd_soc_dapm_aif_out] = 10,
+ [snd_soc_dapm_dai] = 10,
+ [snd_soc_dapm_regulator_supply] = 11,
[snd_soc_dapm_supply] = 11,
[snd_soc_dapm_post] = 12,
};
@@ -172,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
return NULL;
}
+static void dapm_reset(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *w;
+
+ memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
+ list_for_each_entry(w, &card->widgets, list) {
+ w->power_checked = false;
+ w->inputs = -1;
+ w->outputs = -1;
+ }
+}
+
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
{
if (w->codec)
@@ -197,21 +209,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
unsigned short reg, unsigned int mask, unsigned int value)
{
- int change;
+ bool change;
unsigned int old, new;
int ret;
- ret = soc_widget_read(w, reg);
- if (ret < 0)
- return ret;
-
- old = ret;
- new = (old & ~mask) | (value & mask);
- change = old != new;
- if (change) {
- ret = soc_widget_write(w, reg, new);
+ if (w->codec && w->codec->using_regmap) {
+ ret = regmap_update_bits_check(w->codec->control_data,
+ reg, mask, value, &change);
+ if (ret != 0)
+ return ret;
+ } else {
+ ret = soc_widget_read(w, reg);
if (ret < 0)
return ret;
+
+ old = ret;
+ new = (old & ~mask) | (value & mask);
+ change = old != new;
+ if (change) {
+ ret = soc_widget_write(w, reg, new);
+ if (ret < 0)
+ return ret;
+ }
}
return change;
@@ -345,8 +364,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
case snd_soc_dapm_hp:
case snd_soc_dapm_mic:
case snd_soc_dapm_spk:
@@ -504,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
* for widgets so cut the prefix off
* the front of the widget name.
*/
- snprintf(path->long_name, name_len, "%s %s",
- w->name + prefix_len,
+ snprintf((char *)path->long_name, name_len,
+ "%s %s", w->name + prefix_len,
w->kcontrol_news[i].name);
break;
case snd_soc_dapm_mixer_named_ctl:
- snprintf(path->long_name, name_len, "%s",
- w->kcontrol_news[i].name);
+ snprintf((char *)path->long_name, name_len,
+ "%s", w->kcontrol_news[i].name);
break;
}
- path->long_name[name_len - 1] = '\0';
+ ((char *)path->long_name)[name_len - 1] = '\0';
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
wlist, path->long_name,
@@ -548,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
struct snd_soc_dapm_widget_list *wlist;
int shared, wlistentries;
size_t wlistsize;
- char *name;
+ const char *name;
if (w->num_kcontrols != 1) {
dev_err(dapm->dev,
@@ -673,12 +694,18 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
DAPM_UPDATE_STAT(widget, path_checks);
- if (widget->id == snd_soc_dapm_supply)
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
switch (widget->id) {
case snd_soc_dapm_adc:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
if (widget->active) {
widget->outputs = snd_soc_dapm_suspend_check(widget);
return widget->outputs;
@@ -738,13 +765,19 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
DAPM_UPDATE_STAT(widget, path_checks);
- if (widget->id == snd_soc_dapm_supply)
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
/* active stream ? */
switch (widget->id) {
case snd_soc_dapm_dac:
case snd_soc_dapm_aif_in:
+ case snd_soc_dapm_dai:
if (widget->active) {
widget->inputs = snd_soc_dapm_suspend_check(widget);
return widget->inputs;
@@ -821,6 +854,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(dapm_reg_event);
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ return regulator_enable(w->priv);
+ else
+ return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
if (w->power_checked)
@@ -851,6 +897,13 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
return out != 0 && in != 0;
}
+static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
+{
+ DAPM_UPDATE_STAT(w, power_checks);
+
+ return w->active;
+}
+
/* Check to see if an ADC has power */
static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
{
@@ -1251,7 +1304,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
if (d->dev)
- pm_runtime_put_sync(d->dev);
+ pm_runtime_put(d->dev);
}
/* If we just powered up then move to active bias */
@@ -1301,6 +1354,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
}
switch (w->id) {
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
/* Supplies can't affect their outputs, only their inputs */
break;
default:
@@ -1373,13 +1427,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
}
}
- memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
-
- list_for_each_entry(w, &card->widgets, list) {
- w->power_checked = false;
- w->inputs = -1;
- w->outputs = -1;
- }
+ dapm_reset(card);
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down. We
@@ -1400,10 +1448,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* Supplies and micbiases only bring the
* context up to STANDBY as unless something
* else is active and passing audio they
- * generally don't require full power.
+ * generally don't require full power. Signal
+ * generators are virtual pins and have no
+ * power impact themselves.
*/
switch (w->id) {
+ case snd_soc_dapm_siggen:
+ break;
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_micbias:
if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1475,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
&async_domain);
async_synchronize_full_domain(&async_domain);
+ /* do we need to notify any clients that DAPM event is complete */
+ list_for_each_entry(d, &card->dapm_list, list) {
+ if (d->stream_event)
+ d->stream_event(d, event);
+ }
+
pop_dbg(dapm->dev, card->pop_time,
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
pop_wait(card->pop_time);
@@ -1510,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
out = is_connected_output_ep(w);
dapm_clear_walk(w->dapm);
- ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d",
- w->name, w->power ? "On" : "Off", in, out);
+ ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
+ w->name, w->power ? "On" : "Off",
+ w->force ? " (forced)" : "", in, out);
if (w->reg >= 0)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
@@ -1607,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
if (!dapm->debugfs_dapm) {
- printk(KERN_WARNING
+ dev_warn(dapm->dev,
"Failed to create DAPM debugfs directory\n");
return;
}
@@ -1659,9 +1719,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
- struct snd_kcontrol *kcontrol, int change,
- int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
{
struct snd_soc_dapm_path *path;
int found = 0;
@@ -1671,9 +1730,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
widget->id != snd_soc_dapm_value_mux)
return -ENODEV;
- if (!change)
- return 0;
-
/* find dapm widget path assoc with kcontrol */
list_for_each_entry(path, &widget->dapm->card->paths, list) {
if (path->kcontrol != kcontrol)
@@ -1702,9 +1758,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
@@ -1733,6 +1790,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
@@ -1762,6 +1820,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -1869,10 +1928,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
return -EINVAL;
}
+ if (w->connected != status)
+ dapm_mark_dirty(w, "pin configuration");
+
w->connected = status;
if (status == 0)
w->force = 0;
- dapm_mark_dirty(w, "pin configuration");
return 0;
}
@@ -2000,8 +2061,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -2315,7 +2378,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mixer_update_power(widget, kcontrol, connect);
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
@@ -2406,7 +2469,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2467,8 +2530,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
widget->value = ucontrol->value.enumerated.item[0];
- dapm_mux_update_power(widget, kcontrol, change,
- widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
}
}
@@ -2571,7 +2633,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2611,15 +2673,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
ucontrol->value.integer.value[0] =
- snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+ snd_soc_dapm_get_pin_status(&card->dapm, pin);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
@@ -2634,41 +2696,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
if (ucontrol->value.integer.value[0])
- snd_soc_dapm_enable_pin(&codec->dapm, pin);
+ snd_soc_dapm_enable_pin(&card->dapm, pin);
else
- snd_soc_dapm_disable_pin(&codec->dapm, pin);
+ snd_soc_dapm_disable_pin(&card->dapm, pin);
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync(&card->dapm);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
-/**
- * snd_soc_dapm_new_control - create new dapm control
- * @dapm: DAPM context
- * @widget: widget template
- *
- * Creates a new dapm control based upon the template.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget)
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+ const struct snd_soc_dapm_widget *widget)
{
struct snd_soc_dapm_widget *w;
size_t name_len;
+ int ret;
if ((w = dapm_cnew_widget(widget)) == NULL)
- return -ENOMEM;
+ return NULL;
+
+ switch (w->id) {
+ case snd_soc_dapm_regulator_supply:
+ w->priv = devm_regulator_get(dapm->dev, w->name);
+ if (IS_ERR(w->priv)) {
+ ret = PTR_ERR(w->priv);
+ dev_err(dapm->dev, "Failed to request %s: %d\n",
+ w->name, ret);
+ return NULL;
+ }
+ break;
+ default:
+ break;
+ }
name_len = strlen(widget->name) + 1;
if (dapm->codec && dapm->codec->name_prefix)
@@ -2676,13 +2745,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->name = kmalloc(name_len, GFP_KERNEL);
if (w->name == NULL) {
kfree(w);
- return -ENOMEM;
+ return NULL;
}
if (dapm->codec && dapm->codec->name_prefix)
- snprintf(w->name, name_len, "%s %s",
+ snprintf((char *)w->name, name_len, "%s %s",
dapm->codec->name_prefix, widget->name);
else
- snprintf(w->name, name_len, "%s", widget->name);
+ snprintf((char *)w->name, name_len, "%s", widget->name);
switch (w->id) {
case snd_soc_dapm_switch:
@@ -2715,8 +2784,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->power_check = dapm_generic_check_power;
break;
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
w->power_check = dapm_supply_check_power;
break;
+ case snd_soc_dapm_dai:
+ w->power_check = dapm_dai_check_power;
+ break;
default:
w->power_check = dapm_always_on_check_power;
break;
@@ -2734,9 +2807,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
/* machine layer set ups unconnected pins and insertions */
w->connected = 1;
- return 0;
+ return w;
}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
/**
* snd_soc_dapm_new_controls - create new dapm controls
@@ -2752,15 +2824,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget,
int num)
{
- int i, ret;
+ struct snd_soc_dapm_widget *w;
+ int i;
for (i = 0; i < num; i++) {
- ret = snd_soc_dapm_new_control(dapm, widget);
- if (ret < 0) {
+ w = snd_soc_dapm_new_control(dapm, widget);
+ if (!w) {
dev_err(dapm->dev,
- "ASoC: Failed to create DAPM control %s: %d\n",
- widget->name, ret);
- return ret;
+ "ASoC: Failed to create DAPM control %s\n",
+ widget->name);
+ return -ENOMEM;
}
widget++;
}
@@ -2768,40 +2841,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
- const char *stream, int event)
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->card->widgets, list)
- {
- if (!w->sname || w->dapm != dapm)
+ WARN_ON(dapm->dev != dai->dev);
+
+ memset(&template, 0, sizeof(template));
+ template.reg = SND_SOC_NOPM;
+
+ if (dai->driver->playback.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->playback.stream_name;
+ template.sname = dai->driver->playback.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->playback.stream_name);
+ }
+
+ w->priv = dai;
+ dai->playback_widget = w;
+ }
+
+ if (dai->driver->capture.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->capture.stream_name;
+ template.sname = dai->driver->capture.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->capture.stream_name);
+ }
+
+ w->priv = dai;
+ dai->capture_widget = w;
+ }
+
+ return 0;
+}
+
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *dai_w, *w;
+ struct snd_soc_dai *dai;
+ struct snd_soc_dapm_route r;
+
+ memset(&r, 0, sizeof(r));
+
+ /* For each DAI widget... */
+ list_for_each_entry(dai_w, &card->widgets, list) {
+ if (dai_w->id != snd_soc_dapm_dai)
continue;
- dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
- w->name, w->sname, stream, event);
- if (strstr(w->sname, stream)) {
- dapm_mark_dirty(w, "stream event");
- switch(event) {
- case SND_SOC_DAPM_STREAM_START:
- w->active = 1;
- break;
- case SND_SOC_DAPM_STREAM_STOP:
- w->active = 0;
- break;
- case SND_SOC_DAPM_STREAM_SUSPEND:
- case SND_SOC_DAPM_STREAM_RESUME:
- case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
- case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
- break;
+
+ dai = dai_w->priv;
+
+ /* ...find all widgets with the same stream and link them */
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dai_w->dapm)
+ continue;
+
+ if (w->id == snd_soc_dapm_dai)
+ continue;
+
+ if (!w->sname)
+ continue;
+
+ if (dai->driver->playback.stream_name &&
+ strstr(w->sname,
+ dai->driver->playback.stream_name)) {
+ r.source = dai->playback_widget->name;
+ r.sink = w->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
+ }
+
+ if (dai->driver->capture.stream_name &&
+ strstr(w->sname,
+ dai->driver->capture.stream_name)) {
+ r.source = w->name;
+ r.sink = dai->capture_widget->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
}
}
}
- dapm_power_widgets(dapm, event);
+ return 0;
+}
- /* do we need to notify any clients that DAPM stream is complete */
- if (dapm->stream_event)
- dapm->stream_event(dapm, event);
+static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
+ int stream, struct snd_soc_dai *dai,
+ int event)
+{
+ struct snd_soc_dapm_widget *w;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ w = dai->playback_widget;
+ else
+ w = dai->capture_widget;
+
+ if (!w)
+ return;
+
+ dapm_mark_dirty(w, "stream event");
+
+ switch (event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+
+ dapm_power_widgets(dapm, event);
}
/**
@@ -2815,16 +2988,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
*
* Returns 0 for success else error.
*/
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ struct snd_soc_dai *dai, int event)
{
struct snd_soc_codec *codec = rtd->codec;
- if (stream == NULL)
- return 0;
-
mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
+ soc_dapm_stream_event(&codec->dapm, stream, dai, event);
mutex_unlock(&codec->mutex);
return 0;
}
@@ -3068,9 +3238,13 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
* standby.
*/
if (powerdown) {
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE);
+ if (dapm->bias_level == SND_SOC_BIAS_ON)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_PREPARE);
dapm_seq_run(dapm, &down_list, 0, false);
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY);
+ if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_STANDBY);
}
}
@@ -3083,7 +3257,9 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
list_for_each_entry(codec, &card->codec_dev_list, list) {
soc_dapm_shutdown_codec(&codec->dapm);
- snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ snd_soc_dapm_set_bias_level(&codec->dapm,
+ SND_SOC_BIAS_OFF);
}
}
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
new file mode 100644
index 000000000000..4420b7030c83
--- /dev/null
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2012, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Based on:
+ * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ *
+ * 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.
+ *
+ * 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/init.h>
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <sound/dmaengine_pcm.h>
+
+struct dmaengine_pcm_runtime_data {
+ struct dma_chan *dma_chan;
+
+ unsigned int pos;
+
+ void *data;
+};
+
+static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
+ const struct snd_pcm_substream *substream)
+{
+ return substream->runtime->private_data;
+}
+
+/**
+ * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
+ * @substream: PCM substream
+ * @data: Data to set
+ */
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->data = data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
+
+/**
+ * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
+ * @substream: PCM substream
+ *
+ * Returns the data previously set with snd_dmaengine_pcm_set_data
+ */
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->dma_chan;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
+
+/**
+ * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
+ * @substream: PCM substream
+ * @params: hw_params
+ * @slave_config: DMA slave config
+ *
+ * This function can be used to initialize a dma_slave_config from a substream
+ * and hw_params in a dmaengine based PCM driver implementation.
+ */
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+ const struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ enum dma_slave_buswidth buswidth;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->direction = DMA_MEM_TO_DEV;
+ slave_config->dst_addr_width = buswidth;
+ } else {
+ slave_config->direction = DMA_DEV_TO_MEM;
+ slave_config->src_addr_width = buswidth;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
+
+static void dmaengine_pcm_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct dma_chan *chan = prtd->dma_chan;
+ struct dma_async_tx_descriptor *desc;
+ enum dma_transfer_direction direction;
+
+ direction = snd_pcm_substream_to_dma_direction(substream);
+
+ prtd->pos = 0;
+ desc = chan->device->device_prep_dma_cyclic(chan,
+ substream->runtime->dma_addr,
+ snd_pcm_lib_buffer_bytes(substream),
+ snd_pcm_lib_period_bytes(substream), direction);
+
+ if (!desc)
+ return -ENOMEM;
+
+ desc->callback = dmaengine_pcm_dma_complete;
+ desc->callback_param = substream;
+ dmaengine_submit(desc);
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * @substream: PCM substream
+ * @cmd: Trigger command
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function can be used as the PCM trigger callback for dmaengine based PCM
+ * driver implementations.
+ */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = dmaengine_pcm_prepare_and_submit(substream);
+ if (ret)
+ return ret;
+ dma_async_issue_pending(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dmaengine_resume(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_pause(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dmaengine_terminate_all(prtd->dma_chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
+
+/**
+ * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
+ * @substream: PCM substream
+ *
+ * This function can be used as the PCM pointer callback for dmaengine based PCM
+ * driver implementations.
+ */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ return bytes_to_frames(substream->runtime, prtd->pos);
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
+
+static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_CYCLIC, mask);
+ prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
+
+ if (!prtd->dma_chan)
+ return -ENXIO;
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
+ * @substream: PCM substream
+ * @filter_fn: Filter function used to request the DMA channel
+ * @filter_data: Data passed to the DMA filter function
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will request a DMA channel using the passed filter function and
+ * data. The function should usually be called from the pcm open callback.
+ *
+ * Note that this function will use private_data field of the substream's
+ * runtime. So it is not availabe to your pcm driver implementation. If you need
+ * to keep additional data attached to a substream use
+ * snd_dmaeinge_pcm_{set,get}_data.
+ */
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ struct dmaengine_pcm_runtime_data *prtd;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ if (!prtd)
+ return -ENOMEM;
+
+ ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
+ if (ret < 0) {
+ kfree(prtd);
+ return ret;
+ }
+
+ substream->runtime->private_data = prtd;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
+
+/**
+ * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
+ * @substream: PCM substream
+ */
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ dma_release_channel(prtd->dma_chan);
+ kfree(prtd);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index c8610cbf34a5..4d8dc6a27d4d 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -114,6 +114,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
enum snd_soc_control_type control)
{
struct regmap_config config;
+ int ret;
memset(&config, 0, sizeof(config));
codec->write = hw_write;
@@ -140,6 +141,12 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
case SND_SOC_REGMAP:
/* Device has made its own regmap arrangements */
+ codec->using_regmap = true;
+
+ ret = regmap_get_val_bytes(codec->control_data);
+ /* Errors are legitimate for non-integer byte multiples */
+ if (ret > 0)
+ codec->val_bytes = ret;
break;
default:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index cdc860a5ff37..0ad8dcacd2f3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -63,6 +63,41 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
}
/*
+ * List of sample sizes that might go over the bus for parameter
+ * application. There ought to be a wildcard sample size for things
+ * like the DAC/ADC resolution to use but there isn't right now.
+ */
+static int sample_sizes[] = {
+ 24, 32,
+};
+
+static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int ret, i, bits;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ bits = dai->driver->playback.sig_bits;
+ else
+ bits = dai->driver->capture.sig_bits;
+
+ if (!bits)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
+ if (bits >= sample_sizes[i])
+ continue;
+
+ ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
+ sample_sizes[i], bits);
+ if (ret != 0)
+ dev_warn(dai->dev,
+ "Failed to set MSB %d/%d: %d\n",
+ bits, sample_sizes[i], ret);
+ }
+}
+
+/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
* startup for the cpu DAI, platform, machine and codec DAI.
@@ -88,8 +123,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
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);
+ dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
+ cpu_dai->name, ret);
goto out;
}
}
@@ -97,7 +132,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (platform->driver->ops && 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);
+ dev_err(platform->dev, "can't open platform %s: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
@@ -105,8 +141,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
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);
+ dev_err(codec_dai->dev, "can't open codec %s: %d\n",
+ codec_dai->name, ret);
goto codec_dai_err;
}
}
@@ -114,7 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *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", rtd->dai_link->name);
+ pr_err("asoc: %s startup failed: %d\n",
+ rtd->dai_link->name, ret);
goto machine_err;
}
}
@@ -187,6 +224,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto config_err;
}
+ soc_pcm_apply_msb(substream, codec_dai);
+ soc_pcm_apply_msb(substream, cpu_dai);
+
/* Symmetry only applies if we've already got an active stream. */
if (cpu_dai->active) {
ret = soc_pcm_apply_symmetry(substream, cpu_dai);
@@ -267,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
/* 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);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -329,12 +368,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
cpu_dai->runtime = NULL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (codec->ignore_pmdown_time ||
+ if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
rtd->dai_link->ignore_pmdown_time) {
/* powered down playback stream now */
snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_STOP);
} else {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
@@ -343,9 +383,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
}
} else {
/* capture streams can be powered down now */
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -375,7 +414,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *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");
+ pr_err("asoc: machine prepare error: %d\n", ret);
goto out;
}
}
@@ -383,7 +422,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->prepare) {
ret = platform->driver->ops->prepare(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: platform prepare error\n");
+ dev_err(platform->dev, "platform prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -391,7 +431,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
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");
+ dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -399,7 +440,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
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");
+ dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -411,14 +453,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
cancel_delayed_work(&rtd->delayed_work);
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
+ SND_SOC_DAPM_STREAM_START);
snd_soc_dai_digital_mute(codec_dai, 0);
@@ -446,7 +482,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
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");
+ pr_err("asoc: machine hw_params failed: %d\n", ret);
goto out;
}
}
@@ -454,8 +490,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
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);
+ dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
+ codec_dai->name, ret);
goto codec_err;
}
}
@@ -463,8 +499,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
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);
+ dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+ cpu_dai->name, ret);
goto interface_err;
}
}
@@ -472,8 +508,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (platform->driver->ops && 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);
+ dev_err(platform->dev, "%s hw params failed: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 4220bb0f2730..60053709e417 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -89,14 +89,32 @@ static struct snd_soc_platform_driver dummy_platform = {
.ops = &dummy_dma_ops,
};
+static struct snd_soc_codec_driver dummy_codec;
+static struct snd_soc_dai_driver dummy_dai = {
+ .name = "snd-soc-dummy-dai",
+};
+
static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
{
- return snd_soc_register_platform(&pdev->dev, &dummy_platform);
+ int ret;
+
+ ret = snd_soc_register_codec(&pdev->dev, &dummy_codec, &dummy_dai, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_register_platform(&pdev->dev, &dummy_platform);
+ if (ret < 0) {
+ snd_soc_unregister_codec(&pdev->dev);
+ return ret;
+ }
+
+ return ret;
}
static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 4a0e805c4edd..e45ccd851f6a 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -34,8 +35,13 @@
#define DRV_NAME "tegra-alc5632"
+#define GPIO_HP_DET BIT(0)
+
struct tegra_alc5632 {
struct tegra_asoc_utils_data util_data;
+ struct platform_device *pcm_dev;
+ int gpio_requested;
+ int gpio_hp_det;
};
static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
@@ -85,24 +91,18 @@ static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
},
};
+static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
+ .name = "Headset detection",
+ .report = SND_JACK_HEADSET,
+ .debounce_time = 150,
+ .invert = 1,
+};
+
static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Int Spk", NULL),
SND_SOC_DAPM_HP("Headset Stereophone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route tegra_alc5632_audio_map[] = {
- /* Internal Speaker */
- {"Int Spk", NULL, "SPKOUT"},
- {"Int Spk", NULL, "SPKOUTN"},
-
- /* Headset Mic */
- {"MIC1", NULL, "MICBIAS1"},
- {"MICBIAS1", NULL, "Headset Mic"},
-
- /* Headset Stereophone */
- {"Headset Stereophone", NULL, "HPR"},
- {"Headset Stereophone", NULL, "HPL"},
+ SND_SOC_DAPM_MIC("Digital Mic", NULL),
};
static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
@@ -113,6 +113,8 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct device_node *np = codec->card->dev->of_node;
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
&tegra_alc5632_hs_jack);
@@ -120,6 +122,16 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
tegra_alc5632_hs_jack_pins);
+ machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+
+ if (gpio_is_valid(machine->gpio_hp_det)) {
+ tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
+ snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested |= GPIO_HP_DET;
+ }
+
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
return 0;
@@ -128,9 +140,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link tegra_alc5632_dai = {
.name = "ALC5632",
.stream_name = "ALC5632 PCM",
- .codec_name = "alc5632.0-001e",
.platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra-i2s.0",
.codec_dai_name = "alc5632-hifi",
.init = tegra_alc5632_asoc_init,
.ops = &tegra_alc5632_asoc_ops,
@@ -148,8 +158,6 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
.num_controls = ARRAY_SIZE(tegra_alc5632_controls),
.dapm_widgets = tegra_alc5632_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
- .dapm_routes = tegra_alc5632_audio_map,
- .num_dapm_routes = ARRAY_SIZE(tegra_alc5632_audio_map),
.fully_routed = true,
};
@@ -163,45 +171,111 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
sizeof(struct tegra_alc5632), GFP_KERNEL);
if (!alc5632) {
dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err;
}
- ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
- if (ret)
- return ret;
-
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, alc5632);
+ alc5632->pcm_dev = ERR_PTR(-EINVAL);
+
+ if (!(pdev->dev.of_node)) {
+ dev_err(&pdev->dev, "Must be instantiated using device tree\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto err;
+
+ tegra_alc5632_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+
+ if (!tegra_alc5632_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!tegra_alc5632_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ alc5632->pcm_dev = platform_device_register_simple(
+ "tegra-pcm-audio", -1, NULL, 0);
+ if (IS_ERR(alc5632->pcm_dev)) {
+ dev_err(&pdev->dev,
+ "Can't instantiate tegra-pcm-audio\n");
+ ret = PTR_ERR(alc5632->pcm_dev);
+ goto err;
+ }
+
+ ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
+ if (ret)
+ goto err_unregister;
+
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- tegra_asoc_utils_fini(&alc5632->util_data);
- return ret;
+ goto err_fini_utils;
}
return 0;
+
+err_fini_utils:
+ tegra_asoc_utils_fini(&alc5632->util_data);
+err_unregister:
+ if (!IS_ERR(alc5632->pcm_dev))
+ platform_device_unregister(alc5632->pcm_dev);
+err:
+ return ret;
}
static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+
+ if (machine->gpio_requested & GPIO_HP_DET)
+ snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested = 0;
snd_soc_unregister_card(card);
- tegra_asoc_utils_fini(&alc5632->util_data);
+ tegra_asoc_utils_fini(&machine->util_data);
+ if (!IS_ERR(machine->pcm_dev))
+ platform_device_unregister(machine->pcm_dev);
return 0;
}
+static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-alc5632", },
+ {},
+};
+
static struct platform_driver tegra_alc5632_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_alc5632_of_match,
},
.probe = tegra_alc5632_probe,
.remove = __devexit_p(tegra_alc5632_remove),
@@ -212,3 +286,4 @@ MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c22431516ab2..8b4457137c7c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -336,7 +336,7 @@ static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &tegra_dma_mask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 4dd051bdf4fd..c6500d00053b 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -1112,17 +1112,7 @@ static struct spi_driver at73c213_driver = {
.remove = __devexit_p(snd_at73c213_remove),
};
-static int __init at73c213_init(void)
-{
- return spi_register_driver(&at73c213_driver);
-}
-module_init(at73c213_init);
-
-static void __exit at73c213_exit(void)
-{
- spi_unregister_driver(&at73c213_driver);
-}
-module_exit(at73c213_exit);
+module_spi_driver(at73c213_driver);
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC");
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 8af92e3e9c18..fc8cc823e438 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
@@ -29,7 +28,7 @@
#include <sound/initval.h>
MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
-MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
+MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h
index d11e5cb520f0..bde02d105a51 100644
--- a/sound/usb/6fire/chip.h
+++ b/sound/usb/6fire/chip.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index c994daa57af2..6c3d531a250e 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
index edc5dc84b888..d2af0a5ddcf3 100644
--- a/sound/usb/6fire/comm.h
+++ b/sound/usb/6fire/comm.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h
index 7dbeb4a37831..b6eb03ed1c2c 100644
--- a/sound/usb/6fire/common.h
+++ b/sound/usb/6fire/common.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index ac828eff1a63..07ed914d5e71 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -5,9 +5,12 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
+ * Thanks to:
+ * - Holger Ruckdeschel: he found out how to control individual channel
+ * volumes and introduced mute switch
+ *
* 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
@@ -16,6 +19,7 @@
#include <linux/interrupt.h>
#include <sound/control.h>
+#include <sound/tlv.h>
#include "control.h"
#include "comm.h"
@@ -25,26 +29,6 @@ static char *opt_coax_texts[2] = { "Optical", "Coax" };
static char *line_phono_texts[2] = { "Line", "Phono" };
/*
- * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
- * this is done because the linear values cause rapid degredation
- * of volume in the uppermost region.
- */
-static const u8 log_volume_table[128] = {
- 0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
- 0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
- 0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
- 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
- 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
- 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
- 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
- 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
- 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
- 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
- 0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
- 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
- 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
-
-/*
* data that needs to be sent to device. sets up card internal stuff.
* values dumped from windows driver and filtered by trial'n'error.
*/
@@ -59,7 +43,7 @@ init_data[] = {
{ 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
{ 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
{ 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
- { 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
+ { 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
{ 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
{ 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
{ 0 } /* TERMINATING ENTRY */
@@ -70,20 +54,47 @@ static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
+static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0);
+static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500);
+
enum {
DIGITAL_THRU_ONLY_SAMPLERATE = 3
};
-static void usb6fire_control_master_vol_update(struct control_runtime *rt)
+static void usb6fire_control_output_vol_update(struct control_runtime *rt)
{
struct comm_runtime *comm_rt = rt->chip->comm;
- if (comm_rt) {
- /* set volume */
- comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
- log_volume_table[rt->master_vol]);
- /* unmute */
- comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
- }
+ int i;
+
+ if (comm_rt)
+ for (i = 0; i < 6; i++)
+ if (!(rt->ovol_updated & (1 << i))) {
+ comm_rt->write8(comm_rt, 0x12, 0x0f + i,
+ 180 - rt->output_vol[i]);
+ rt->ovol_updated |= 1 << i;
+ }
+}
+
+static void usb6fire_control_output_mute_update(struct control_runtime *rt)
+{
+ struct comm_runtime *comm_rt = rt->chip->comm;
+
+ if (comm_rt)
+ comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute);
+}
+
+static void usb6fire_control_input_vol_update(struct control_runtime *rt)
+{
+ struct comm_runtime *comm_rt = rt->chip->comm;
+ int i;
+
+ if (comm_rt)
+ for (i = 0; i < 2; i++)
+ if (!(rt->ivol_updated & (1 << i))) {
+ comm_rt->write8(comm_rt, 0x12, 0x1c + i,
+ rt->input_vol[i] & 0x3f);
+ rt->ivol_updated |= 1 << i;
+ }
}
static void usb6fire_control_line_phono_update(struct control_runtime *rt)
@@ -165,34 +176,147 @@ static int usb6fire_control_streaming_update(struct control_runtime *rt)
return -EINVAL;
}
-static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
+ uinfo->count = 2;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 127;
+ uinfo->value.integer.max = 180;
return 0;
}
-static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
int changed = 0;
- if (rt->master_vol != ucontrol->value.integer.value[0]) {
- rt->master_vol = ucontrol->value.integer.value[0];
- usb6fire_control_master_vol_update(rt);
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) {
+ rt->output_vol[ch] = ucontrol->value.integer.value[0];
+ rt->ovol_updated &= ~(1 << ch);
changed = 1;
}
+ if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) {
+ rt->output_vol[ch + 1] = ucontrol->value.integer.value[1];
+ rt->ovol_updated &= ~(2 << ch);
+ changed = 1;
+ }
+
+ if (changed)
+ usb6fire_control_output_vol_update(rt);
+
return changed;
}
-static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = rt->master_vol;
+ unsigned int ch = kcontrol->private_value;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = rt->output_vol[ch];
+ ucontrol->value.integer.value[1] = rt->output_vol[ch + 1];
+ return 0;
+}
+
+static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
+ u8 old = rt->output_mute;
+ u8 value = 0;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ rt->output_mute &= ~(3 << ch);
+ if (ucontrol->value.integer.value[0])
+ value |= 1;
+ if (ucontrol->value.integer.value[1])
+ value |= 2;
+ rt->output_mute |= value << ch;
+
+ if (rt->output_mute != old)
+ usb6fire_control_output_mute_update(rt);
+
+ return rt->output_mute != old;
+}
+
+static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
+ u8 value = rt->output_mute >> ch;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = 1 & value;
+ value >>= 1;
+ ucontrol->value.integer.value[1] = 1 & value;
+
+ return 0;
+}
+
+static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 30;
+ return 0;
+}
+
+static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+
+ if (rt->input_vol[0] != ucontrol->value.integer.value[0]) {
+ rt->input_vol[0] = ucontrol->value.integer.value[0] - 15;
+ rt->ivol_updated &= ~(1 << 0);
+ changed = 1;
+ }
+ if (rt->input_vol[1] != ucontrol->value.integer.value[1]) {
+ rt->input_vol[1] = ucontrol->value.integer.value[1] - 15;
+ rt->ivol_updated &= ~(1 << 1);
+ changed = 1;
+ }
+
+ if (changed)
+ usb6fire_control_input_vol_update(rt);
+
+ return changed;
+}
+
+static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = rt->input_vol[0] + 15;
+ ucontrol->value.integer.value[1] = rt->input_vol[1] + 15;
+
return 0;
}
@@ -287,18 +411,83 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct __devinitdata snd_kcontrol_new elements[] = {
+static struct __devinitdata snd_kcontrol_new vol_elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
+ .name = "Analog Playback Volume",
.index = 0,
+ .private_value = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Volume",
+ .index = 1,
+ .private_value = 2,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Volume",
+ .index = 2,
+ .private_value = 4,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {}
+};
+
+static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 0,
+ .private_value = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 1,
+ .private_value = 2,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = usb6fire_control_master_vol_info,
- .get = usb6fire_control_master_vol_get,
- .put = usb6fire_control_master_vol_put
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 2,
+ .private_value = 4,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
+ },
+ {}
+};
+
+static struct __devinitdata snd_kcontrol_new elements[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line/Phono Capture Route",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -324,9 +513,54 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
.get = usb6fire_control_digital_thru_get,
.put = usb6fire_control_digital_thru_put
},
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Capture Volume",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_input_vol_info,
+ .get = usb6fire_control_input_vol_get,
+ .put = usb6fire_control_input_vol_put,
+ .tlv = { .p = tlv_input }
+ },
{}
};
+static int usb6fire_control_add_virtual(
+ struct control_runtime *rt,
+ struct snd_card *card,
+ char *name,
+ struct snd_kcontrol_new *elems)
+{
+ int ret;
+ int i;
+ struct snd_kcontrol *vmaster =
+ snd_ctl_make_virtual_master(name, tlv_output);
+ struct snd_kcontrol *control;
+
+ if (!vmaster)
+ return -ENOMEM;
+ ret = snd_ctl_add(card, vmaster);
+ if (ret < 0)
+ return ret;
+
+ i = 0;
+ while (elems[i].name) {
+ control = snd_ctl_new1(&elems[i], rt);
+ if (!control)
+ return -ENOMEM;
+ ret = snd_ctl_add(card, control);
+ if (ret < 0)
+ return ret;
+ ret = snd_ctl_add_slave(vmaster, control);
+ if (ret < 0)
+ return ret;
+ i++;
+ }
+ return 0;
+}
+
int __devinit usb6fire_control_init(struct sfire_chip *chip)
{
int i;
@@ -352,9 +586,26 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
usb6fire_control_opt_coax_update(rt);
usb6fire_control_line_phono_update(rt);
- usb6fire_control_master_vol_update(rt);
+ usb6fire_control_output_vol_update(rt);
+ usb6fire_control_output_mute_update(rt);
+ usb6fire_control_input_vol_update(rt);
usb6fire_control_streaming_update(rt);
+ ret = usb6fire_control_add_virtual(rt, chip->card,
+ "Master Playback Volume", vol_elements);
+ if (ret) {
+ snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ kfree(rt);
+ return ret;
+ }
+ ret = usb6fire_control_add_virtual(rt, chip->card,
+ "Master Playback Switch", mute_elements);
+ if (ret) {
+ snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ kfree(rt);
+ return ret;
+ }
+
i = 0;
while (elements[i].name) {
ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
index 8f5aeead2e3d..9a596d95474a 100644
--- a/sound/usb/6fire/control.h
+++ b/sound/usb/6fire/control.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +43,11 @@ struct control_runtime {
bool line_phono_switch;
bool digital_thru_switch;
bool usb_streaming;
- u8 master_vol;
+ u8 output_vol[6];
+ u8 ovol_updated;
+ u8 output_mute;
+ s8 input_vol[2];
+ u8 ivol_updated;
};
int __devinit usb6fire_control_init(struct sfire_chip *chip);
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 3b5f517a3972..6f9715ab32fe 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index 13f4509dce2b..f0e5179b242b 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
index 97a7bf669135..5114eccc1d8e 100644
--- a/sound/usb/6fire/midi.h
+++ b/sound/usb/6fire/midi.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index d144cdb2f159..c97d05f0e966 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
index 2bee81374002..3104301b257d 100644
--- a/sound/usb/6fire/pcm.h
+++ b/sound/usb/6fire/pcm.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 3efc21c3d67c..ff77b28f3da1 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -106,6 +106,7 @@ config SND_USB_6FIRE
select BITREVERSE
select SND_RAWMIDI
select SND_PCM
+ select SND_VMASTER
help
Say Y here to include support for TerraTec 6fire DMX USB interface.
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 2cf87f5afed4..fde9a7a29cb6 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -311,8 +311,10 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
spin_lock(&dev->spinlock);
- if (dev->input_panic || dev->output_panic)
+ if (dev->input_panic || dev->output_panic) {
ptr = SNDRV_PCM_POS_XRUN;
+ goto unlock;
+ }
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
ptr = bytes_to_frames(sub->runtime,
@@ -321,6 +323,7 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
ptr = bytes_to_frames(sub->runtime,
dev->audio_in_buf_pos[index]);
+unlock:
spin_unlock(&dev->spinlock);
return ptr;
}
diff --git a/sound/usb/card.h b/sound/usb/card.h
index a39edcc32a93..da5fa1ac4eda 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -1,6 +1,7 @@
#ifndef __USBAUDIO_CARD_H
#define __USBAUDIO_CARD_H
+#define MAX_NR_RATES 1024
#define MAX_PACKS 20
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 8
diff --git a/sound/usb/format.c b/sound/usb/format.c
index e09aba19375c..ddfef57c4c9f 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -209,8 +209,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
return 0;
}
-#define MAX_UAC2_NR_RATES 1024
-
/*
* Helper function to walk the array of sample rate triplets reported by
* the device. The problem is that we need to parse whole array first to
@@ -255,7 +253,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
fp->rates |= snd_pcm_rate_to_rate_bit(rate);
nr_rates++;
- if (nr_rates >= MAX_UAC2_NR_RATES) {
+ if (nr_rates >= MAX_NR_RATES) {
snd_printk(KERN_ERR "invalid uac2 rates\n");
break;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0220b0f335b9..0eed6115c2d4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -695,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs)
{
struct audioformat *fp;
+ int *rate_list;
int count = 0, needs_knot = 0;
int err;
@@ -708,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
if (!needs_knot)
return 0;
- subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
+ subs->rate_list.list = rate_list =
+ kmalloc(sizeof(int) * count, GFP_KERNEL);
if (!subs->rate_list.list)
return -ENOMEM;
subs->rate_list.count = count;
@@ -717,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
list_for_each_entry(fp, &subs->fmt_list, list) {
int i;
for (i = 0; i < fp->nr_rates; i++)
- subs->rate_list.list[count++] = fp->rate_table[i];
+ rate_list[count++] = fp->rate_table[i];
}
err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&subs->rate_list);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 8edc5035fc8f..d89ab4c7d44b 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -1618,6 +1618,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /* Edirol UM-3G */
+ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .ifnum = 0,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ }
+},
+{
/* Boss JS-8 Jam Station */
USB_DEVICE(0x0582, 0x0109),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index a3ddac0deffd..27817266867a 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -132,10 +132,14 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
unsigned *rate_table = NULL;
fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
- if (! fp) {
+ if (!fp) {
snd_printk(KERN_ERR "cannot memdup\n");
return -ENOMEM;
}
+ if (fp->nr_rates > MAX_NR_RATES) {
+ kfree(fp);
+ return -EINVAL;
+ }
if (fp->nr_rates > 0) {
rate_table = kmemdup(fp->rate_table,
sizeof(int) * fp->nr_rates, GFP_KERNEL);
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 6ffb3713b60c..520ef96d7c75 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -80,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs)
cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
snd_printk(KERN_ERR "active frame status %i. "
- "Most propably some hardware problem.\n",
+ "Most probably some hardware problem.\n",
urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status;
}
@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
{
snd_printk(KERN_ERR
"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-"Most propably some urb of usb-frame %i is still missing.\n"
+"Most probably some urb of usb-frame %i is still missing.\n"
"Cause could be too long delays in usb-hcd interrupt handling.\n",
usb_get_current_frame_number(usX2Y->dev),
subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index a51340f6f2db..8e40b6e67e9e 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
}
for (i = 0; i < nr_of_packs(); i++) {
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
- snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status);
+ snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status;
}
lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride;
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ac86d67b636e..7c12650165ae 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -104,7 +104,7 @@ endif
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm
-ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip
@@ -168,10 +168,7 @@ endif
### --- END CONFIGURATION SECTION ---
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
# Guard against environment variables
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index a57b66e853c2..185a96d66dd1 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,2 +1,8 @@
#include "../../../arch/x86/lib/memcpy_64.S"
+/*
+ * We need to provide note.GNU-stack section, saying that we want
+ * NOT executable stack. Otherwise the final linking will assume that
+ * the ELF stack should not be restricted at all and set it RWX.
+ */
+.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 59d43abfbfec..fb8566181f27 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -20,7 +20,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
-#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -31,7 +30,6 @@
#include <stdlib.h>
#include <string.h>
-#undef _GNU_SOURCE
#include "perf.h"
#include "builtin.h"
#include "util/util.h"
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8f80df896038..dd162aa24baa 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws)
static void perf_top__update_print_entries(struct perf_top *top)
{
- top->print_entries = top->winsize.ws_row;
-
if (top->print_entries > 9)
top->print_entries -= 9;
}
@@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar
struct perf_top *top = arg;
get_term_dimensions(&top->winsize);
+ if (!top->print_entries
+ || (top->print_entries+4) > top->winsize.ws_row) {
+ top->print_entries = top->winsize.ws_row;
+ } else {
+ top->print_entries += 4;
+ top->winsize.ws_row = top->print_entries;
+ }
perf_top__update_print_entries(top);
}
@@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
};
perf_top__sig_winch(SIGWINCH, NULL, top);
sigaction(SIGWINCH, &act, NULL);
- } else
+ } else {
+ perf_top__sig_winch(SIGWINCH, NULL, top);
signal(SIGWINCH, SIG_DFL);
+ }
break;
case 'E':
if (top->evlist->nr_entries > 1) {
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 73ddaf06b8e7..2044324b755a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -554,7 +554,7 @@ static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
is_kernel_mmap = memcmp(event->mmap.filename,
kmmap_prefix,
- strlen(kmmap_prefix)) == 0;
+ strlen(kmmap_prefix) - 1) == 0;
if (event->mmap.filename[0] == '/' ||
(!is_kernel_mmap && event->mmap.filename[0] == '[')) {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 667f3b78bb2c..7132ee834e0e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -463,6 +463,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
memset(data, 0, sizeof(*data));
data->cpu = data->pid = data->tid = -1;
data->stream_id = data->id = data->time = -1ULL;
+ data->period = 1;
if (event->header.type != PERF_RECORD_SAMPLE) {
if (!sample_id_all)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e7e0b09c12c..ecd7f4dd7eea 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
- size = strlen(name);
+ size = strlen(ev.event_type.event_type.name);
size = ALIGN(size, sizeof(u64));
ev.event_type.header.size = sizeof(ev.event_type) -
(sizeof(ev.event_type.event_type.name) - size);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900e2211..29cb65459811 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,7 +19,6 @@
*
*/
-#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -33,7 +32,6 @@
#include <limits.h>
#include <elf.h>
-#undef _GNU_SOURCE
#include "util.h"
#include "event.h"
#include "string.h"
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 215d50f2042e..0975438c3e72 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc9ee95..1a8d4dc4f386 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,14 +21,13 @@
* The parts for function graph printing was taken and modified from the
* Linux Kernel that were written by Frederic Weisbecker.
*/
-#define _GNU_SOURCE
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
-#undef _GNU_SOURCE
#include "../perf.h"
#include "util.h"
#include "trace-event.h"
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 1212a386a033..e81aef1f2569 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1,6 +1,4 @@
-#define _GNU_SOURCE
#include <stdio.h>
-#undef _GNU_SOURCE
#include "../libslang.h"
#include <stdlib.h>
#include <string.h>
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 6ef3c5691762..4f48f5901b30 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b9c530cce79a..ecf9898169c8 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -40,7 +40,6 @@
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#define HAS_BOOL
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7287bf5d1c9e..a91f980077d8 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
if (memslot && memslot->dirty_bitmap) {
unsigned long rel_gfn = gfn - memslot->base_gfn;
- if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
+ if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))
memslot->nr_dirty_pages++;
}
}