]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux...
authorDave Airlie <airlied@redhat.com>
Tue, 28 Jan 2014 23:37:47 +0000 (09:37 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 28 Jan 2014 23:37:47 +0000 (09:37 +1000)
omapdrm patches for 3.14

* tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  drm/omap: Enable DT support for DMM
  drm/omap: fix: change dev_unload order
  drm/omap: fix: disable encoder before destroying it
  drm/omap: fix: disconnect devices when omapdrm module is removed
  drm/omap: fix: Defer probe if an omapdss device requests for it at connect
  drm/omap: fix (un)registering irqs inside an irq handler

Conflicts:
drivers/gpu/drm/omapdrm/omap_drv.c

835 files changed:
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt
Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt
Documentation/devicetree/bindings/dma/tegra20-apbdma.txt
Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.txt
Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt
Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mipi/nvidia,tegra114-mipi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
Documentation/devicetree/bindings/nvec/nvidia,nvec.txt
Documentation/devicetree/bindings/panel/auo,b101aw03.txt [new file with mode: 0644]
Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt [new file with mode: 0644]
Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt [new file with mode: 0644]
Documentation/devicetree/bindings/panel/simple-panel.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.txt
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt
Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt
Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt
Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt
Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra20-paz00.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/io.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/xen/page.h
arch/arm/kernel/traps.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/powergate.c
arch/arm/mm/flush.c
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/page.h
arch/parisc/kernel/cache.c
arch/powerpc/boot/dts/mpc5125twr.dts
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/unaligned.h
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/pci.h
arch/s390/Kconfig
arch/s390/include/asm/smp.h
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/pci/pci_event.c
arch/sh/kernel/sh_ksyms_32.c
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/kgdb_64.c
arch/sparc/kernel/smp_64.c
arch/x86/include/asm/fpu-internal.h
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kvm/lapic.c
arch/x86/kvm/vmx.c
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/ata/ahci.c
drivers/ata/sata_sis.c
drivers/block/null_blk.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/Makefile
drivers/char/agp/Kconfig
drivers/char/agp/Makefile
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-gtt.c
drivers/char/tpm/tpm_ppi.c
drivers/clk/clk-divider.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/tegra/Makefile
drivers/clk/tegra/clk-id.h [new file with mode: 0644]
drivers/clk/tegra/clk-periph-gate.c
drivers/clk/tegra/clk-periph.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-audio.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra-fixed.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra-periph.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra-pmc.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra-super-gen4.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-calxeda.c
drivers/crypto/ixp4xx_crypto.c
drivers/dma/dmaengine.c
drivers/dma/ioat/dma.c
drivers/dma/mmp_pdma.c
drivers/dma/of-dma.c
drivers/dma/tegra20-apb-dma.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/bochs/Kconfig [new file with mode: 0644]
drivers/gpu/drm/bochs/Makefile [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs.h [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_drv.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_fbdev.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_hw.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_kms.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_mm.c [new file with mode: 0644]
drivers/gpu/drm/cirrus/cirrus_drv.h
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/cirrus/cirrus_main.c
drivers/gpu/drm/cirrus/cirrus_mode.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_agpsupport.c
drivers/gpu/drm/drm_buffer.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_edid_load.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_memory.c
drivers/gpu/drm/drm_mipi_dsi.c [new file with mode: 0644]
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_panel.c [new file with mode: 0644]
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/drm_usb.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/accel_2d.c
drivers/gpu/drm/gma500/cdv_intel_dp.c
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_intel_drv.h
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/gma500/psb_irq.h
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/dvo_ns2501.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_ums.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_pll.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/i915/intel_sideband.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/mga/mga_dma.c
drivers/gpu/drm/mga/mga_drv.h
drivers/gpu/drm/mga/mga_ioc32.c
drivers/gpu/drm/mga/mga_irq.c
drivers/gpu/drm/mga/mga_state.c
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/msm/Kconfig
drivers/gpu/drm/msm/Makefile
drivers/gpu/drm/msm/NOTES
drivers/gpu/drm/msm/adreno/a2xx.xml.h
drivers/gpu/drm/msm/adreno/a3xx.xml.h
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
drivers/gpu/drm/msm/adreno/a3xx_gpu.h
drivers/gpu/drm/msm/adreno/adreno_common.xml.h
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.h
drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
drivers/gpu/drm/msm/dsi/dsi.xml.h
drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
drivers/gpu/drm/msm/dsi/sfpb.xml.h
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi.xml.h
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c [new file with mode: 0644]
drivers/gpu/drm/msm/hdmi/qfprom.xml.h
drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h [moved from drivers/gpu/drm/msm/mdp4/mdp4.xml.h with 94% similarity]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c [moved from drivers/gpu/drm/msm/mdp4/mdp4_crtc.c with 96% similarity]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c [moved from drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c with 98% similarity]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c [moved from drivers/gpu/drm/msm/mdp4/mdp4_kms.c with 89% similarity]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h [moved from drivers/gpu/drm/msm/mdp4/mdp4_kms.h with 79% similarity]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c [moved from drivers/gpu/drm/msm/mdp4/mdp4_plane.c with 98% similarity]
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_common.xml.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_format.c [moved from drivers/gpu/drm/msm/mdp4/mdp4_format.c with 85% similarity]
drivers/gpu/drm/msm/mdp/mdp_kms.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp4/mdp4_irq.c [deleted file]
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_fb.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_iommu.c [new file with mode: 0644]
drivers/gpu/drm/msm/msm_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/msm_mmu.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/core/engine.c
drivers/gpu/drm/nouveau/core/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/engine/device/nv04.c
drivers/gpu/drm/nouveau/core/engine/device/nv10.c
drivers/gpu/drm/nouveau/core/engine/device/nv20.c
drivers/gpu/drm/nouveau/core/engine/device/nv30.c
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/device/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/engine/disp/vga.c
drivers/gpu/drm/nouveau/core/engine/falcon.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
drivers/gpu/drm/nouveau/core/engine/graph/nv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
drivers/gpu/drm/nouveau/core/include/core/device.h
drivers/gpu/drm/nouveau/core/include/engine/fifo.h
drivers/gpu/drm/nouveau/core/include/engine/graph.h
drivers/gpu/drm/nouveau/core/include/subdev/bar.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
drivers/gpu/drm/nouveau/core/include/subdev/vm.h
drivers/gpu/drm/nouveau/core/subdev/bar/base.c
drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/bar/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
drivers/gpu/drm/nouveau/core/subdev/clock/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c
drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
drivers/gpu/drm/nouveau/core/subdev/vm/base.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv04/disp.h
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/omapdrm/omap_debugfs.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/gpu/drm/panel/Kconfig [new file with mode: 0644]
drivers/gpu/drm/panel/Makefile [new file with mode: 0644]
drivers/gpu/drm/panel/panel-simple.c [new file with mode: 0644]
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_irq.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/r128/r128_cce.c
drivers/gpu/drm/r128/r128_drv.h
drivers/gpu/drm/r128/r128_ioc32.c
drivers/gpu/drm/r128/r128_irq.c
drivers/gpu/drm/r128/r128_state.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_i2c.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/ci_smc.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/cikd.h
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dma.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/pptable.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300_cmdbuf.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_dma.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/r600_dpm.h
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_mem.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_sa.c
drivers/gpu/drm/radeon/radeon_state.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs780_dpm.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.h
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/si_smc.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/radeon/sislands_smc.h
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/sumo_smc.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/radeon/trinity_smc.c
drivers/gpu/drm/radeon/uvd_v2_2.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_drv.h
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/savage/savage_bci.c
drivers/gpu/drm/savage/savage_state.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/sis/sis_mm.c
drivers/gpu/drm/tegra/Kconfig
drivers/gpu/drm/tegra/Makefile
drivers/gpu/drm/tegra/bus.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/dc.h
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/dsi.c [new file with mode: 0644]
drivers/gpu/drm/tegra/dsi.h [new file with mode: 0644]
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/tegra/gem.h
drivers/gpu/drm/tegra/gr3d.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/mipi-phy.c [new file with mode: 0644]
drivers/gpu/drm/tegra/mipi-phy.h [new file with mode: 0644]
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/ttm/ttm_lock.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/via/via_dma.c
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/via/via_drv.h
drivers/gpu/drm/via/via_irq.c
drivers/gpu/drm/via/via_video.c
drivers/gpu/drm/vmwgfx/Makefile
drivers/gpu/drm/vmwgfx/svga3d_reg.h
drivers/gpu/drm/vmwgfx/svga_reg.h
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/host1x/Kconfig
drivers/gpu/host1x/Makefile
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/channel.c
drivers/gpu/host1x/debug.c
drivers/gpu/host1x/dev.c
drivers/gpu/host1x/dev.h
drivers/gpu/host1x/hw/host1x02.c
drivers/gpu/host1x/hw/host1x02_hardware.h [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x04.c [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x04.h [new file with mode: 0644]
drivers/gpu/host1x/hw/host1x04_hardware.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x02_uclass.h
drivers/gpu/host1x/hw/hw_host1x04_channel.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x04_sync.h [new file with mode: 0644]
drivers/gpu/host1x/hw/hw_host1x04_uclass.h [new file with mode: 0644]
drivers/gpu/host1x/job.c
drivers/gpu/host1x/mipi.c [new file with mode: 0644]
drivers/gpu/host1x/syncpt.c
drivers/i2c/busses/i2c-tegra.c
drivers/idle/intel_idle.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/input/input.c
drivers/input/keyboard/tegra-kbc.c
drivers/input/touchscreen/zforce_ts.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/telespci.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/mfd/rtsx_pcr.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/phy/phy.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/dm9601.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/of/Kconfig
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/pci/host/pci-tegra.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-acpi.c
drivers/power/Kconfig
drivers/power/power_supply_core.c
drivers/s390/char/tty3270.c
drivers/spi/Kconfig
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-tegra20-slink.c
drivers/staging/bcm/Bcmnet.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/nvec/nvec.c
drivers/staging/nvec/nvec.h
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/tty/serial/serial-tegra.c
drivers/usb/host/ehci-tegra.c
drivers/video/fbmem.c
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/link.c
fs/eventpoll.c
fs/ext4/extents.c
fs/gfs2/aops.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/meta_io.c
fs/gfs2/ops_fstype.c
fs/xfs/xfs_attr_remote.c
fs/xfs/xfs_bmap_util.c
include/acpi/acpi_bus.h
include/drm/drmP.h
include/drm/drm_agpsupport.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_dp_helper.h
include/drm/drm_mipi_dsi.h [new file with mode: 0644]
include/drm/drm_os_linux.h
include/drm/drm_panel.h [new file with mode: 0644]
include/drm/drm_pciids.h
include/drm/ttm/ttm_bo_driver.h
include/drm/ttm/ttm_object.h
include/dt-bindings/clock/tegra114-car.h
include/dt-bindings/clock/tegra124-car.h [new file with mode: 0644]
include/dt-bindings/clock/tegra20-car.h
include/dt-bindings/clock/tegra30-car.h
include/linux/clk/tegra.h
include/linux/dmaengine.h
include/linux/fb.h
include/linux/host1x.h
include/linux/netdevice.h
include/linux/rtnetlink.h
include/linux/skbuff.h
include/linux/tegra-powergate.h
include/net/llc_pdu.h
include/net/sctp/structs.h
include/sound/dmaengine_pcm.h
include/uapi/drm/drm.h
include/uapi/drm/i915_drm.h
include/uapi/drm/radeon_drm.h
include/uapi/drm/vmwgfx_drm.h
include/uapi/linux/input.h
mm/fremap.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory-failure.c
mm/mlock.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_sock.c
net/bridge/br_multicast.c
net/core/dev.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/netpoll.c
net/dccp/probe.c
net/ieee802154/6lowpan.c
net/ipv4/gre_offload.c
net/ipv4/inet_diag.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/route.c
net/ipv6/sit.c
net/llc/af_llc.c
net/mac80211/iface.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_log.c
net/netfilter/nft_exthdr.c
net/nfc/core.c
net/rds/ib.c
net/rose/af_rose.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/sch_generic.c
net/sctp/outqueue.c
net/tipc/link.c
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/wireless/radiotap.c
net/wireless/sme.c
security/selinux/hooks.c
security/selinux/include/objsec.h
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/tegra/Kconfig
sound/soc/tegra/tegra20_ac97.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_ahub.h
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra30_i2s.h
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.h

index 1608a54e90e1541e6a1f7ca918f194f9763ed35e..68ac65f82a1c590e6f046c6b926523d816d5fbe7 100644 (file)
@@ -9,6 +9,7 @@ Required properties:
 - compatible : Should contain "nvidia,tegra<chip>-pmc".
 - reg : Offset and length of the register set for the device
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
   "pclk" (The Tegra clock of that name),
   "clk32k_in" (The 32KHz clock input to Tegra).
index 46f5c791ea0df6e94e2ea6bd8ef26436231f8ebe..0f2f920e87348515995cb553ece45cf0949213b7 100644 (file)
@@ -159,6 +159,8 @@ clock which they consume.
   mixer                        343
   hdmi                 344
   g2d                  345
+  mdma0                        346
+  smmu_mdma0           347
 
 
    [Clock Muxes]
index 0c80c267710451918297675c1e47f2020e183cff..9acea9d931600e01fe37ec0b40a25bcf82a2e864 100644 (file)
@@ -15,6 +15,9 @@ Required properties :
   In clock consumers, this cell represents the clock ID exposed by the
   CAR. The assignments may be found in header file
   <dt-bindings/clock/tegra114-car.h>.
+- #reset-cells : Should be 1.
+  In clock consumers, this cell represents the bit number in the CAR's
+  array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
 
 Example SoC include file:
 
@@ -23,6 +26,7 @@ Example SoC include file:
                compatible = "nvidia,tegra114-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        usb@c5004000 {
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
new file mode 100644 (file)
index 0000000..ded5d62
--- /dev/null
@@ -0,0 +1,63 @@
+NVIDIA Tegra124 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra124-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the
+  CAR. The assignments may be found in header file
+  <dt-bindings/clock/tegra124-car.h>.
+- #reset-cells : Should be 1.
+  In clock consumers, this cell represents the bit number in the CAR's
+  array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
+
+Example SoC include file:
+
+/ {
+       tegra_car: clock {
+               compatible = "nvidia,tegra124-car";
+               reg = <0x60006000 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+       usb@c5004000 {
+               clocks = <&tegra_car TEGRA124_CLK_USB2>;
+       };
+};
+
+Example board file:
+
+/ {
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               osc: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <112400000>;
+               };
+
+               clk_32k: clock@1 {
+                       compatible = "fixed-clock";
+                       reg = <1>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
+       &tegra_car {
+               clocks = <&clk_32k> <&osc>;
+       };
+};
index fcfed5bf73fb8ad6c862457165445577bd25694f..6c5901b503d019adfcd0f24bc8c99aed03fb50f0 100644 (file)
@@ -15,6 +15,9 @@ Required properties :
   In clock consumers, this cell represents the clock ID exposed by the
   CAR. The assignments may be found in header file
   <dt-bindings/clock/tegra20-car.h>.
+- #reset-cells : Should be 1.
+  In clock consumers, this cell represents the bit number in the CAR's
+  array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
 
 Example SoC include file:
 
@@ -23,6 +26,7 @@ Example SoC include file:
                compatible = "nvidia,tegra20-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        usb@c5004000 {
index 0f714081e986b5c722d29d42a3599bd2399369cc..63618cde12df16a7e842834799f6f058bd2ac7a6 100644 (file)
@@ -15,6 +15,9 @@ Required properties :
   In clock consumers, this cell represents the clock ID exposed by the
   CAR. The assignments may be found in header file
   <dt-bindings/clock/tegra30-car.h>.
+- #reset-cells : Should be 1.
+  In clock consumers, this cell represents the bit number in the CAR's
+  array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
 
 Example SoC include file:
 
@@ -23,6 +26,7 @@ Example SoC include file:
                compatible = "nvidia,tegra30-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        usb@c5004000 {
index 90fa7da525b8dd7ede457b5e44a00338f805d099..c6908e7c42cca6936ec9798f5614af25298fb981 100644 (file)
@@ -5,6 +5,16 @@ Required properties:
 - reg: Should contain DMA registers location and length. This shuld include
   all of the per-channel registers.
 - interrupts: Should contain all of the per-channel DMA interrupts.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - dma
+- #dma-cells : Must be <1>. This dictates the length of DMA specifiers in
+  client nodes' dmas properties. The specifier represents the DMA request
+  select value for the peripheral. For more details, consult the Tegra TRM's
+  documentation of the APB DMA channel control register REQ_SEL field.
 
 Examples:
 
@@ -27,4 +37,8 @@ apbdma: dma@6000a000 {
                       0 149 0x04
                       0 150 0x04
                       0 151 0x04 >;
+       clocks = <&tegra_car 34>;
+       resets = <&tegra_car 34>;
+       reset-names = "dma";
+       #dma-cells = <1>;
 };
index b4fa934ae3a2a2fa0e68e85199d676a4b8a682ff..9e9008f8fa3231905428d8e1b62cf2a864008b31 100644 (file)
@@ -9,6 +9,12 @@ Required properties:
 - #size-cells: The number of cells used to represent the size of an address
   range in the host1x address space. Should be 1.
 - ranges: The mapping of the host1x address space to the CPU address space.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - host1x
 
 The host1x top-level node defines a number of children, each representing one
 of the following host1x client modules:
@@ -19,6 +25,12 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-mpe"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - mpe
 
 - vi: video input
 
@@ -26,6 +38,12 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-vi"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - vi
 
 - epp: encoder pre-processor
 
@@ -33,6 +51,12 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-epp"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - epp
 
 - isp: image signal processor
 
@@ -40,6 +64,12 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-isp"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - isp
 
 - gr2d: 2D graphics engine
 
@@ -47,12 +77,30 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-gr2d"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - 2d
 
 - gr3d: 3D graphics engine
 
   Required properties:
   - compatible: "nvidia,tegra<chip>-gr3d"
   - reg: Physical base address and length of the controller's registers.
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    (This property may be omitted if the only clock in the list is "3d")
+    - 3d
+      This MUST be the first entry.
+    - 3d2 (Only required on SoCs with two 3D clocks)
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - 3d
+    - 3d2 (Only required on SoCs with two 3D clocks)
 
 - dc: display controller
 
@@ -60,6 +108,16 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-dc"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    - dc
+      This MUST be the first entry.
+    - parent
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - dc
 
   Each display controller node has a child node, named "rgb", that represents
   the RGB output associated with the controller. It can take the following
@@ -67,6 +125,7 @@ of the following host1x client modules:
   - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
+  - nvidia,panel: phandle of a display panel
 
 - hdmi: High Definition Multimedia Interface
 
@@ -76,11 +135,22 @@ of the following host1x client modules:
   - interrupts: The interrupt outputs from the controller.
   - vdd-supply: regulator for supply voltage
   - pll-supply: regulator for PLL
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    - hdmi
+      This MUST be the first entry.
+    - parent
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - hdmi
 
   Optional properties:
   - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
+  - nvidia,panel: phandle of a display panel
 
 - tvo: TV encoder output
 
@@ -88,12 +158,34 @@ of the following host1x client modules:
   - compatible: "nvidia,tegra<chip>-tvo"
   - reg: Physical base address and length of the controller's registers.
   - interrupts: The interrupt outputs from the controller.
+  - clocks: Must contain one entry, for the module clock.
+    See ../clocks/clock-bindings.txt for details.
 
 - dsi: display serial interface
 
   Required properties:
   - compatible: "nvidia,tegra<chip>-dsi"
   - reg: Physical base address and length of the controller's registers.
+  - clocks: Must contain an entry for each entry in clock-names.
+    See ../clocks/clock-bindings.txt for details.
+  - clock-names: Must include the following entries:
+    - dsi
+      This MUST be the first entry.
+    - lp
+    - parent
+  - resets: Must contain an entry for each entry in reset-names.
+    See ../reset/reset.txt for details.
+  - reset-names: Must include the following entries:
+    - dsi
+  - nvidia,mipi-calibrate: Should contain a phandle and a specifier specifying
+    which pads are used by this DSI output and need to be calibrated. See also
+    ../mipi/nvidia,tegra114-mipi.txt.
+
+  Optional properties:
+  - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+  - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+  - nvidia,edid: supplies a binary EDID blob
+  - nvidia,panel: phandle of a display panel
 
 Example:
 
@@ -105,6 +197,9 @@ Example:
                reg = <0x50000000 0x00024000>;
                interrupts = <0 65 0x04   /* mpcore syncpt */
                              0 67 0x04>; /* mpcore general */
+               clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
+               resets = <&tegra_car 28>;
+               reset-names = "host1x";
 
                #address-cells = <1>;
                #size-cells = <1>;
@@ -115,41 +210,64 @@ Example:
                        compatible = "nvidia,tegra20-mpe";
                        reg = <0x54040000 0x00040000>;
                        interrupts = <0 68 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_MPE>;
+                       resets = <&tegra_car 60>;
+                       reset-names = "mpe";
                };
 
                vi {
                        compatible = "nvidia,tegra20-vi";
                        reg = <0x54080000 0x00040000>;
                        interrupts = <0 69 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_VI>;
+                       resets = <&tegra_car 100>;
+                       reset-names = "vi";
                };
 
                epp {
                        compatible = "nvidia,tegra20-epp";
                        reg = <0x540c0000 0x00040000>;
                        interrupts = <0 70 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_EPP>;
+                       resets = <&tegra_car 19>;
+                       reset-names = "epp";
                };
 
                isp {
                        compatible = "nvidia,tegra20-isp";
                        reg = <0x54100000 0x00040000>;
                        interrupts = <0 71 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_ISP>;
+                       resets = <&tegra_car 23>;
+                       reset-names = "isp";
                };
 
                gr2d {
                        compatible = "nvidia,tegra20-gr2d";
                        reg = <0x54140000 0x00040000>;
                        interrupts = <0 72 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_GR2D>;
+                       resets = <&tegra_car 21>;
+                       reset-names = "2d";
                };
 
                gr3d {
                        compatible = "nvidia,tegra20-gr3d";
                        reg = <0x54180000 0x00040000>;
+                       clocks = <&tegra_car TEGRA20_CLK_GR3D>;
+                       resets = <&tegra_car 24>;
+                       reset-names = "3d";
                };
 
                dc@54200000 {
                        compatible = "nvidia,tegra20-dc";
                        reg = <0x54200000 0x00040000>;
                        interrupts = <0 73 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_DISP1>,
+                                <&tegra_car TEGRA20_CLK_PLL_P>;
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 27>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
@@ -160,6 +278,11 @@ Example:
                        compatible = "nvidia,tegra20-dc";
                        reg = <0x54240000 0x00040000>;
                        interrupts = <0 74 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_DISP2>,
+                                <&tegra_car TEGRA20_CLK_PLL_P>;
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 26>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
@@ -170,6 +293,11 @@ Example:
                        compatible = "nvidia,tegra20-hdmi";
                        reg = <0x54280000 0x00040000>;
                        interrupts = <0 75 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_HDMI>,
+                                <&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
+                       clock-names = "hdmi", "parent";
+                       resets = <&tegra_car 51>;
+                       reset-names = "hdmi";
                        status = "disabled";
                };
 
@@ -177,12 +305,18 @@ Example:
                        compatible = "nvidia,tegra20-tvo";
                        reg = <0x542c0000 0x00040000>;
                        interrupts = <0 76 0x04>;
+                       clocks = <&tegra_car TEGRA20_CLK_TVO>;
                        status = "disabled";
                };
 
                dsi {
                        compatible = "nvidia,tegra20-dsi";
                        reg = <0x54300000 0x00040000>;
+                       clocks = <&tegra_car TEGRA20_CLK_DSI>,
+                                <&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
+                       clock-names = "dsi", "parent";
+                       resets = <&tegra_car 48>;
+                       reset-names = "dsi";
                        status = "disabled";
                };
        };
index ef77cc7a0e466d4a40a481625cb13e00d6f76754..87507e9ce6db50ee4eac7089291afa115806084c 100644 (file)
@@ -39,12 +39,23 @@ Required properties:
 - interrupts: Should contain I2C controller interrupts.
 - address-cells: Address cells for I2C device address.
 - size-cells: Size of the I2C device address.
-- clocks: Clock ID as per
-               Documentation/devicetree/bindings/clock/tegra<chip-id>.txt
-       for I2C controller.
-- clock-names: Name of the clock:
-       Tegra20/Tegra30 I2C controller: "div-clk and "fast-clk".
-       Tegra114 I2C controller: "div-clk".
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  Tegra20/Tegra30:
+  - div-clk
+  - fast-clk
+  Tegra114:
+  - div-clk
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - i2c
+- dmas: Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names: Must include the following entries:
+  - rx
+  - tx
 
 Example:
 
@@ -56,5 +67,9 @@ Example:
                #size-cells = <0>;
                clocks = <&tegra_car 12>, <&tegra_car 124>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 12>;
+               reset-names = "i2c";
+               dmas = <&apbdma 16>, <&apbdma 16>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
index 2995fae7ee474ce81b1a4fdeca3e195d77154ded..0382b8bd69c63b2e821f3a976028384254c81437 100644 (file)
@@ -13,6 +13,12 @@ Required properties:
   array of pin numbers which is used as column.
 - linux,keymap: The keymap for keys as described in the binding document
   devicetree/bindings/input/matrix-keymap.txt.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - kbc
 
 Optional properties, in addition to those specified by the shared
 matrix-keyboard bindings:
@@ -31,6 +37,9 @@ keyboard: keyboard {
        compatible = "nvidia,tegra20-kbc";
        reg = <0x7000e200 0x100>;
        interrupts = <0 85 0x04>;
+       clocks = <&tegra_car 36>;
+       resets = <&tegra_car 36>;
+       reset-names = "kbc";
        nvidia,ghost-filter;
        nvidia,debounce-delay-ms = <640>;
        nvidia,kbc-row-pins = <0 1 2>;    /* pin 0, 1, 2 as rows */
diff --git a/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt b/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt
new file mode 100644 (file)
index 0000000..973c272
--- /dev/null
@@ -0,0 +1,98 @@
+MIPI DSI (Display Serial Interface) busses
+==========================================
+
+The MIPI Display Serial Interface specifies a serial bus and a protocol for
+communication between a host and up to four peripherals. This document will
+define the syntax used to represent a DSI bus in a device tree.
+
+This document describes DSI bus-specific properties only or defines existing
+standard properties in the context of the DSI bus.
+
+Each DSI host provides a DSI bus. The DSI host controller's node contains a
+set of properties that characterize the bus. Child nodes describe individual
+peripherals on that bus.
+
+The following assumes that only a single peripheral is connected to a DSI
+host. Experience shows that this is true for the large majority of setups.
+
+DSI host
+--------
+
+In addition to the standard properties and those defined by the parent bus of
+a DSI host, the following properties apply to a node representing a DSI host.
+
+Required properties:
+- #address-cells: The number of cells required to represent an address on the
+  bus. DSI peripherals are addressed using a 2-bit virtual channel number, so
+  a maximum of 4 devices can be addressed on a single bus. Hence the value of
+  this property should be 1.
+- #size-cells: Should be 0. There are cases where it makes sense to use a
+  different value here. See below.
+
+DSI peripheral
+--------------
+
+Peripherals are represented as child nodes of the DSI host's node. Properties
+described here apply to all DSI peripherals, but individual bindings may want
+to define additional, device-specific properties.
+
+Required properties:
+- reg: The virtual channel number of a DSI peripheral. Must be in the range
+  from 0 to 3.
+
+Some DSI peripherals respond to more than a single virtual channel. In that
+case two alternative representations can be chosen:
+- The reg property can take multiple entries, one for each virtual channel
+  that the peripheral responds to.
+- If the virtual channels that a peripheral responds to are consecutive, the
+  #size-cells can be set to 1. The first cell of each entry in the reg
+  property is the number of the first virtual channel and the second cell is
+  the number of consecutive virtual channels.
+
+Example
+-------
+
+       dsi-host {
+               ...
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* peripheral responds to virtual channel 0 */
+               peripheral@0 {
+                       compatible = "...";
+                       reg = <0>;
+               };
+
+               ...
+       };
+
+       dsi-host {
+               ...
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* peripheral responds to virtual channels 0 and 2 */
+               peripheral@0 {
+                       compatible = "...";
+                       reg = <0, 2>;
+               };
+
+               ...
+       };
+
+       dsi-host {
+               ...
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* peripheral responds to virtual channels 1, 2 and 3 */
+               peripheral@1 {
+                       compatible = "...";
+                       reg = <1 3>;
+               };
+
+               ...
+       };
diff --git a/Documentation/devicetree/bindings/mipi/nvidia,tegra114-mipi.txt b/Documentation/devicetree/bindings/mipi/nvidia,tegra114-mipi.txt
new file mode 100644 (file)
index 0000000..e4a25ce
--- /dev/null
@@ -0,0 +1,41 @@
+NVIDIA Tegra MIPI pad calibration controller
+
+Required properties:
+- compatible: "nvidia,tegra<chip>-mipi"
+- reg: Physical base address and length of the controller's registers.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - mipi-cal
+- #nvidia,mipi-calibrate-cells: Should be 1. The cell is a bitmask of the pads
+  that need to be calibrated for a given device.
+
+User nodes need to contain an nvidia,mipi-calibrate property that has a
+phandle to refer to the calibration controller node and a bitmask of the pads
+that need to be calibrated.
+
+Example:
+
+       mipi: mipi@700e3000 {
+               compatible = "nvidia,tegra114-mipi";
+               reg = <0x700e3000 0x100>;
+               clocks = <&tegra_car TEGRA114_CLK_MIPI_CAL>;
+               clock-names = "mipi-cal";
+               #nvidia,mipi-calibrate-cells = <1>;
+       };
+
+       ...
+
+       host1x@50000000 {
+               ...
+
+               dsi@54300000 {
+                       ...
+
+                       nvidia,mipi-calibrate = <&mipi 0x060>;
+
+                       ...
+               };
+
+               ...
+       };
index c6d7b11db9eb00ed81ad3fcff3ddb78c9dbdc072..f357c16ea815c5fc6c3b2d7a8a4c41a9683f60bc 100644 (file)
@@ -8,6 +8,12 @@ by mmc.txt and the properties used by the sdhci-tegra driver.
 
 Required properties:
 - compatible : Should be "nvidia,<chip>-sdhci"
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - sdhci
 
 Optional properties:
 - power-gpios : Specify GPIOs for power control
@@ -18,6 +24,9 @@ sdhci@c8000200 {
        compatible = "nvidia,tegra20-sdhci";
        reg = <0xc8000200 0x200>;
        interrupts = <47>;
+       clocks = <&tegra_car 14>;
+       resets = <&tegra_car 14>;
+       reset-names = "sdhci";
        cd-gpios = <&gpio 69 0>; /* gpio PI5 */
        wp-gpios = <&gpio 57 0>; /* gpio PH1 */
        power-gpios = <&gpio 155 0>; /* gpio PT3 */
index 5aeee53ff9f4afcb78fba8516d50e4f97edbccbf..5ae601e7f51f313a5c0a0f4dbc0095151841a519 100644 (file)
@@ -7,3 +7,15 @@ Required properties:
 - clock-frequency : the frequency of the i2c bus
 - gpios : the gpio used for ec request
 - slave-addr: the i2c address of the slave controller
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  Tegra20/Tegra30:
+  - div-clk
+  - fast-clk
+  Tegra114:
+  - div-clk
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - i2c
diff --git a/Documentation/devicetree/bindings/panel/auo,b101aw03.txt b/Documentation/devicetree/bindings/panel/auo,b101aw03.txt
new file mode 100644 (file)
index 0000000..72e088a
--- /dev/null
@@ -0,0 +1,7 @@
+AU Optronics Corporation 10.1" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,b101aw03"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt b/Documentation/devicetree/bindings/panel/chunghwa,claa101wb03.txt
new file mode 100644 (file)
index 0000000..0ab2c05
--- /dev/null
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa101wb03"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt b/Documentation/devicetree/bindings/panel/panasonic,vvx10f004b00.txt
new file mode 100644 (file)
index 0000000..d328b03
--- /dev/null
@@ -0,0 +1,7 @@
+Panasonic Corporation 10.1" WUXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "panasonic,vvx10f004b00"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/simple-panel.txt b/Documentation/devicetree/bindings/panel/simple-panel.txt
new file mode 100644 (file)
index 0000000..1341bbf
--- /dev/null
@@ -0,0 +1,21 @@
+Simple display panel
+
+Required properties:
+- power-supply: regulator to provide the supply voltage
+
+Optional properties:
+- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+       panel: panel {
+               compatible = "cptt,claa101wb01";
+               ddc-i2c-bus = <&panelddc>;
+
+               power-supply = <&vdd_pnl_reg>;
+               enable-gpios = <&gpio 90 0>;
+
+               backlight = <&backlight>;
+       };
index 6b7510775c50da125ff55c491613afaa0f216e16..24cee06915c989cfd6866ad5f3d86e3605cd0ae3 100644 (file)
@@ -42,14 +42,19 @@ Required properties:
     - 0xc2000000: prefetchable memory region
   Please refer to the standard PCI bus binding document for a more detailed
   explanation.
-- clocks: List of clock inputs of the controller. Must contain an entry for
-  each entry in the clock-names property.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
-  "pex": The Tegra clock of that name
-  "afi": The Tegra clock of that name
-  "pcie_xclk": The Tegra clock of that name
-  "pll_e": The Tegra clock of that name
-  "cml": The Tegra clock of that name (not required for Tegra20)
+  - pex
+  - afi
+  - pll_e
+  - cml (not required for Tegra20)
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - pex
+  - afi
+  - pcie_x
 
 Root ports are defined as subnodes of the PCIe controller node.
 
@@ -91,9 +96,10 @@ SoC DTSI:
                          0x82000000 0 0xa0000000 0xa0000000 0 0x10000000   /* non-prefetchable memory */
                          0xc2000000 0 0xb0000000 0xb0000000 0 0x10000000>; /* prefetchable memory */
 
-               clocks = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>,
-                        <&tegra_car 118>;
-               clock-names = "pex", "afi", "pcie_xclk", "pll_e";
+               clocks = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 118>;
+               clock-names = "pex", "afi", "pll_e";
+               resets = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>;
+               reset-names = "pex", "afi", "pcie_x";
                status = "disabled";
 
                pci@1,0 {
index c3fc57af877260e5f25ca1290e1ca333895d9bdd..c7ea9d4a988b8d78971a96cf585a011ae7274711 100644 (file)
@@ -7,6 +7,12 @@ Required properties:
 - reg: physical base address and length of the controller's registers
 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
   the cells format.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - pwm
 
 Example:
 
@@ -14,4 +20,7 @@ Example:
                compatible = "nvidia,tegra20-pwm";
                reg = <0x7000a000 0x100>;
                #pwm-cells = <2>;
+               clocks = <&tegra_car 17>;
+               resets = <&tegra_car 17>;
+               reset-names = "pwm";
        };
index 93f45e9dce7cf07899d65c525181684d0bfd30c5..652d1ff2e8beb6f9ca33d145be74f2e12fb0eacf 100644 (file)
@@ -9,6 +9,8 @@ Required properties:
 - compatible : should be "nvidia,tegra20-rtc".
 - reg : Specifies base physical address and size of the registers.
 - interrupts : A single interrupt specifier.
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
 
 Example:
 
@@ -16,4 +18,5 @@ timer {
        compatible = "nvidia,tegra20-rtc";
        reg = <0x7000e000 0x100>;
        interrupts = <0 2 0x04>;
+       clocks = <&tegra_car 4>;
 };
index 392a4493eebd59354161b5c6fc6ee5f7a44d59fa..845850caf088100fb325d5353a6c4a1e1073e730 100644 (file)
@@ -4,8 +4,17 @@ Required properties:
 - compatible : should be "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
 - reg: Should contain UART controller registers location and length.
 - interrupts: Should contain UART controller interrupts.
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this UART controller.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - serial
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
 
 Optional properties:
 - nvidia,enable-modem-interrupt: Enable modem interrupts. Should be enable
@@ -18,7 +27,11 @@ serial@70006000 {
        reg = <0x70006000 0x40>;
        reg-shift = <2>;
        interrupts = <0 36 0x04>;
-       nvidia,dma-request-selector = <&apbdma 8>;
        nvidia,enable-modem-interrupt;
+       clocks = <&tegra_car 6>;
+       resets = <&tegra_car 6>;
+       reset-names = "serial";
+       dmas = <&apbdma 8>, <&apbdma 8>;
+       dma-names = "rx", "tx";
        status = "disabled";
 };
index 8b8903ef0800069afdad90f10e5964f3bd2e20c9..57f40f93453ecabbf89763ef66a2f709ca29af7b 100644 (file)
@@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
 Required properties:
 - compatible : "nvidia,tegra-audio-alc5632"
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  "pll_a" (The Tegra clock of that name),
-  "pll_a_out0" (The Tegra clock of that name),
-  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - 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,
index dc6224994d69d97f31614a308d71ba6cf2c9784c..7788808dcd0bb20d5183bdce92d2591f9ac90bdb 100644 (file)
@@ -3,10 +3,11 @@ NVIDIA Tegra audio complex, with RT5640 CODEC
 Required properties:
 - compatible : "nvidia,tegra-audio-rt5640"
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  "pll_a" (The Tegra clock of that name),
-  "pll_a_out0" (The Tegra clock of that name),
-  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - 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,
index aab6ce0ad2fc5930054a1f97c73ea5781aa57e10..96f6a57dd6b40669b5addf6fbd9319b81c501fae 100644 (file)
@@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
 Required properties:
 - compatible : "nvidia,tegra-audio-wm8753"
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  "pll_a" (The Tegra clock of that name),
-  "pll_a_out0" (The Tegra clock of that name),
-  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - 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,
index 4b44dfb6ca0dcb08e5ad4468df6aeee853d3d56e..b795d282818d8acd34b9c57fdc53cb5e721d009a 100644 (file)
@@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
 Required properties:
 - compatible : "nvidia,tegra-audio-wm8903"
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  "pll_a" (The Tegra clock of that name),
-  "pll_a_out0" (The Tegra clock of that name),
-  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - 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,
index ad589b16363988460afb2f697535a0c8dfaa47e4..436f6cd9d07cdfc6cdc4dc93416329e3db7ecdad 100644 (file)
@@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
 Required properties:
 - compatible : "nvidia,tegra-audio-wm9712"
 - clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  "pll_a" (The Tegra clock of that name),
-  "pll_a_out0" (The Tegra clock of that name),
-  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - 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,
index c1454979c1ef71b8a5b506154418f5d1f9c24357..eaf00102d92c295765ddd895f9a937511a9cc80b 100644 (file)
@@ -4,19 +4,33 @@ Required properties:
 - compatible : "nvidia,tegra20-ac97"
 - reg : Should contain AC97 controller registers location and length
 - interrupts : Should contain AC97 interrupt
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for the AC97 controller
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - ac97
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
 - nvidia,codec-reset-gpio : The Tegra GPIO controller's phandle and the number
   of the GPIO used to reset the external AC97 codec
 - nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
   of the GPIO corresponding with the AC97 DAP _FS line
+
 Example:
 
 ac97@70002000 {
        compatible = "nvidia,tegra20-ac97";
        reg = <0x70002000 0x200>;
        interrupts = <0 81 0x04>;
-       nvidia,dma-request-selector = <&apbdma 12>;
        nvidia,codec-reset-gpio = <&gpio 170 0>;
        nvidia,codec-sync-gpio = <&gpio 120 0>;
+       clocks = <&tegra_car 3>;
+       resets = <&tegra_car 3>;
+       reset-names = "ac97";
+       dmas = <&apbdma 12>, <&apbdma 12>;
+       dma-names = "rx", "tx";
 };
index 0df2b5c816e3fd31beb853e51a922a1a0f65ad49..dc30c6bfbe95fc60a2642695fcacc7125221cc75 100644 (file)
@@ -4,8 +4,17 @@ Required properties:
 - compatible : "nvidia,tegra20-i2s"
 - reg : Should contain I2S registers location and length
 - interrupts : Should contain I2S interrupt
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this I2S controller
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - i2s
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
 
 Example:
 
@@ -13,5 +22,9 @@ i2s@70002800 {
        compatible = "nvidia,tegra20-i2s";
        reg = <0x70002800 0x200>;
        interrupts = < 45 >;
-       nvidia,dma-request-selector = < &apbdma 2 >;
+       clocks = <&tegra_car 11>;
+       resets = <&tegra_car 11>;
+       reset-names = "i2s";
+       dmas = <&apbdma 21>, <&apbdma 21>;
+       dma-names = "rx", "tx";
 };
index 0e5c12c665230d5f5d1df14bb4d3faed5621b4c4..946e2ac46091c05dfd9266febfb8362ad646e0cc 100644 (file)
@@ -7,18 +7,48 @@ Required properties:
   - Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
   - Tegra114 requires an additional entry, for the APBIF2 register block.
 - interrupts : Should contain AHUB interrupt
-- nvidia,dma-request-selector : A list of the DMA channel specifiers. Each
-  entry contains the Tegra DMA controller's phandle and request selector.
-  If a single entry is present, the request selectors for the channels are
-  assumed to be contiguous, and increment from this value.
-  If multiple values are given, one value must be given per channel.
-- clocks : Must contain an entry for each required entry in clock-names.
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entries:
-  - Tegra30: Requires d_audio, apbif, i2s0, i2s1, i2s2, i2s3, i2s4, dam0,
-    dam1, dam2, spdif_in.
-  - Tegra114: Additionally requires amx, adx.
+  - d_audio
+  - apbif
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  Tegra30 and later:
+  - d_audio
+  - apbif
+  - i2s0
+  - i2s1
+  - i2s2
+  - i2s3
+  - i2s4
+  - dam0
+  - dam1
+  - dam2
+  - spdif
+  Tegra114 and later additionally require:
+  - amx
+  - adx
+  Tegra124 and later additionally require:
+  - amx1
+  - adx1
+  - afc0
+  - afc1
+  - afc2
+  - afc3
+  - afc4
+  - afc5
 - ranges : The bus address mapping for the configlink register bus.
   Can be empty since the mapping is 1:1.
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx0 .. rx<n>
+  - tx0 .. tx<n>
+  ... where n is:
+  Tegra30: 3
+  Tegra114, Tegra124: 9
 - #address-cells : For the configlink bus. Should be <1>;
 - #size-cells : For the configlink bus. Should be <1>.
 
@@ -35,13 +65,20 @@ ahub@70080000 {
        reg = <0x70080000 0x200 0x70080200 0x100>;
        interrupts = < 0 103 0x04 >;
        nvidia,dma-request-selector = <&apbdma 1>;
-       clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
+       clocks = <&tegra_car 106>, <&tegra_car 107>;
+       clock-names = "d_audio", "apbif";
+       resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
                <&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
                <&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
-               <&tegra_car 110>, <&tegra_car 162>;
-       clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+               <&tegra_car 110>, <&tegra_car 10>;
+       reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
                "i2s3", "i2s4", "dam0", "dam1", "dam2",
-               "spdif_in";
+               "spdif";
+       dmas = <&apbdma 1>, <&apbdma 1>;
+              <&apbdma 2>, <&apbdma 2>;
+              <&apbdma 3>, <&apbdma 3>;
+              <&apbdma 4>, <&apbdma 4>;
+       dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
        ranges;
        #address-cells = <1>;
        #size-cells = <1>;
index dfa6c037124aeb242ffdc4c2919aae058e7543a9..0c113ffe381492627474948aeb3f8357c4693d44 100644 (file)
@@ -3,13 +3,22 @@ NVIDIA Tegra30 I2S controller
 Required properties:
 - compatible : "nvidia,tegra30-i2s"
 - reg : Should contain I2S registers location and length
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - i2s
 - nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback)
   first, tx (capture) second. See nvidia,tegra30-ahub.txt for values.
 
 Example:
 
-i2s@70002800 {
+i2s@70080300 {
        compatible = "nvidia,tegra30-i2s";
        reg = <0x70080300 0x100>;
        nvidia,ahub-cif-ids = <4 4>;
+       clocks = <&tegra_car 11>;
+       resets = <&tegra_car 11>;
+       reset-names = "i2s";
 };
index 91ff771c7e77da25031f19e0bd8cdf973494f63e..7ea701e07dc2603453eb4b37d1aaef1c626a3e06 100644 (file)
@@ -4,10 +4,19 @@ Required properties:
 - compatible : should be "nvidia,tegra114-spi".
 - reg: Should contain SPI registers location and length.
 - interrupts: Should contain SPI interrupts.
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this SPI controller.
-- This is also require clock named "spi" as per binding document
-  Documentation/devicetree/bindings/clock/clock-bindings.txt
+- clock-names : Must include the following entries:
+  - spi
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - spi
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
 
 Recommended properties:
 - spi-max-frequency: Definition as per
@@ -18,9 +27,14 @@ spi@7000d600 {
        compatible = "nvidia,tegra114-spi";
        reg = <0x7000d600 0x200>;
        interrupts = <0 82 0x04>;
-       nvidia,dma-request-selector = <&apbdma 16>;
        spi-max-frequency = <25000000>;
        #address-cells = <1>;
        #size-cells = <0>;
+       clocks = <&tegra_car 44>;
+       clock-names = "spi";
+       resets = <&tegra_car 44>;
+       reset-names = "spi";
+       dmas = <&apbdma 16>, <&apbdma 16>;
+       dma-names = "rx", "tx";
        status = "disabled";
 };
index 7b53da5cb75b9d24e11652f15bd15d11e67d6ada..bdf08e6dec9bdf325fe9a992c2dfd611dbd46a92 100644 (file)
@@ -4,8 +4,17 @@ Required properties:
 - compatible : should be "nvidia,tegra20-sflash".
 - reg: Should contain SFLASH registers location and length.
 - interrupts: Should contain SFLASH interrupts.
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this SFLASH controller.
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - spi
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
 
 Recommended properties:
 - spi-max-frequency: Definition as per
@@ -17,10 +26,13 @@ spi@7000c380 {
        compatible = "nvidia,tegra20-sflash";
        reg = <0x7000c380 0x80>;
        interrupts = <0 39 0x04>;
-       nvidia,dma-request-selector = <&apbdma 16>;
        spi-max-frequency = <25000000>;
        #address-cells = <1>;
        #size-cells = <0>;
+       clocks = <&tegra_car 43>;
+       resets = <&tegra_car 43>;
+       reset-names = "spi";
+       dmas = <&apbdma 11>, <&apbdma 11>;
+       dma-names = "rx", "tx";
        status = "disabled";
 };
-
index eefe15e3d95e8f3cc9a8ff2885ec494563d488cd..5db9144a33c8beee16993c5f79100b59e8de669b 100644 (file)
@@ -4,8 +4,17 @@ Required properties:
 - compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
 - reg: Should contain SLINK registers location and length.
 - interrupts: Should contain SLINK interrupts.
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this SLINK controller.
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - spi
+- dmas : Must contain an entry for each entry in clock-names.
+  See ../dma/dma.txt for details.
+- dma-names : Must include the following entries:
+  - rx
+  - tx
 
 Recommended properties:
 - spi-max-frequency: Definition as per
@@ -17,10 +26,13 @@ spi@7000d600 {
        compatible = "nvidia,tegra20-slink";
        reg = <0x7000d600 0x200>;
        interrupts = <0 82 0x04>;
-       nvidia,dma-request-selector = <&apbdma 16>;
        spi-max-frequency = <25000000>;
        #address-cells = <1>;
        #size-cells = <0>;
+       clocks = <&tegra_car 44>;
+       resets = <&tegra_car 44>;
+       reset-names = "spi";
+       dmas = <&apbdma 16>, <&apbdma 16>;
+       dma-names = "rx", "tx";
        status = "disabled";
 };
-
index e019fdc38773c8046617a33aee0aad5883aa1ce7..4a864bd10d3d3cb8a9eb32c95a0e2899dbb97f4c 100644 (file)
@@ -8,6 +8,8 @@ Required properties:
 - compatible : should be "nvidia,tegra20-timer".
 - reg : Specifies base physical address and size of the registers.
 - interrupts : A list of 4 interrupts; one per timer channel.
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
 
 Example:
 
@@ -18,4 +20,5 @@ timer {
                        0 1 0x04
                        0 41 0x04
                        0 42 0x04>;
+       clocks = <&tegra_car 132>;
 };
index 906109d4c593303ed3453f9284ba13426a21e5de..b5082a1cf461a16af5d37a5691a1b603ae47e031 100644 (file)
@@ -10,6 +10,8 @@ Required properties:
 - reg : Specifies base physical address and size of the registers.
 - interrupts : A list of 6 interrupts; one per each of timer channels 1
     through 5, and one for the shared interrupt for the remaining channels.
+- clocks : Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
 
 timer {
        compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
@@ -20,4 +22,5 @@ timer {
                      0 42 0x04
                      0 121 0x04
                      0 122 0x04>;
+       clocks = <&tegra_car 214>;
 };
index df0933043a5be46f705a450e3956f92d8ef77600..3dc9140e3dfba6d26f7c43e43d04308134cb543e 100644 (file)
@@ -8,7 +8,12 @@ and additions :
 Required properties :
  - compatible : Should be "nvidia,tegra20-ehci".
  - nvidia,phy : phandle of the PHY that the controller is connected to.
- - clocks : Contains a single entry which defines the USB controller's clock.
+ - clocks : Must contain one entry, for the module clock.
+   See ../clocks/clock-bindings.txt for details.
+ - resets : Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+ - reset-names : Must include the following entries:
+   - usb
 
 Optional properties:
  - nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
index d5e4ff328cc7146827ac3d02cd8df189b881abc4..31a046213274e06e63e26da0514ede7ebc7c4443 100644 (file)
@@ -783,7 +783,7 @@ F:  arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-highbank/
@@ -1368,6 +1368,9 @@ T:        git git://git.xilinx.com/linux-xlnx.git
 S:     Supported
 F:     arch/arm/mach-zynq/
 F:     drivers/cpuidle/cpuidle-zynq.c
+N:     zynq
+N:     xilinx
+F:     drivers/clocksource/cadence_ttc_timer.c
 
 ARM SMMU DRIVER
 M:     Will Deacon <will.deacon@arm.com>
@@ -2825,8 +2828,10 @@ F:       include/uapi/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
+M:     Jani Nikula <jani.nikula@linux.intel.com>
 L:     intel-gfx@lists.freedesktop.org
 L:     dri-devel@lists.freedesktop.org
+Q:     http://patchwork.freedesktop.org/project/intel-gfx/
 T:     git git://people.freedesktop.org/~danvet/drm-intel
 S:     Supported
 F:     drivers/gpu/drm/i915/
@@ -6256,7 +6261,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6268,7 +6273,7 @@ K:        of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
index ab80be7a38bca0261b2adc49e878f00fea113dcd..eeec740776f3548d2ffa871b52d34a881e2f77e4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc8
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
index 9db5047812f3d6c05a36643abbea0e1fb33e8195..177becde7a268bdcee91be7b049567d17daf9809 100644 (file)
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x10800000 0x1000>;
                        interrupts = <0 33 0>;
-                       clocks = <&clock 271>;
+                       clocks = <&clock 346>;
                        clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
index 8d42787c8ff172a0b8594899b8ef92dd08d2be10..731249fbe2064f53d5fb6bce7a20ff22953f3ba8 100644 (file)
@@ -43,6 +43,7 @@
                compatible = "nvidia,tegra114-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        apbdma: dma {
@@ -81,6 +82,9 @@
                             <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_APBDMA>;
+               resets = <&tegra_car 34>;
+               reset-names = "dma";
+               #dma-cells = <1>;
        };
 
        ahb: ahb {
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 8>;
-               status = "disabled";
                clocks = <&tegra_car TEGRA114_CLK_UARTA>;
+               resets = <&tegra_car 6>;
+               reset-names = "serial";
+               dmas = <&apbdma 8>, <&apbdma 8>;
+               dma-names = "rx", "tx";
+               status = "disabled";
        };
 
        uartb: serial@70006040 {
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 9>;
-               status = "disabled";
                clocks = <&tegra_car TEGRA114_CLK_UARTB>;
+               resets = <&tegra_car 7>;
+               reset-names = "serial";
+               dmas = <&apbdma 9>, <&apbdma 9>;
+               dma-names = "rx", "tx";
+               status = "disabled";
        };
 
        uartc: serial@70006200 {
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 10>;
-               status = "disabled";
                clocks = <&tegra_car TEGRA114_CLK_UARTC>;
+               resets = <&tegra_car 55>;
+               reset-names = "serial";
+               dmas = <&apbdma 10>, <&apbdma 10>;
+               dma-names = "rx", "tx";
+               status = "disabled";
        };
 
        uartd: serial@70006300 {
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 19>;
-               status = "disabled";
                clocks = <&tegra_car TEGRA114_CLK_UARTD>;
+               resets = <&tegra_car 65>;
+               reset-names = "serial";
+               dmas = <&apbdma 19>, <&apbdma 19>;
+               dma-names = "rx", "tx";
+               status = "disabled";
        };
 
        pwm: pwm {
                reg = <0x7000a000 0x100>;
                #pwm-cells = <2>;
                clocks = <&tegra_car TEGRA114_CLK_PWM>;
+               resets = <&tegra_car 17>;
+               reset-names = "pwm";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_I2C1>;
                clock-names = "div-clk";
+               resets = <&tegra_car 12>;
+               reset-names = "i2c";
+               dmas = <&apbdma 21>, <&apbdma 21>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_I2C2>;
                clock-names = "div-clk";
+               resets = <&tegra_car 54>;
+               reset-names = "i2c";
+               dmas = <&apbdma 22>, <&apbdma 22>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_I2C3>;
                clock-names = "div-clk";
+               resets = <&tegra_car 67>;
+               reset-names = "i2c";
+               dmas = <&apbdma 23>, <&apbdma 23>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_I2C4>;
                clock-names = "div-clk";
+               resets = <&tegra_car 103>;
+               reset-names = "i2c";
+               dmas = <&apbdma 26>, <&apbdma 26>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_I2C5>;
                clock-names = "div-clk";
+               resets = <&tegra_car 47>;
+               reset-names = "i2c";
+               dmas = <&apbdma 24>, <&apbdma 24>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000d400 0x200>;
                interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 15>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC1>;
                clock-names = "spi";
+               resets = <&tegra_car 41>;
+               reset-names = "spi";
+               dmas = <&apbdma 15>, <&apbdma 15>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000d600 0x200>;
                interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 16>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC2>;
                clock-names = "spi";
+               resets = <&tegra_car 44>;
+               reset-names = "spi";
+               dmas = <&apbdma 16>, <&apbdma 16>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000d800 0x200>;
                interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 17>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC3>;
                clock-names = "spi";
+               resets = <&tegra_car 46>;
+               reset-names = "spi";
+               dmas = <&apbdma 17>, <&apbdma 17>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000da00 0x200>;
                interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 18>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC4>;
                clock-names = "spi";
+               resets = <&tegra_car 68>;
+               reset-names = "spi";
+               dmas = <&apbdma 18>, <&apbdma 18>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000dc00 0x200>;
                interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 27>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC5>;
                clock-names = "spi";
+               resets = <&tegra_car 104>;
+               reset-names = "spi";
+               dmas = <&apbdma 27>, <&apbdma 27>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra114-spi";
                reg = <0x7000de00 0x200>;
                interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 28>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA114_CLK_SBC6>;
                clock-names = "spi";
+               resets = <&tegra_car 105>;
+               reset-names = "spi";
+               dmas = <&apbdma 28>, <&apbdma 28>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x7000e200 0x100>;
                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_KBC>;
+               resets = <&tegra_car 36>;
+               reset-names = "kbc";
                status = "disabled";
        };
 
                      <0x70080200 0x100>,
                      <0x70081000 0x200>;
                interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 1>, <&apbdma 2>,
-                       <&apbdma 3>, <&apbdma 4>, <&apbdma 6>, <&apbdma 7>,
-                       <&apbdma 12>, <&apbdma 13>, <&apbdma 14>,
-                       <&apbdma 29>;
                clocks = <&tegra_car TEGRA114_CLK_D_AUDIO>,
-                        <&tegra_car TEGRA114_CLK_APBIF>,
-                        <&tegra_car TEGRA114_CLK_I2S0>,
-                        <&tegra_car TEGRA114_CLK_I2S1>,
-                        <&tegra_car TEGRA114_CLK_I2S2>,
-                        <&tegra_car TEGRA114_CLK_I2S3>,
-                        <&tegra_car TEGRA114_CLK_I2S4>,
-                        <&tegra_car TEGRA114_CLK_DAM0>,
-                        <&tegra_car TEGRA114_CLK_DAM1>,
-                        <&tegra_car TEGRA114_CLK_DAM2>,
-                        <&tegra_car TEGRA114_CLK_SPDIF_IN>,
-                        <&tegra_car TEGRA114_CLK_AMX>,
-                        <&tegra_car TEGRA114_CLK_ADX>;
-               clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+                        <&tegra_car TEGRA114_CLK_APBIF>;
+               clock-names = "d_audio", "apbif";
+               resets = <&tegra_car 106>, /* d_audio */
+                        <&tegra_car 107>, /* apbif */
+                        <&tegra_car 30>,  /* i2s0 */
+                        <&tegra_car 11>,  /* i2s1 */
+                        <&tegra_car 18>,  /* i2s2 */
+                        <&tegra_car 101>, /* i2s3 */
+                        <&tegra_car 102>, /* i2s4 */
+                        <&tegra_car 108>, /* dam0 */
+                        <&tegra_car 109>, /* dam1 */
+                        <&tegra_car 110>, /* dam2 */
+                        <&tegra_car 10>,  /* spdif */
+                        <&tegra_car 153>, /* amx */
+                        <&tegra_car 154>; /* adx */
+               reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
                              "i2s3", "i2s4", "dam0", "dam1", "dam2",
-                             "spdif_in", "amx", "adx";
+                             "spdif", "amx", "adx";
+               dmas = <&apbdma 1>, <&apbdma 1>,
+                      <&apbdma 2>, <&apbdma 2>,
+                      <&apbdma 3>, <&apbdma 3>,
+                      <&apbdma 4>, <&apbdma 4>,
+                      <&apbdma 6>, <&apbdma 6>,
+                      <&apbdma 7>, <&apbdma 7>,
+                      <&apbdma 12>, <&apbdma 12>,
+                      <&apbdma 13>, <&apbdma 13>,
+                      <&apbdma 14>, <&apbdma 14>,
+                      <&apbdma 29>, <&apbdma 29>;
+               dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2",
+                           "rx3", "tx3", "rx4", "tx4", "rx5", "tx5",
+                           "rx6", "tx6", "rx7", "tx7", "rx8", "tx8",
+                           "rx9", "tx9";
                ranges;
                #address-cells = <1>;
                #size-cells = <1>;
                        reg = <0x70080300 0x100>;
                        nvidia,ahub-cif-ids = <4 4>;
                        clocks = <&tegra_car TEGRA114_CLK_I2S0>;
+                       resets = <&tegra_car 30>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080400 0x100>;
                        nvidia,ahub-cif-ids = <5 5>;
                        clocks = <&tegra_car TEGRA114_CLK_I2S1>;
+                       resets = <&tegra_car 11>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080500 0x100>;
                        nvidia,ahub-cif-ids = <6 6>;
                        clocks = <&tegra_car TEGRA114_CLK_I2S2>;
+                       resets = <&tegra_car 18>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080600 0x100>;
                        nvidia,ahub-cif-ids = <7 7>;
                        clocks = <&tegra_car TEGRA114_CLK_I2S3>;
+                       resets = <&tegra_car 101>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080700 0x100>;
                        nvidia,ahub-cif-ids = <8 8>;
                        clocks = <&tegra_car TEGRA114_CLK_I2S4>;
+                       resets = <&tegra_car 102>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
        };
                reg = <0x78000000 0x200>;
                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_SDMMC1>;
+               resets = <&tegra_car 14>;
+               reset-names = "sdhci";
                status = "disable";
        };
 
                reg = <0x78000200 0x200>;
                interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_SDMMC2>;
+               resets = <&tegra_car 9>;
+               reset-names = "sdhci";
                status = "disable";
        };
 
                reg = <0x78000400 0x200>;
                interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_SDMMC3>;
+               resets = <&tegra_car 69>;
+               reset-names = "sdhci";
                status = "disable";
        };
 
                reg = <0x78000600 0x200>;
                interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA114_CLK_SDMMC4>;
+               resets = <&tegra_car 15>;
+               reset-names = "sdhci";
                status = "disable";
        };
 
                interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "utmi";
                clocks = <&tegra_car TEGRA114_CLK_USBD>;
+               resets = <&tegra_car 22>;
+               reset-names = "usb";
                nvidia,phy = <&phy1>;
                status = "disabled";
        };
                interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "utmi";
                clocks = <&tegra_car TEGRA114_CLK_USB3>;
+               resets = <&tegra_car 59>;
+               reset-names = "usb";
                nvidia,phy = <&phy3>;
                status = "disabled";
        };
index 8d71fc9d8a2f6cca72ef5f04d1fe5517ffbc5de0..e57fb3aefc2a624cf99a69fb1c7b54444bd1cb05 100644 (file)
                clocks = <&tegra_car TEGRA20_CLK_I2C3>,
                         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 67>;
+               reset-names = "i2c";
        };
 
        i2c@7000d000 {
index df40b54fd8bca58eeeb610d6a5c755d4fec51aae..c90d0aac3afe8eb61f8f1b5c03545bd0585cf7b3 100644 (file)
@@ -22,6 +22,8 @@
                interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
                             <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
                clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
+               resets = <&tegra_car 28>;
+               reset-names = "host1x";
 
                #address-cells = <1>;
                #size-cells = <1>;
@@ -33,6 +35,8 @@
                        reg = <0x54040000 0x00040000>;
                        interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_MPE>;
+                       resets = <&tegra_car 60>;
+                       reset-names = "mpe";
                };
 
                vi {
@@ -40,6 +44,8 @@
                        reg = <0x54080000 0x00040000>;
                        interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_VI>;
+                       resets = <&tegra_car 20>;
+                       reset-names = "vi";
                };
 
                epp {
@@ -47,6 +53,8 @@
                        reg = <0x540c0000 0x00040000>;
                        interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_EPP>;
+                       resets = <&tegra_car 19>;
+                       reset-names = "epp";
                };
 
                isp {
@@ -54,6 +62,8 @@
                        reg = <0x54100000 0x00040000>;
                        interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_ISP>;
+                       resets = <&tegra_car 23>;
+                       reset-names = "isp";
                };
 
                gr2d {
                        reg = <0x54140000 0x00040000>;
                        interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_GR2D>;
+                       resets = <&tegra_car 21>;
+                       reset-names = "2d";
                };
 
                gr3d {
                        compatible = "nvidia,tegra20-gr3d";
                        reg = <0x54180000 0x00040000>;
                        clocks = <&tegra_car TEGRA20_CLK_GR3D>;
+                       resets = <&tegra_car 24>;
+                       reset-names = "3d";
                };
 
                dc@54200000 {
@@ -75,7 +89,9 @@
                        interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_DISP1>,
                                 <&tegra_car TEGRA20_CLK_PLL_P>;
-                       clock-names = "disp1", "parent";
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 27>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
                        interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA20_CLK_DISP2>,
                                 <&tegra_car TEGRA20_CLK_PLL_P>;
-                       clock-names = "disp2", "parent";
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 26>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
                        clocks = <&tegra_car TEGRA20_CLK_HDMI>,
                                 <&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
                        clock-names = "hdmi", "parent";
+                       resets = <&tegra_car 51>;
+                       reset-names = "hdmi";
                        status = "disabled";
                };
 
                        compatible = "nvidia,tegra20-dsi";
                        reg = <0x54300000 0x00040000>;
                        clocks = <&tegra_car TEGRA20_CLK_DSI>;
+                       resets = <&tegra_car 48>;
+                       reset-names = "dsi";
                        status = "disabled";
                };
        };
                compatible = "nvidia,tegra20-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        apbdma: dma {
                             <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_APBDMA>;
+               resets = <&tegra_car 34>;
+               reset-names = "dma";
+               #dma-cells = <1>;
        };
 
        ahb {
                compatible = "nvidia,tegra20-ac97";
                reg = <0x70002000 0x200>;
                interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 12>;
                clocks = <&tegra_car TEGRA20_CLK_AC97>;
+               resets = <&tegra_car 3>;
+               reset-names = "ac97";
+               dmas = <&apbdma 12>, <&apbdma 12>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-i2s";
                reg = <0x70002800 0x200>;
                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 2>;
                clocks = <&tegra_car TEGRA20_CLK_I2S1>;
+               resets = <&tegra_car 11>;
+               reset-names = "i2s";
+               dmas = <&apbdma 2>, <&apbdma 2>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-i2s";
                reg = <0x70002a00 0x200>;
                interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 1>;
                clocks = <&tegra_car TEGRA20_CLK_I2S2>;
+               resets = <&tegra_car 18>;
+               reset-names = "i2s";
+               dmas = <&apbdma 1>, <&apbdma 1>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 8>;
                clocks = <&tegra_car TEGRA20_CLK_UARTA>;
+               resets = <&tegra_car 6>;
+               reset-names = "serial";
+               dmas = <&apbdma 8>, <&apbdma 8>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 9>;
                clocks = <&tegra_car TEGRA20_CLK_UARTB>;
+               resets = <&tegra_car 7>;
+               reset-names = "serial";
+               dmas = <&apbdma 9>, <&apbdma 9>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 10>;
                clocks = <&tegra_car TEGRA20_CLK_UARTC>;
+               resets = <&tegra_car 55>;
+               reset-names = "serial";
+               dmas = <&apbdma 10>, <&apbdma 10>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 19>;
                clocks = <&tegra_car TEGRA20_CLK_UARTD>;
+               resets = <&tegra_car 65>;
+               reset-names = "serial";
+               dmas = <&apbdma 19>, <&apbdma 19>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 20>;
                clocks = <&tegra_car TEGRA20_CLK_UARTE>;
+               resets = <&tegra_car 66>;
+               reset-names = "serial";
+               dmas = <&apbdma 20>, <&apbdma 20>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x7000a000 0x100>;
                #pwm-cells = <2>;
                clocks = <&tegra_car TEGRA20_CLK_PWM>;
+               resets = <&tegra_car 17>;
+               reset-names = "pwm";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA20_CLK_I2C1>,
                         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 12>;
+               reset-names = "i2c";
+               dmas = <&apbdma 21>, <&apbdma 21>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-sflash";
                reg = <0x7000c380 0x80>;
                interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 11>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA20_CLK_SPI>;
+               resets = <&tegra_car 43>;
+               reset-names = "spi";
+               dmas = <&apbdma 11>, <&apbdma 11>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA20_CLK_I2C2>,
                         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 54>;
+               reset-names = "i2c";
+               dmas = <&apbdma 22>, <&apbdma 22>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA20_CLK_I2C3>,
                         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 67>;
+               reset-names = "i2c";
+               dmas = <&apbdma 23>, <&apbdma 23>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA20_CLK_DVC>,
                         <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 47>;
+               reset-names = "i2c";
+               dmas = <&apbdma 24>, <&apbdma 24>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-slink";
                reg = <0x7000d400 0x200>;
                interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 15>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA20_CLK_SBC1>;
+               resets = <&tegra_car 41>;
+               reset-names = "spi";
+               dmas = <&apbdma 15>, <&apbdma 15>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-slink";
                reg = <0x7000d600 0x200>;
                interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 16>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA20_CLK_SBC2>;
+               resets = <&tegra_car 44>;
+               reset-names = "spi";
+               dmas = <&apbdma 16>, <&apbdma 16>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-slink";
                reg = <0x7000d800 0x200>;
                interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 17>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA20_CLK_SBC3>;
+               resets = <&tegra_car 46>;
+               reset-names = "spi";
+               dmas = <&apbdma 17>, <&apbdma 17>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra20-slink";
                reg = <0x7000da00 0x200>;
                interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 18>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA20_CLK_SBC4>;
+               resets = <&tegra_car 68>;
+               reset-names = "spi";
+               dmas = <&apbdma 18>, <&apbdma 18>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x7000e200 0x100>;
                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_KBC>;
+               resets = <&tegra_car 36>;
+               reset-names = "kbc";
                status = "disabled";
        };
 
 
                clocks = <&tegra_car TEGRA20_CLK_PEX>,
                         <&tegra_car TEGRA20_CLK_AFI>,
-                        <&tegra_car TEGRA20_CLK_PCIE_XCLK>,
                         <&tegra_car TEGRA20_CLK_PLL_E>;
-               clock-names = "pex", "afi", "pcie_xclk", "pll_e";
+               clock-names = "pex", "afi", "pll_e";
+               resets = <&tegra_car 70>,
+                        <&tegra_car 72>,
+                        <&tegra_car 74>;
+               reset-names = "pex", "afi", "pcie_x";
                status = "disabled";
 
                pci@1,0 {
                phy_type = "utmi";
                nvidia,has-legacy-mode;
                clocks = <&tegra_car TEGRA20_CLK_USBD>;
+               resets = <&tegra_car 22>;
+               reset-names = "usb";
                nvidia,needs-double-reset;
                nvidia,phy = <&phy1>;
                status = "disabled";
                interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "ulpi";
                clocks = <&tegra_car TEGRA20_CLK_USB2>;
+               resets = <&tegra_car 58>;
+               reset-names = "usb";
                nvidia,phy = <&phy2>;
                status = "disabled";
        };
                interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "utmi";
                clocks = <&tegra_car TEGRA20_CLK_USB3>;
+               resets = <&tegra_car 59>;
+               reset-names = "usb";
                nvidia,phy = <&phy3>;
                status = "disabled";
        };
                reg = <0xc8000000 0x200>;
                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_SDMMC1>;
+               resets = <&tegra_car 14>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0xc8000200 0x200>;
                interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_SDMMC2>;
+               resets = <&tegra_car 9>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0xc8000400 0x200>;
                interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_SDMMC3>;
+               resets = <&tegra_car 69>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0xc8000600 0x200>;
                interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA20_CLK_SDMMC4>;
+               resets = <&tegra_car 15>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
index 2bd55cfd88adcb4d3e525ae45ea471a6376a8e34..31259b09e7ccc3f97b4574deaf56f65a096ed8d9 100644 (file)
 
                clocks = <&tegra_car TEGRA30_CLK_PCIE>,
                         <&tegra_car TEGRA30_CLK_AFI>,
-                        <&tegra_car TEGRA30_CLK_PCIEX>,
                         <&tegra_car TEGRA30_CLK_PLL_E>,
                         <&tegra_car TEGRA30_CLK_CML0>;
-               clock-names = "pex", "afi", "pcie_xclk", "pll_e", "cml";
+               clock-names = "pex", "afi", "pll_e", "cml";
+               resets = <&tegra_car 70>,
+                        <&tegra_car 72>,
+                        <&tegra_car 74>;
+               reset-names = "pex", "afi", "pcie_x";
                status = "disabled";
 
                pci@1,0 {
@@ -92,6 +95,8 @@
                interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
                             <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
                clocks = <&tegra_car TEGRA30_CLK_HOST1X>;
+               resets = <&tegra_car 28>;
+               reset-names = "host1x";
 
                #address-cells = <1>;
                #size-cells = <1>;
                        reg = <0x54040000 0x00040000>;
                        interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_MPE>;
+                       resets = <&tegra_car 60>;
+                       reset-names = "mpe";
                };
 
                vi {
                        reg = <0x54080000 0x00040000>;
                        interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_VI>;
+                       resets = <&tegra_car 20>;
+                       reset-names = "vi";
                };
 
                epp {
                        reg = <0x540c0000 0x00040000>;
                        interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_EPP>;
+                       resets = <&tegra_car 19>;
+                       reset-names = "epp";
                };
 
                isp {
                        reg = <0x54100000 0x00040000>;
                        interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_ISP>;
+                       resets = <&tegra_car 23>;
+                       reset-names = "isp";
                };
 
                gr2d {
                        compatible = "nvidia,tegra30-gr2d";
                        reg = <0x54140000 0x00040000>;
                        interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       resets = <&tegra_car 21>;
+                       reset-names = "2d";
                        clocks = <&tegra_car TEGRA30_CLK_GR2D>;
                };
 
                        clocks = <&tegra_car TEGRA30_CLK_GR3D
                                  &tegra_car TEGRA30_CLK_GR3D2>;
                        clock-names = "3d", "3d2";
+                       resets = <&tegra_car 24>,
+                                <&tegra_car 98>;
+                       reset-names = "3d", "3d2";
                };
 
                dc@54200000 {
                        interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_DISP1>,
                                 <&tegra_car TEGRA30_CLK_PLL_P>;
-                       clock-names = "disp1", "parent";
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 27>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
                        interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&tegra_car TEGRA30_CLK_DISP2>,
                                 <&tegra_car TEGRA30_CLK_PLL_P>;
-                       clock-names = "disp2", "parent";
+                       clock-names = "dc", "parent";
+                       resets = <&tegra_car 26>;
+                       reset-names = "dc";
 
                        rgb {
                                status = "disabled";
                        clocks = <&tegra_car TEGRA30_CLK_HDMI>,
                                 <&tegra_car TEGRA30_CLK_PLL_D2_OUT0>;
                        clock-names = "hdmi", "parent";
+                       resets = <&tegra_car 51>;
+                       reset-names = "hdmi";
                        status = "disabled";
                };
 
                        compatible = "nvidia,tegra30-dsi";
                        reg = <0x54300000 0x00040000>;
                        clocks = <&tegra_car TEGRA30_CLK_DSIA>;
+                       resets = <&tegra_car 48>;
+                       reset-names = "dsi";
                        status = "disabled";
                };
        };
                compatible = "nvidia,tegra30-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        apbdma: dma {
                             <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_APBDMA>;
+               resets = <&tegra_car 34>;
+               reset-names = "dma";
+               #dma-cells = <1>;
        };
 
        ahb: ahb {
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 8>;
                clocks = <&tegra_car TEGRA30_CLK_UARTA>;
+               resets = <&tegra_car 6>;
+               reset-names = "serial";
+               dmas = <&apbdma 8>, <&apbdma 8>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 9>;
                clocks = <&tegra_car TEGRA30_CLK_UARTB>;
+               resets = <&tegra_car 7>;
+               reset-names = "serial";
+               dmas = <&apbdma 9>, <&apbdma 9>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 10>;
                clocks = <&tegra_car TEGRA30_CLK_UARTC>;
+               resets = <&tegra_car 55>;
+               reset-names = "serial";
+               dmas = <&apbdma 10>, <&apbdma 10>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 19>;
                clocks = <&tegra_car TEGRA30_CLK_UARTD>;
+               resets = <&tegra_car 65>;
+               reset-names = "serial";
+               dmas = <&apbdma 19>, <&apbdma 19>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 20>;
                clocks = <&tegra_car TEGRA30_CLK_UARTE>;
+               resets = <&tegra_car 66>;
+               reset-names = "serial";
+               dmas = <&apbdma 20>, <&apbdma 20>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x7000a000 0x100>;
                #pwm-cells = <2>;
                clocks = <&tegra_car TEGRA30_CLK_PWM>;
+               resets = <&tegra_car 17>;
+               reset-names = "pwm";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA30_CLK_I2C1>,
                         <&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 12>;
+               reset-names = "i2c";
+               dmas = <&apbdma 21>, <&apbdma 21>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA30_CLK_I2C2>,
                         <&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 54>;
+               reset-names = "i2c";
+               dmas = <&apbdma 22>, <&apbdma 22>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA30_CLK_I2C3>,
                         <&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 67>;
+               reset-names = "i2c";
+               dmas = <&apbdma 23>, <&apbdma 23>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_I2C4>,
                         <&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
+               resets = <&tegra_car 103>;
+               reset-names = "i2c";
                clock-names = "div-clk", "fast-clk";
+               dmas = <&apbdma 26>, <&apbdma 26>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                clocks = <&tegra_car TEGRA30_CLK_I2C5>,
                         <&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
                clock-names = "div-clk", "fast-clk";
+               resets = <&tegra_car 47>;
+               reset-names = "i2c";
+               dmas = <&apbdma 24>, <&apbdma 24>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000d400 0x200>;
                interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 15>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC1>;
+               resets = <&tegra_car 41>;
+               reset-names = "spi";
+               dmas = <&apbdma 15>, <&apbdma 15>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000d600 0x200>;
                interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 16>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC2>;
+               resets = <&tegra_car 44>;
+               reset-names = "spi";
+               dmas = <&apbdma 16>, <&apbdma 16>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000d800 0x200>;
                interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 17>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC3>;
+               resets = <&tegra_car 46>;
+               reset-names = "spi";
+               dmas = <&apbdma 17>, <&apbdma 17>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000da00 0x200>;
                interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 18>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC4>;
+               resets = <&tegra_car 68>;
+               reset-names = "spi";
+               dmas = <&apbdma 18>, <&apbdma 18>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000dc00 0x200>;
                interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 27>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC5>;
+               resets = <&tegra_car 104>;
+               reset-names = "spi";
+               dmas = <&apbdma 27>, <&apbdma 27>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
                reg = <0x7000de00 0x200>;
                interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 28>;
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&tegra_car TEGRA30_CLK_SBC6>;
+               resets = <&tegra_car 106>;
+               reset-names = "spi";
+               dmas = <&apbdma 28>, <&apbdma 28>;
+               dma-names = "rx", "tx";
                status = "disabled";
        };
 
                reg = <0x7000e200 0x100>;
                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_KBC>;
+               resets = <&tegra_car 36>;
+               reset-names = "kbc";
                status = "disabled";
        };
 
                reg = <0x70080000 0x200
                       0x70080200 0x100>;
                interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
-               nvidia,dma-request-selector = <&apbdma 1>;
                clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
-                        <&tegra_car TEGRA30_CLK_APBIF>,
-                        <&tegra_car TEGRA30_CLK_I2S0>,
-                        <&tegra_car TEGRA30_CLK_I2S1>,
-                        <&tegra_car TEGRA30_CLK_I2S2>,
-                        <&tegra_car TEGRA30_CLK_I2S3>,
-                        <&tegra_car TEGRA30_CLK_I2S4>,
-                        <&tegra_car TEGRA30_CLK_DAM0>,
-                        <&tegra_car TEGRA30_CLK_DAM1>,
-                        <&tegra_car TEGRA30_CLK_DAM2>,
-                        <&tegra_car TEGRA30_CLK_SPDIF_IN>;
-               clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+                        <&tegra_car TEGRA30_CLK_APBIF>;
+               clock-names = "d_audio", "apbif";
+               resets = <&tegra_car 106>, /* d_audio */
+                        <&tegra_car 107>, /* apbif */
+                        <&tegra_car 30>,  /* i2s0 */
+                        <&tegra_car 11>,  /* i2s1 */
+                        <&tegra_car 18>,  /* i2s2 */
+                        <&tegra_car 101>, /* i2s3 */
+                        <&tegra_car 102>, /* i2s4 */
+                        <&tegra_car 108>, /* dam0 */
+                        <&tegra_car 109>, /* dam1 */
+                        <&tegra_car 110>, /* dam2 */
+                        <&tegra_car 10>;  /* spdif */
+               reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
                              "i2s3", "i2s4", "dam0", "dam1", "dam2",
-                             "spdif_in";
+                             "spdif";
+               dmas = <&apbdma 1>, <&apbdma 1>,
+                      <&apbdma 2>, <&apbdma 2>,
+                      <&apbdma 3>, <&apbdma 3>,
+                      <&apbdma 4>, <&apbdma 4>;
+               dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2",
+                           "rx3", "tx3";
                ranges;
                #address-cells = <1>;
                #size-cells = <1>;
                        reg = <0x70080300 0x100>;
                        nvidia,ahub-cif-ids = <4 4>;
                        clocks = <&tegra_car TEGRA30_CLK_I2S0>;
+                       resets = <&tegra_car 30>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080400 0x100>;
                        nvidia,ahub-cif-ids = <5 5>;
                        clocks = <&tegra_car TEGRA30_CLK_I2S1>;
+                       resets = <&tegra_car 11>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080500 0x100>;
                        nvidia,ahub-cif-ids = <6 6>;
                        clocks = <&tegra_car TEGRA30_CLK_I2S2>;
+                       resets = <&tegra_car 18>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080600 0x100>;
                        nvidia,ahub-cif-ids = <7 7>;
                        clocks = <&tegra_car TEGRA30_CLK_I2S3>;
+                       resets = <&tegra_car 101>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
 
                        reg = <0x70080700 0x100>;
                        nvidia,ahub-cif-ids = <8 8>;
                        clocks = <&tegra_car TEGRA30_CLK_I2S4>;
+                       resets = <&tegra_car 102>;
+                       reset-names = "i2s";
                        status = "disabled";
                };
        };
                reg = <0x78000000 0x200>;
                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_SDMMC1>;
+               resets = <&tegra_car 14>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0x78000200 0x200>;
                interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_SDMMC2>;
+               resets = <&tegra_car 9>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0x78000400 0x200>;
                interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_SDMMC3>;
+               resets = <&tegra_car 69>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                reg = <0x78000600 0x200>;
                interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA30_CLK_SDMMC4>;
+               resets = <&tegra_car 15>;
+               reset-names = "sdhci";
                status = "disabled";
        };
 
                interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "utmi";
                clocks = <&tegra_car TEGRA30_CLK_USBD>;
+               resets = <&tegra_car 22>;
+               reset-names = "usb";
                nvidia,needs-double-reset;
                nvidia,phy = <&phy1>;
                status = "disabled";
                interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "ulpi";
                clocks = <&tegra_car TEGRA30_CLK_USB2>;
+               resets = <&tegra_car 58>;
+               reset-names = "usb";
                nvidia,phy = <&phy2>;
                status = "disabled";
        };
                interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
                phy_type = "utmi";
                clocks = <&tegra_car TEGRA30_CLK_USB3>;
+               resets = <&tegra_car 59>;
+               reset-names = "usb";
                nvidia,phy = <&phy3>;
                status = "disabled";
        };
index 64205d453260d12ec1e2d43c424fab1c3251788a..71e5fc7cfb18f489f3adadb20c6f8049421fb079 100644 (file)
@@ -58,7 +58,7 @@
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index f3d96d9325737fba399dc5e6613d223e03fcb7a1..be068db960ee0006ac1aa25a4e69b95265404844 100644 (file)
@@ -701,7 +701,7 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index 3c597c222ef278a8eb170a4169b5e54dcc158ac0..fbeb39c869e9fdcedace1d61688247c14141cab3 100644 (file)
@@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  */
 #define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_cache(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap                                __arm_iounmap
 
index 6976b03e521369bddedfe6968cfa221c6705c552..8756e4bcdba0609ff789a4f1efaa551faa39ed98 100644 (file)
@@ -347,7 +347,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
+                                       && pfn_valid(__pa(kaddr) >> PAGE_SHIFT) )
 
 #endif
 
index 75579a9d6f76cba3cc84ad61d01ed103269378bd..3759cacdd7f8601322b98ffed6598d97ee8bd016 100644 (file)
@@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
        return __set_phys_to_machine(pfn, mfn);
 }
 
-#define xen_remap(cookie, size) ioremap_cached((cookie), (size));
+#define xen_remap(cookie, size) ioremap_cache((cookie), (size));
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
index 7940241f0576b0db1cc0a749e449c7faf492518a..6eda3bf85c52123dc75fb04fe46f0eb197c78d62 100644 (file)
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
 
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+static const char *handler[]= {
+       "prefetch abort",
+       "data abort",
+       "address exception",
+       "interrupt",
+       "undefined instruction",
+};
 
 void *vectors_page;
 
index 9ee78f7b4990751386cf7f29337ec075297349dd..782f6c71fa0a6c761269cfc4b74fc6cdd0839e75 100644 (file)
@@ -96,11 +96,12 @@ static struct irqaction footbridge_timer_irq = {
 void __init footbridge_timer_init(void)
 {
        struct clock_event_device *ce = &ckevt_dc21285;
+       unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
 
-       clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+       clocksource_register_hz(&cksrc_dc21285, rate);
 
        setup_irq(ce->irq, &footbridge_timer_irq);
 
        ce->cpumask = cpumask_of(smp_processor_id());
-       clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
+       clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
 }
index c186891230233fe617161531b5f637246b4e0da7..8ea87bd45c330abd37df9eba0b30b8f4efc8dc47 100644 (file)
@@ -483,7 +483,7 @@ static struct platform_device lcdc0_device = {
        .id             = 0,
        .dev    = {
                .platform_data  = &lcdc0_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -580,7 +580,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index fe689b7fdc9e715ecd724edcc746913010627fb4..bc40b853ffd3cff2204bdfdc283863a9577f51bc 100644 (file)
@@ -334,7 +334,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index af06753eb8092500de41707ac68216bd3ed244a0..e721d2ccceaef8c1d57bd0d671fa097a2c0f539a 100644 (file)
@@ -409,7 +409,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -499,7 +499,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index 09e740f58b274184f0cd22b282def431d037b6d9..15c09294effa30dbb3c2ef662e61788ea140ba96 100644 (file)
@@ -14,6 +14,8 @@ config ARCH_TEGRA
        select MIGHT_HAVE_CACHE_L2X0
        select MIGHT_HAVE_PCI
        select PINCTRL
+       select ARCH_HAS_RESET_CONTROLLER
+       select RESET_CONTROLLER
        select SOC_BUS
        select SPARSE_IRQ
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
index 85d28e756bb77e8d3b4b66342608e136716288b3..3d0c537d9b945af08de57ecaa354169674fdc33e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/reset.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/clk/tegra.h>
 #include "fuse.h"
 #include "iomap.h"
 
+#define DPD_SAMPLE             0x020
+#define  DPD_SAMPLE_ENABLE     (1 << 0)
+#define  DPD_SAMPLE_DISABLE    (0 << 0)
+
 #define PWRGATE_TOGGLE         0x30
 #define  PWRGATE_TOGGLE_START  (1 << 8)
 
 
 #define PWRGATE_STATUS         0x38
 
+#define IO_DPD_REQ             0x1b8
+#define  IO_DPD_REQ_CODE_IDLE  (0 << 30)
+#define  IO_DPD_REQ_CODE_OFF   (1 << 30)
+#define  IO_DPD_REQ_CODE_ON    (2 << 30)
+#define  IO_DPD_REQ_CODE_MASK  (3 << 30)
+
+#define IO_DPD_STATUS          0x1bc
+#define IO_DPD2_REQ            0x1c0
+#define IO_DPD2_STATUS         0x1c4
+#define SEL_DPD_TIM            0x1c8
+
+#define GPU_RG_CNTRL           0x2d4
+
 static int tegra_num_powerdomains;
 static int tegra_num_cpu_domains;
 static const u8 *tegra_cpu_domains;
@@ -58,6 +76,13 @@ static const u8 tegra114_cpu_domains[] = {
        TEGRA_POWERGATE_CPU3,
 };
 
+static const u8 tegra124_cpu_domains[] = {
+       TEGRA_POWERGATE_CPU0,
+       TEGRA_POWERGATE_CPU1,
+       TEGRA_POWERGATE_CPU2,
+       TEGRA_POWERGATE_CPU3,
+};
+
 static DEFINE_SPINLOCK(tegra_powergate_lock);
 
 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
@@ -108,6 +133,7 @@ int tegra_powergate_power_off(int id)
 
        return tegra_powergate_set(id, false);
 }
+EXPORT_SYMBOL(tegra_powergate_power_off);
 
 int tegra_powergate_is_powered(int id)
 {
@@ -127,13 +153,24 @@ int tegra_powergate_remove_clamping(int id)
        if (id < 0 || id >= tegra_num_powerdomains)
                return -EINVAL;
 
+       /*
+        * The Tegra124 GPU has a separate register (with different semantics)
+        * to remove clamps.
+        */
+       if (tegra_chip_id == TEGRA124) {
+               if (id == TEGRA_POWERGATE_3D) {
+                       pmc_write(0, GPU_RG_CNTRL);
+                       return 0;
+               }
+       }
+
        /*
         * Tegra 2 has a bug where PCIE and VDE clamping masks are
         * swapped relatively to the partition ids
         */
-       if (id ==  TEGRA_POWERGATE_VDEC)
+       if (id == TEGRA_POWERGATE_VDEC)
                mask = (1 << TEGRA_POWERGATE_PCIE);
-       else if (id == TEGRA_POWERGATE_PCIE)
+       else if (id == TEGRA_POWERGATE_PCIE)
                mask = (1 << TEGRA_POWERGATE_VDEC);
        else
                mask = (1 << id);
@@ -142,13 +179,15 @@ int tegra_powergate_remove_clamping(int id)
 
        return 0;
 }
+EXPORT_SYMBOL(tegra_powergate_remove_clamping);
 
 /* Must be called with clk disabled, and returns with clk enabled */
-int tegra_powergate_sequence_power_up(int id, struct clk *clk)
+int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+                                       struct reset_control *rst)
 {
        int ret;
 
-       tegra_periph_reset_assert(clk);
+       reset_control_assert(rst);
 
        ret = tegra_powergate_power_on(id);
        if (ret)
@@ -165,7 +204,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk)
                goto err_clamp;
 
        udelay(10);
-       tegra_periph_reset_deassert(clk);
+       reset_control_deassert(rst);
 
        return 0;
 
@@ -202,6 +241,11 @@ int __init tegra_powergate_init(void)
                tegra_num_cpu_domains = 4;
                tegra_cpu_domains = tegra114_cpu_domains;
                break;
+       case TEGRA124:
+               tegra_num_powerdomains = 25;
+               tegra_num_cpu_domains = 4;
+               tegra_cpu_domains = tegra124_cpu_domains;
+               break;
        default:
                /* Unknown Tegra variant. Disable powergating */
                tegra_num_powerdomains = 0;
@@ -243,12 +287,36 @@ static const char * const powergate_name_t30[] = {
 };
 
 static const char * const powergate_name_t114[] = {
-       [TEGRA_POWERGATE_CPU]   = "cpu0",
+       [TEGRA_POWERGATE_CPU]   = "crail",
+       [TEGRA_POWERGATE_3D]    = "3d",
+       [TEGRA_POWERGATE_VENC]  = "venc",
+       [TEGRA_POWERGATE_VDEC]  = "vdec",
+       [TEGRA_POWERGATE_MPE]   = "mpe",
+       [TEGRA_POWERGATE_HEG]   = "heg",
+       [TEGRA_POWERGATE_CPU1]  = "cpu1",
+       [TEGRA_POWERGATE_CPU2]  = "cpu2",
+       [TEGRA_POWERGATE_CPU3]  = "cpu3",
+       [TEGRA_POWERGATE_CELP]  = "celp",
+       [TEGRA_POWERGATE_CPU0]  = "cpu0",
+       [TEGRA_POWERGATE_C0NC]  = "c0nc",
+       [TEGRA_POWERGATE_C1NC]  = "c1nc",
+       [TEGRA_POWERGATE_DIS]   = "dis",
+       [TEGRA_POWERGATE_DISB]  = "disb",
+       [TEGRA_POWERGATE_XUSBA] = "xusba",
+       [TEGRA_POWERGATE_XUSBB] = "xusbb",
+       [TEGRA_POWERGATE_XUSBC] = "xusbc",
+};
+
+static const char * const powergate_name_t124[] = {
+       [TEGRA_POWERGATE_CPU]   = "crail",
        [TEGRA_POWERGATE_3D]    = "3d",
        [TEGRA_POWERGATE_VENC]  = "venc",
+       [TEGRA_POWERGATE_PCIE]  = "pcie",
        [TEGRA_POWERGATE_VDEC]  = "vdec",
+       [TEGRA_POWERGATE_L2]    = "l2",
        [TEGRA_POWERGATE_MPE]   = "mpe",
        [TEGRA_POWERGATE_HEG]   = "heg",
+       [TEGRA_POWERGATE_SATA]  = "sata",
        [TEGRA_POWERGATE_CPU1]  = "cpu1",
        [TEGRA_POWERGATE_CPU2]  = "cpu2",
        [TEGRA_POWERGATE_CPU3]  = "cpu3",
@@ -256,11 +324,14 @@ static const char * const powergate_name_t114[] = {
        [TEGRA_POWERGATE_CPU0]  = "cpu0",
        [TEGRA_POWERGATE_C0NC]  = "c0nc",
        [TEGRA_POWERGATE_C1NC]  = "c1nc",
+       [TEGRA_POWERGATE_SOR]   = "sor",
        [TEGRA_POWERGATE_DIS]   = "dis",
        [TEGRA_POWERGATE_DISB]  = "disb",
        [TEGRA_POWERGATE_XUSBA] = "xusba",
        [TEGRA_POWERGATE_XUSBB] = "xusbb",
        [TEGRA_POWERGATE_XUSBC] = "xusbc",
+       [TEGRA_POWERGATE_VIC]   = "vic",
+       [TEGRA_POWERGATE_IRAM]  = "iram",
 };
 
 static int powergate_show(struct seq_file *s, void *data)
@@ -307,6 +378,9 @@ int __init tegra_powergate_debugfs_init(void)
        case TEGRA114:
                powergate_name = powergate_name_t114;
                break;
+       case TEGRA124:
+               powergate_name = powergate_name_t124;
+               break;
        }
 
        if (powergate_name) {
@@ -320,3 +394,120 @@ int __init tegra_powergate_debugfs_init(void)
 }
 
 #endif
+
+static int tegra_io_rail_prepare(int id, unsigned long *request,
+                                unsigned long *status, unsigned int *bit)
+{
+       unsigned long rate, value;
+       struct clk *clk;
+
+       *bit = id % 32;
+
+       /*
+        * There are two sets of 30 bits to select IO rails, but bits 30 and
+        * 31 are control bits rather than IO rail selection bits.
+        */
+       if (id > 63 || *bit == 30 || *bit == 31)
+               return -EINVAL;
+
+       if (id < 32) {
+               *status = IO_DPD_STATUS;
+               *request = IO_DPD_REQ;
+       } else {
+               *status = IO_DPD2_STATUS;
+               *request = IO_DPD2_REQ;
+       }
+
+       clk = clk_get_sys(NULL, "pclk");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rate = clk_get_rate(clk);
+       clk_put(clk);
+
+       pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
+
+       /* must be at least 200 ns, in APB (PCLK) clock cycles */
+       value = DIV_ROUND_UP(1000000000, rate);
+       value = DIV_ROUND_UP(200, value);
+       pmc_write(value, SEL_DPD_TIM);
+
+       return 0;
+}
+
+static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
+                             unsigned long val, unsigned long timeout)
+{
+       unsigned long value;
+
+       timeout = jiffies + msecs_to_jiffies(timeout);
+
+       while (time_after(timeout, jiffies)) {
+               value = pmc_read(offset);
+               if ((value & mask) == val)
+                       return 0;
+
+               usleep_range(250, 1000);
+       }
+
+       return -ETIMEDOUT;
+}
+
+static void tegra_io_rail_unprepare(void)
+{
+       pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
+}
+
+int tegra_io_rail_power_on(int id)
+{
+       unsigned long request, status, value;
+       unsigned int bit, mask;
+       int err;
+
+       err = tegra_io_rail_prepare(id, &request, &status, &bit);
+       if (err < 0)
+               return err;
+
+       mask = 1 << bit;
+
+       value = pmc_read(request);
+       value |= mask;
+       value &= ~IO_DPD_REQ_CODE_MASK;
+       value |= IO_DPD_REQ_CODE_OFF;
+       pmc_write(value, request);
+
+       err = tegra_io_rail_poll(status, mask, 0, 250);
+       if (err < 0)
+               return err;
+
+       tegra_io_rail_unprepare();
+
+       return 0;
+}
+
+int tegra_io_rail_power_off(int id)
+{
+       unsigned long request, status, value;
+       unsigned int bit, mask;
+       int err;
+
+       err = tegra_io_rail_prepare(id, &request, &status, &bit);
+       if (err < 0)
+               return err;
+
+       mask = 1 << bit;
+
+       value = pmc_read(request);
+       value |= mask;
+       value &= ~IO_DPD_REQ_CODE_MASK;
+       value |= IO_DPD_REQ_CODE_ON;
+       pmc_write(value, request);
+
+       err = tegra_io_rail_poll(status, mask, mask, 250);
+       if (err < 0)
+               return err;
+
+       tegra_io_rail_unprepare();
+
+       return 0;
+}
index 6d5ba9afb16a4409d50dbdbc03d08c83642df9b4..3387e60e4ea381c579725774ebab8d587eeded0c 100644 (file)
@@ -175,16 +175,16 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
                unsigned long i;
                if (cache_is_vipt_nonaliasing()) {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_atomic(page);
+                               void *addr = kmap_atomic(page + i);
                                __cpuc_flush_dcache_area(addr, PAGE_SIZE);
                                kunmap_atomic(addr);
                        }
                } else {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_high_get(page);
+                               void *addr = kmap_high_get(page + i);
                                if (addr) {
                                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
-                                       kunmap_high(page);
+                                       kunmap_high(page + i);
                                }
                        }
                }
index f0e2784e7ccacd6c6d0856ce87d1f1d26e81c083..2f9b751878ba86bf6cc32cfdadd9b7847ad158d5 100644 (file)
@@ -125,42 +125,38 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma
 void mark_rodata_ro(void);
 #endif
 
-#ifdef CONFIG_PA8X00
-/* Only pa8800, pa8900 needs this */
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
 
-void kunmap_parisc(void *addr);
-
 static inline void *kmap(struct page *page)
 {
        might_sleep();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void kunmap(struct page *page)
 {
-       kunmap_parisc(page_address(page));
+       flush_kernel_dcache_page_addr(page_address(page));
 }
 
 static inline void *kmap_atomic(struct page *page)
 {
        pagefault_disable();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void __kunmap_atomic(void *addr)
 {
-       kunmap_parisc(addr);
+       flush_kernel_dcache_page_addr(addr);
        pagefault_enable();
 }
 
 #define kmap_atomic_prot(page, prot)   kmap_atomic(page)
 #define kmap_atomic_pfn(pfn)   kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
-#endif
 
 #endif /* _PARISC_CACHEFLUSH_H */
 
index b7adb2ac049c0e6b72817dee3df92d124c612e42..c53fc63149e8312437fe4109e8070495ba39d90a 100644 (file)
@@ -28,9 +28,8 @@ struct page;
 
 void clear_page_asm(void *page);
 void copy_page_asm(void *to, void *from);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *pg);
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-                          struct page *pg);
+#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
+#define copy_user_page(vto, vfrom, vaddr, page) copy_page_asm(vto, vfrom)
 
 /* #define CONFIG_PARISC_TMPALIAS */
 
index c035673209f732f0850aaa4dc98d2d49eee3b74c..a72545554a3154c254eace0648a769d4df645b25 100644 (file)
@@ -388,41 +388,6 @@ void flush_kernel_dcache_page_addr(void *addr)
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
-void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
-{
-       clear_page_asm(vto);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(clear_user_page);
-
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-       struct page *pg)
-{
-       /* Copy using kernel mapping.  No coherency is needed
-          (all in kmap/kunmap) on machines that don't support
-          non-equivalent aliasing.  However, the `from' page
-          needs to be flushed before it can be accessed through
-          the kernel mapping. */
-       preempt_disable();
-       flush_dcache_page_asm(__pa(vfrom), vaddr);
-       preempt_enable();
-       copy_page_asm(vto, vfrom);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(copy_user_page);
-
-#ifdef CONFIG_PA8X00
-
-void kunmap_parisc(void *addr)
-{
-       if (parisc_requires_coherency())
-               flush_kernel_dcache_page_addr(addr);
-}
-EXPORT_SYMBOL(kunmap_parisc);
-#endif
-
 void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 {
        unsigned long flags;
index 4177b62240c2440ff19f6089cb84cd5b9e0d27a0..a618dfc13e4c8f88a5ff70b88325fd39675c9e8a 100644 (file)
@@ -58,7 +58,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     // 66 MHz ips bus
                        reg = <0xA000 0x1000>;
                };
 
+               // disable USB1 port
+               // TODO:
+               // correct pinmux config and fix USB3320 ulpi dependency
+               // before re-enabling it
                usb@3000 {
                        compatible = "fsl,mpc5121-usb2-dr";
                        reg = <0x3000 0x400>;
                        interrupts = <43 0x8>;
                        dr_mode = "host";
                        phy_type = "ulpi";
+                       status = "disabled";
                };
 
                // 5125 PSCs are not 52xx or 5121 PSC compatible
index 894662a5d4d5c5aa25f43e30653609d80d901774..243ce69ad685ffd335041537e6f0b33b0aafe3df 100644 (file)
@@ -284,7 +284,7 @@ do_kvm_##n:                                                         \
        subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
        beq-    1f;                                                        \
        ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
-1:     cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
+1:     cmpdi   cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace  */ \
        blt+    cr1,3f;                 /* abort if it is               */ \
        li      r1,(n);                 /* will be reloaded later       */ \
        sth     r1,PACA_TRAP_SAVE(r13);                                    \
index 5f1b1e3c21374d5a1833ed00c9af9d5c06a35123..8296381ae43294e679976f6a82d3bb936d64921f 100644 (file)
@@ -4,13 +4,18 @@
 #ifdef __KERNEL__
 
 /*
- * The PowerPC can do unaligned accesses itself in big endian mode.
+ * The PowerPC can do unaligned accesses itself based on its endian mode.
  */
 #include <linux/unaligned/access_ok.h>
 #include <linux/unaligned/generic.h>
 
+#ifdef __LITTLE_ENDIAN__
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+#else
 #define get_unaligned  __get_unaligned_be
 #define put_unaligned  __put_unaligned_be
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
index 2ae41aba40530f7facf916f6ce101ad3196a7363..4f0946de2d5c917540f6f51a50c13640011fea8c 100644 (file)
@@ -80,6 +80,7 @@ END_FTR_SECTION(0, 1)
         * of the function that the cpu should jump to to continue
         * initialization.
         */
+       .balign 8
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -470,6 +471,7 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4:     /* Now copy the rest of the kernel up to _end */
index cb64a6e1dc5186918b4d2052e52e961cfb14eedb..078145acf7fb867dca6278f776a935ba0b2ecf25 100644 (file)
@@ -1986,19 +1986,23 @@ static void __init prom_init_stdout(void)
        /* Get the full OF pathname of the stdout device */
        memset(path, 0, 256);
        call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
-       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
-       val = cpu_to_be32(stdout_node);
-       prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
-                    &val, sizeof(val));
        prom_printf("OF stdout device is: %s\n", of_stdout_device);
        prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
                     path, strlen(path) + 1);
 
-       /* If it's a display, note it */
-       memset(type, 0, sizeof(type));
-       prom_getprop(stdout_node, "device_type", type, sizeof(type));
-       if (strcmp(type, "display") == 0)
-               prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       /* instance-to-package fails on PA-Semi */
+       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
+       if (stdout_node != PROM_ERROR) {
+               val = cpu_to_be32(stdout_node);
+               prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
+                            &val, sizeof(val));
+
+               /* If it's a display, note it */
+               memset(type, 0, sizeof(type));
+               prom_getprop(stdout_node, "device_type", type, sizeof(type));
+               if (strcmp(type, "display") == 0)
+                       prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       }
 }
 
 static int __init prom_find_machine_type(void)
index d73a5901490018486fed19115fce46d88084f701..596a285c07554d65dfd561367a52ffed47aba55d 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define sLd sld                /* Shift towards low-numbered address. */
+#define sHd srd                /* Shift towards high-numbered address. */
+#else
+#define sLd srd                /* Shift towards low-numbered address. */
+#define sHd sld                /* Shift towards high-numbered address. */
+#endif
+
        .align  7
 _GLOBAL(__copy_tofrom_user)
 BEGIN_FTR_SECTION
@@ -118,10 +126,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 24:    ld      r9,0(r4)        /* 3+2n loads, 2+2n stores */
 25:    ld      r0,8(r4)
-       sld     r6,r9,r10
+       sLd     r6,r9,r10
 26:    ldu     r9,16(r4)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        or      r7,r7,r6
        blt     cr6,79f
 27:    ld      r0,8(r4)
@@ -129,35 +137,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 28:    ld      r0,0(r4)        /* 4+2n loads, 3+2n stores */
 29:    ldu     r9,8(r4)
-       sld     r8,r0,r10
+       sLd     r8,r0,r10
        addi    r3,r3,-8
        blt     cr6,5f
 30:    ld      r0,8(r4)
-       srd     r12,r9,r11
-       sld     r6,r9,r10
+       sHd     r12,r9,r11
+       sLd     r6,r9,r10
 31:    ldu     r9,16(r4)
        or      r12,r8,r12
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        addi    r3,r3,16
        beq     cr6,78f
 
 1:     or      r7,r7,r6
 32:    ld      r0,8(r4)
 76:    std     r12,8(r3)
-2:     srd     r12,r9,r11
-       sld     r6,r9,r10
+2:     sHd     r12,r9,r11
+       sLd     r6,r9,r10
 33:    ldu     r9,16(r4)
        or      r12,r8,r12
 77:    stdu    r7,16(r3)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        bdnz    1b
 
 78:    std     r12,8(r3)
        or      r7,r7,r6
 79:    std     r7,16(r3)
-5:     srd     r12,r9,r11
+5:     sHd     r12,r9,r11
        or      r12,r8,r12
 80:    std     r12,24(r3)
        bne     6f
@@ -165,23 +173,38 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        blr
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
-       sld     r9,r9,r10
+       sLd     r9,r9,r10
        ble     cr1,7f
 34:    ld      r0,8(r4)
-       srd     r7,r0,r11
+       sHd     r7,r0,r11
        or      r9,r7,r9
 7:
        bf      cr7*4+1,1f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,32
+#endif
 94:    stw     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,32
+#endif
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,16
+#endif
 95:    sth     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,16
+#endif
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,8
+#endif
 96:    stb     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,8
+#endif
 3:     li      r3,0
        blr
 
index 02245cee78183852d52f3a907023dcd9a63529bf..d7ddcee7feb8bc8084d18be32f348263c8de6e0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
                ioda_eeh_nb_init = 1;
        }
 
-       /* We needn't HUB diag-data on PHB3 */
-       if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-               hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-               if (!hub_diag) {
-                       pr_err("%s: Out of memory !\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
 #ifdef CONFIG_DEBUG_FS
        if (phb->dbgfs) {
                debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoP7IOCErrorData *data;
+       struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
        long rc;
 
-       data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
                           __func__, phb->hub_id, rc);
@@ -820,14 +809,15 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
        struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
                            __func__, hose->global_number, rc);
                return;
        }
 
+       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
        switch (common->ioType) {
        case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
                ioda_eeh_p7ioc_phb_diag(hose, common);
index 911c24ef033e0ae207036e5d5cab8bceaf07e14a..1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d 100644 (file)
@@ -172,11 +172,13 @@ struct pnv_phb {
                } ioda;
        };
 
-       /* PHB status structure */
+       /* PHB and hub status structure */
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
index 1e1a03d2d19fbbb35804d4fc28d8d9eac355a9c4..e9f3125325266ff8b93f13c009003d3d4aa335de 100644 (file)
@@ -135,7 +135,6 @@ config S390
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
        select OLD_SIGACTION
index ac9bed8e103fa741f85b3aecc64fcc9a18511c82..16077939409622fc946b943f4556d91cc272211c 100644 (file)
@@ -31,6 +31,7 @@ extern void smp_yield(void);
 extern void smp_stop_cpu(void);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
+extern void smp_fill_possible_mask(void);
 
 #else /* CONFIG_SMP */
 
@@ -50,6 +51,7 @@ static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
 static inline void smp_stop_cpu(void) { }
+static inline void smp_fill_possible_mask(void) { }
 
 #endif /* CONFIG_SMP */
 
index 4444875266ee028bdcc4d43604a4dea591a1a47c..0f3d44ecbfc6d5cd66541a0fe4c651acdf6a8336 100644 (file)
@@ -1023,6 +1023,7 @@ void __init setup_arch(char **cmdline_p)
        setup_vmcoreinfo();
        setup_lowcore();
 
+       smp_fill_possible_mask();
         cpu_init();
        s390_init_cpu_topology();
 
index dc4a534650604a972967ab5dedd2c1b7155c29ad..958704798f4a8e91ff898149b8d6379a39cede13 100644 (file)
@@ -721,18 +721,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
        return 0;
 }
 
-static int __init setup_possible_cpus(char *s)
-{
-       int max, cpu;
+static unsigned int setup_possible_cpus __initdata;
 
-       if (kstrtoint(s, 0, &max) < 0)
-               return 0;
-       init_cpu_possible(cpumask_of(0));
-       for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++)
-               set_cpu_possible(cpu, true);
+static int __init _setup_possible_cpus(char *s)
+{
+       get_option(&s, &setup_possible_cpus);
        return 0;
 }
-early_param("possible_cpus", setup_possible_cpus);
+early_param("possible_cpus", _setup_possible_cpus);
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -775,6 +771,17 @@ void __noreturn cpu_die(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+void __init smp_fill_possible_mask(void)
+{
+       unsigned int possible, cpu;
+
+       possible = setup_possible_cpus;
+       if (!possible)
+               possible = MACHINE_IS_VM ? 64 : nr_cpu_ids;
+       for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
+}
+
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        /* request the 0x1201 emergency signal external interrupt */
index 800f064b0da7c9a32c3910ecefdfb3e6979d7f9b..069607209a3075c6f4ff2c62fe91b7eb1d99c8aa 100644 (file)
@@ -75,6 +75,7 @@ void zpci_event_availability(void *data)
                if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED)
                        break;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
+               zdev->fh = ccdf->fh;
                ret = zpci_enable_device(zdev);
                if (ret)
                        break;
@@ -101,6 +102,7 @@ void zpci_event_availability(void *data)
                if (pdev)
                        pci_stop_and_remove_bus_device(pdev);
 
+               zdev->fh = ccdf->fh;
                zpci_disable_device(zdev);
                zdev->state = ZPCI_FN_STATE_STANDBY;
                break;
index 2a0a596ebf67d948663df3009d1ca14c8b09dabc..d77f2f6c7ff0761de1b51f09eb8926923c817681 100644 (file)
@@ -20,6 +20,11 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(empty_zero_page);
+#ifdef CONFIG_FLATMEM
+/* need in pfn_valid macro */
+EXPORT_SYMBOL(min_low_pfn);
+EXPORT_SYMBOL(max_low_pfn);
+#endif
 
 #define DECLARE_EXPORT(name)           \
        extern void name(void);EXPORT_SYMBOL(name)
index e562d3caee57457a3b188f13b2959d47a7f835b4..ad7e178337f12f2f753f66ec2a9c26dae65c9f68 100644 (file)
@@ -262,8 +262,8 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
-#define __copy_to_user_inatomic ___copy_to_user
-#define __copy_from_user_inatomic ___copy_from_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 struct pt_regs;
 extern unsigned long compute_effective_address(struct pt_regs *,
index 070ed141aac79728da15f406289219a9c385fe27..76663b019eb5207f389655dac5133afce6e553aa 100644 (file)
@@ -854,7 +854,7 @@ int dma_supported(struct device *dev, u64 device_mask)
                return 1;
 
 #ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return pci64_dma_supported(to_pci_dev(dev), device_mask);
 #endif
 
index 2096468de9b27f7dd2bb54f17e3b308f8d359836..e7e215dfa86668750c9490331d94b288ab78857c 100644 (file)
@@ -666,10 +666,9 @@ EXPORT_SYMBOL(dma_ops);
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-#ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return 1;
-#endif
+
        return 0;
 }
 EXPORT_SYMBOL(dma_supported);
index 60b19f50c80a8f9d7f31b4b4105ed4fcded6a5ca..b45fe3fb4d2cfbc7999d34a1b25baf9bc0278c2e 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/context_tracking.h>
 
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
index b66a5338231e965252fef5f23234141bb2fc8f85..b085311dcd0ea9f81840e1fc2550c4f870e984eb 100644 (file)
@@ -123,11 +123,12 @@ void smp_callin(void)
                rmb();
 
        set_cpu_online(cpuid, true);
-       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
 
+       local_irq_enable();
+
        cpu_startup_entry(CPUHP_ONLINE);
 }
 
index c49a613c6452fc66afdf5de52572dc8d033a8fcc..cea1c76d49bf5b04344bb17c353bab35869cf01a 100644 (file)
@@ -293,12 +293,13 @@ static inline int restore_fpu_checking(struct task_struct *tsk)
        /* 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. "m" 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" (tsk->thread.fpu.has_fpu));
+       if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) {
+               asm volatile(
+                       "fnclex\n\t"
+                       "emms\n\t"
+                       "fildl %P[addr]"        /* set F?P to defined value */
+                       : : [addr] "m" (tsk->thread.fpu.has_fpu));
+       }
 
        return fpu_restore_checking(&tsk->thread.fpu);
 }
index 51e2988c5728d5d57b5b8f0ef035258cc292b2c1..a2a4f4697889657675289e15e358b7f354ea2225 100644 (file)
@@ -1082,7 +1082,7 @@ ENTRY(ftrace_caller)
        pushl $0        /* Pass NULL as regs pointer */
        movl 4*4(%esp), %eax
        movl 0x4(%ebp), %edx
-       leal function_trace_op, %ecx
+       movl function_trace_op, %ecx
        subl $MCOUNT_INSN_SIZE, %eax
 
 .globl ftrace_call
@@ -1140,7 +1140,7 @@ ENTRY(ftrace_regs_caller)
        movl 12*4(%esp), %eax   /* Load ip (1st parameter) */
        subl $MCOUNT_INSN_SIZE, %eax    /* Adjust ip */
        movl 0x4(%ebp), %edx    /* Load parent ip (2nd parameter) */
-       leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
+       movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
        pushl %esp              /* Save pt_regs as 4th parameter */
 
 GLOBAL(ftrace_regs_call)
index e21b0785a85b2fc2f2ca1615820d5e432a9f4675..1e96c3628bf24fc4fe0086ac6f9dc70b2c1c590d 100644 (file)
@@ -88,7 +88,7 @@ END(function_hook)
        MCOUNT_SAVE_FRAME \skip
 
        /* Load the ftrace_ops into the 3rd parameter */
-       leaq function_trace_op, %rdx
+       movq function_trace_op(%rip), %rdx
 
        /* Load ip into the first parameter */
        movq RIP(%rsp), %rdi
index dec48bfaddb8ff79ee7f7734cebfca7f36844461..1673940cf9c35169d808a71ef31c031d5c8a390d 100644 (file)
@@ -1350,6 +1350,10 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                return;
        }
 
+       if (!kvm_vcpu_is_bsp(apic->vcpu))
+               value &= ~MSR_IA32_APICBASE_BSP;
+       vcpu->arch.apic_base = value;
+
        /* update jump label if enable bit changes */
        if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
                if (value & MSR_IA32_APICBASE_ENABLE)
@@ -1359,10 +1363,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                recalculate_apic_map(vcpu->kvm);
        }
 
-       if (!kvm_vcpu_is_bsp(apic->vcpu))
-               value &= ~MSR_IA32_APICBASE_BSP;
-
-       vcpu->arch.apic_base = value;
        if ((old_value ^ value) & X2APIC_ENABLE) {
                if (value & X2APIC_ENABLE) {
                        u32 id = kvm_apic_id(apic);
index b2fe1c252f35f92e3b6707406998738a9275c8d2..da7837e1349da8ac4ac06468fb2f05e798e136f1 100644 (file)
@@ -8283,8 +8283,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        kvm_set_cr4(vcpu, vmcs12->host_cr4);
 
-       if (nested_cpu_has_ept(vmcs12))
-               nested_ept_uninit_mmu_context(vcpu);
+       nested_ept_uninit_mmu_context(vcpu);
 
        kvm_set_cr3(vcpu, vmcs12->host_cr3);
        kvm_mmu_reset_context(vcpu);
index 8711e3797165fa73fd0c401cedbb54c61eb68e4a..3c2e4aa529c479e92090c8862deaadcf0a8645e5 100644 (file)
@@ -207,7 +207,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
                goto end;
 
        result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
        if (result) {
                power_supply_unregister(&ac->charger);
                goto end;
@@ -255,7 +255,7 @@ static int acpi_ac_remove(struct platform_device *pdev)
                return -EINVAL;
 
        acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
 
        ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
index fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68..5876a49dfd386a4653325d99fcc69aa8452b12e1 100644 (file)
@@ -62,6 +62,7 @@ MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
 MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
+static int battery_bix_broken_package;
 static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -416,7 +417,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
                return -ENODEV;
        }
-       if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+
+       if (battery_bix_broken_package)
+               result = extract_package(battery, buffer.pointer,
+                               extended_info_offsets + 1,
+                               ARRAY_SIZE(extended_info_offsets) - 1);
+       else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
                result = extract_package(battery, buffer.pointer,
                                extended_info_offsets,
                                ARRAY_SIZE(extended_info_offsets));
@@ -754,6 +760,17 @@ static int battery_notify(struct notifier_block *nb,
        return 0;
 }
 
+static struct dmi_system_id bat_dmi_table[] = {
+       {
+               .ident = "NEC LZ750/LS",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
+               },
+       },
+       {},
+};
+
 static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
@@ -846,6 +863,9 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
+
+       if (dmi_check_system(bat_dmi_table))
+               battery_bix_broken_package = 1;
        acpi_bus_register_driver(&acpi_battery_driver);
 }
 
index bba9b72e25f8235e6d12593bdd16bb378c7af25a..0710004055c809f3059cde2337373503666fd96f 100644 (file)
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
 }
 EXPORT_SYMBOL(acpi_bus_get_private_data);
 
+void acpi_bus_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               adev->flags.no_hotplug = true;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
+
 static void acpi_print_osc_error(acpi_handle handle,
        struct acpi_osc_context *context, char *error)
 {
index c0ed4f273cf22b50a486b08f08c811e563781b07..e3a92a6da39ae258cf9a4094f4293799e378271b 100644 (file)
@@ -427,6 +427,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
+                        PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9170 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
index fe3ca0989b14cac2e712ef2778f2a1b7e528c85b..1ad2f62d34b98fd0b41be9a239827e1634327c54 100644 (file)
@@ -83,6 +83,10 @@ static struct pci_driver sis_pci_driver = {
        .id_table               = sis_pci_tbl,
        .probe                  = sis_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template sis_sht = {
index a2e69d26266d9b7faef4244aef695180d4c6eaef..83a598ebb65a4ab7699d1dcebe1b44b42ea8ae5a 100644 (file)
@@ -425,10 +425,7 @@ static void null_del_dev(struct nullb *nullb)
        list_del_init(&nullb->list);
 
        del_gendisk(nullb->disk);
-       if (queue_mode == NULL_Q_MQ)
-               blk_mq_free_queue(nullb->q);
-       else
-               blk_cleanup_queue(nullb->q);
+       blk_cleanup_queue(nullb->q);
        put_disk(nullb->disk);
        kfree(nullb);
 }
@@ -578,10 +575,7 @@ static int null_add_dev(void)
        disk = nullb->disk = alloc_disk_node(1, home_node);
        if (!disk) {
 queue_fail:
-               if (queue_mode == NULL_Q_MQ)
-                       blk_mq_free_queue(nullb->q);
-               else
-                       blk_cleanup_queue(nullb->q);
+               blk_cleanup_queue(nullb->q);
                cleanup_queues(nullb);
 err:
                kfree(nullb);
index 6bfc1bb318f6399397ca8f169cc07fd98b46256d..dceb85f8d9a8251ed115e06af348692898f6a400 100644 (file)
@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
        { USB_DEVICE(0x0489, 0xe04e) },
@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index c0ff34f2d2df577efffe902562f9578690ea4e39..3980fd18f6eaeeb129fe543728f19231df80bd59 100644 (file)
@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index 7ff1d0d208a7c3f89f6827fd3e9ba8815dad202d..2d68054f97954402095051600529754b0f4b3e56 100644 (file)
@@ -50,7 +50,7 @@ obj-$(CONFIG_GPIO_TB0219)     += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
 obj-$(CONFIG_MWAVE)            += mwave/
-obj-$(CONFIG_AGP)              += agp/
+obj-y                          += agp/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
 
 obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
index d8b1b576556cf8eba8c2fa398c6c9bc8d6960803..c528f96ee204fb3f480e29d96992e1e0c1870272 100644 (file)
@@ -68,6 +68,7 @@ config AGP_AMD64
 config AGP_INTEL
        tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
        depends on AGP && X86
+       select INTEL_GTT
        help
          This option gives you AGP support for the GLX component of X
          on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
@@ -155,3 +156,7 @@ config AGP_SGI_TIOCA
           This option gives you AGP GART support for the SGI TIO chipset
           for IA64 processors.
 
+config INTEL_GTT
+       tristate
+       depends on X86 && PCI
+
index 8eb56e273e75719f51d617fe3a2ed5c4b9cc06f2..604489bcdbf9b6c70b51e89f093accfdb34f4d25 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1)      += hp-agp.o
 obj-$(CONFIG_AGP_PARISC)       += parisc-agp.o
 obj-$(CONFIG_AGP_I460)         += i460-agp.o
 obj-$(CONFIG_AGP_INTEL)                += intel-agp.o
-obj-$(CONFIG_AGP_INTEL)                += intel-gtt.o
+obj-$(CONFIG_INTEL_GTT)                += intel-gtt.o
 obj-$(CONFIG_AGP_NVIDIA)       += nvidia-agp.o
 obj-$(CONFIG_AGP_SGI_TIOCA)    += sgi-agp.o
 obj-$(CONFIG_AGP_SIS)          += sis-agp.o
index a426ee1f57a6fd71b30fbd80429cac7c97aa1b4c..9ef0a48a5b28196600a780e4f76ec33ab4120c5e 100644 (file)
@@ -14,9 +14,6 @@
 #include "intel-agp.h"
 #include <drm/intel-gtt.h>
 
-int intel_agp_enabled;
-EXPORT_SYMBOL(intel_agp_enabled);
-
 static int intel_fetch_size(void)
 {
        int i;
@@ -814,8 +811,6 @@ static int agp_intel_probe(struct pci_dev *pdev,
 found_gmch:
        pci_set_drvdata(pdev, bridge);
        err = agp_add_bridge(bridge);
-       if (!err)
-               intel_agp_enabled = 1;
        return err;
 }
 
index b8e2014cb9cb0681d8fa1a21d7930b13e1e2a261..078968d8d07d933b974c8183b6cbd1f9a7163011 100644 (file)
@@ -94,6 +94,7 @@ static struct _intel_private {
 #define IS_IRONLAKE    intel_private.driver->is_ironlake
 #define HAS_PGTBL_EN   intel_private.driver->has_pgtbl_enable
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_gtt_map_memory(struct page **pages,
                                unsigned int num_entries,
                                struct sg_table *st)
@@ -168,6 +169,7 @@ static void i8xx_destroy_pages(struct page *page)
        __free_pages(page, 2);
        atomic_dec(&agp_bridge->current_memory_agp);
 }
+#endif
 
 #define I810_GTT_ORDER 4
 static int i810_setup(void)
@@ -209,6 +211,7 @@ static void i810_cleanup(void)
        free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER);
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start,
                                      int type)
 {
@@ -289,6 +292,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
        }
        kfree(curr);
 }
+#endif
 
 static int intel_gtt_setup_scratch_page(void)
 {
@@ -647,7 +651,9 @@ static int intel_gtt_init(void)
                return -ENOMEM;
        }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        global_cache_flush();   /* FIXME: ? */
+#endif
 
        intel_private.stolen_size = intel_gtt_stolen_size();
 
@@ -671,6 +677,7 @@ static int intel_gtt_init(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_fetch_size(void)
 {
        int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
@@ -689,6 +696,7 @@ static int intel_fake_agp_fetch_size(void)
 
        return 0;
 }
+#endif
 
 static void i830_cleanup(void)
 {
@@ -801,6 +809,7 @@ static int i830_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge)
 {
        agp_bridge->gatt_table_real = NULL;
@@ -825,6 +834,7 @@ static int intel_fake_agp_configure(void)
 
        return 0;
 }
+#endif
 
 static bool i830_check_flags(unsigned int flags)
 {
@@ -863,6 +873,7 @@ void intel_gtt_insert_sg_entries(struct sg_table *st,
 }
 EXPORT_SYMBOL(intel_gtt_insert_sg_entries);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static void intel_gtt_insert_pages(unsigned int first_entry,
                                   unsigned int num_entries,
                                   struct page **pages,
@@ -928,6 +939,7 @@ out_err:
        mem->is_flushed = true;
        return ret;
 }
+#endif
 
 void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 {
@@ -941,6 +953,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 }
 EXPORT_SYMBOL(intel_gtt_clear_range);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_remove_entries(struct agp_memory *mem,
                                         off_t pg_start, int type)
 {
@@ -982,6 +995,7 @@ static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
        /* always return NULL for other allocation types for now */
        return NULL;
 }
+#endif
 
 static int intel_alloc_chipset_flush_resource(void)
 {
@@ -1138,6 +1152,7 @@ static int i9xx_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static const struct agp_bridge_driver intel_fake_agp_driver = {
        .owner                  = THIS_MODULE,
        .size_type              = FIXED_APER_SIZE,
@@ -1159,6 +1174,7 @@ static const struct agp_bridge_driver intel_fake_agp_driver = {
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_destroy_pages      = agp_generic_destroy_pages,
 };
+#endif
 
 static const struct intel_gtt_driver i81x_gtt_driver = {
        .gen = 1,
@@ -1376,11 +1392,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
 
        intel_private.refcount++;
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        if (bridge) {
                bridge->driver = &intel_fake_agp_driver;
                bridge->dev_private_data = &intel_private;
                bridge->dev = bridge_pdev;
        }
+#endif
 
        intel_private.bridge_dev = pci_dev_get(bridge_pdev);
 
index 8e562dc656016cd9c4dbeaaa3dac0a96a02d0f26..e1f3337a0cf9f7d7fa223a86e84282765d915108 100644 (file)
@@ -27,15 +27,18 @@ static char *tpm_device_name = "TPM";
 static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
                                void **return_value)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-       if (strstr(buffer.pointer, context) != NULL) {
-               *return_value = handle;
+
+       if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
+               if (strstr(buffer.pointer, context) != NULL) {
+                       *return_value = handle;
+                       status = AE_CTRL_TERMINATE;
+               }
                kfree(buffer.pointer);
-               return AE_CTRL_TERMINATE;
        }
-       return AE_OK;
+
+       return status;
 }
 
 static inline void ppi_assign_params(union acpi_object params[4],
index 8d3009e44fba40d4fba82825bd59d98febf53984..5543b7df8e16c736c210407a5d837ffb32ab3beb 100644 (file)
@@ -87,7 +87,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div;
index 39b40aaede2b36a3bd92546ff344420b480fb569..68e515d093d864ca9cc704d6f90a441695e67a6d 100644 (file)
@@ -26,17 +26,17 @@ static struct clk_onecell_data clk_data;
 #define ASS_CLK_DIV 0x4
 #define ASS_CLK_GATE 0x8
 
+/* list of all parent clock list */
+static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
+static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
+
+#ifdef CONFIG_PM_SLEEP
 static unsigned long reg_save[][2] = {
        {ASS_CLK_SRC,  0},
        {ASS_CLK_DIV,  0},
        {ASS_CLK_GATE, 0},
 };
 
-/* list of all parent clock list */
-static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
-static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
-
-#ifdef CONFIG_PM_SLEEP
 static int exynos_audss_clk_suspend(void)
 {
        int i;
index ad5ff50c5f281a5e1c31c498c78c5a717aa464de..1a7c1b929c690b03b2b24a1423da55a97b66aa00 100644 (file)
@@ -39,7 +39,7 @@
 #define SRC_TOP1               0xc214
 #define SRC_CAM                        0xc220
 #define SRC_TV                 0xc224
-#define SRC_MFC                        0xcc28
+#define SRC_MFC                        0xc228
 #define SRC_G3D                        0xc22c
 #define E4210_SRC_IMAGE                0xc230
 #define SRC_LCD0               0xc234
index adf32343c9f9c408f5b8bc7c78a6ce3bc66c27a7..e52359cf9b6fe76db63b787717f003454d89e12e 100644 (file)
@@ -25,6 +25,7 @@
 #define MPLL_LOCK              0x4000
 #define MPLL_CON0              0x4100
 #define SRC_CORE1              0x4204
+#define GATE_IP_ACP            0x8800
 #define CPLL_LOCK              0x10020
 #define EPLL_LOCK              0x10030
 #define VPLL_LOCK              0x10040
@@ -75,7 +76,6 @@
 #define SRC_CDREX              0x20200
 #define PLL_DIV2_SEL           0x20a24
 #define GATE_IP_DISP1          0x10928
-#define GATE_IP_ACP            0x10000
 
 /* list of PLLs to be registered */
 enum exynos5250_plls {
@@ -120,7 +120,8 @@ enum exynos5250_clks {
        spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
        hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
        tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, mdma0,
+       smmu_mdma0,
 
        /* mux clocks */
        mout_hdmi = 1024,
@@ -354,8 +355,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
        GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
        GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
-       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
-       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 1, 0, 0),
        GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
        GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
        GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -406,7 +407,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
        GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
        GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+       GATE(sysreg, "sysreg", "aclk66",
+                       GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
        GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0),
        GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
        GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
@@ -492,6 +494,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
        GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+       GATE(mdma0, "mdma0", "aclk266", GATE_IP_ACP, 1, 0, 0),
+       GATE(smmu_mdma0, "smmu_mdma0", "aclk266", GATE_IP_ACP, 5, 0, 0),
 };
 
 static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
index f49fac2d193acf662856fc74e5acd1d668b2cc84..f7dfb72884a4e2d177261984023d7c20f9249a22 100644 (file)
@@ -6,7 +6,12 @@ obj-y                                  += clk-periph-gate.o
 obj-y                                  += clk-pll.o
 obj-y                                  += clk-pll-out.o
 obj-y                                  += clk-super.o
-
+obj-y                                  += clk-tegra-audio.o
+obj-y                                  += clk-tegra-periph.o
+obj-y                                  += clk-tegra-pmc.o
+obj-y                                  += clk-tegra-fixed.o
+obj-y                                  += clk-tegra-super-gen4.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += clk-tegra114.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)       += clk-tegra124.o
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
new file mode 100644 (file)
index 0000000..cf0c323
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * This header provides IDs for clocks common between several Tegra SoCs
+ */
+#ifndef _TEGRA_CLK_ID_H
+#define _TEGRA_CLK_ID_H
+
+enum clk_id {
+       tegra_clk_actmon,
+       tegra_clk_adx,
+       tegra_clk_adx1,
+       tegra_clk_afi,
+       tegra_clk_amx,
+       tegra_clk_amx1,
+       tegra_clk_apbdma,
+       tegra_clk_apbif,
+       tegra_clk_audio0,
+       tegra_clk_audio0_2x,
+       tegra_clk_audio0_mux,
+       tegra_clk_audio1,
+       tegra_clk_audio1_2x,
+       tegra_clk_audio1_mux,
+       tegra_clk_audio2,
+       tegra_clk_audio2_2x,
+       tegra_clk_audio2_mux,
+       tegra_clk_audio3,
+       tegra_clk_audio3_2x,
+       tegra_clk_audio3_mux,
+       tegra_clk_audio4,
+       tegra_clk_audio4_2x,
+       tegra_clk_audio4_mux,
+       tegra_clk_blink,
+       tegra_clk_bsea,
+       tegra_clk_bsev,
+       tegra_clk_cclk_g,
+       tegra_clk_cclk_lp,
+       tegra_clk_cilab,
+       tegra_clk_cilcd,
+       tegra_clk_cile,
+       tegra_clk_clk_32k,
+       tegra_clk_clk72Mhz,
+       tegra_clk_clk_m,
+       tegra_clk_clk_m_div2,
+       tegra_clk_clk_m_div4,
+       tegra_clk_clk_out_1,
+       tegra_clk_clk_out_1_mux,
+       tegra_clk_clk_out_2,
+       tegra_clk_clk_out_2_mux,
+       tegra_clk_clk_out_3,
+       tegra_clk_clk_out_3_mux,
+       tegra_clk_cml0,
+       tegra_clk_cml1,
+       tegra_clk_csi,
+       tegra_clk_csite,
+       tegra_clk_csus,
+       tegra_clk_cve,
+       tegra_clk_dam0,
+       tegra_clk_dam1,
+       tegra_clk_dam2,
+       tegra_clk_d_audio,
+       tegra_clk_dds,
+       tegra_clk_dfll_ref,
+       tegra_clk_dfll_soc,
+       tegra_clk_disp1,
+       tegra_clk_disp2,
+       tegra_clk_dp2,
+       tegra_clk_dpaux,
+       tegra_clk_dsia,
+       tegra_clk_dsialp,
+       tegra_clk_dsia_mux,
+       tegra_clk_dsib,
+       tegra_clk_dsiblp,
+       tegra_clk_dsib_mux,
+       tegra_clk_dtv,
+       tegra_clk_emc,
+       tegra_clk_entropy,
+       tegra_clk_epp,
+       tegra_clk_epp_8,
+       tegra_clk_extern1,
+       tegra_clk_extern2,
+       tegra_clk_extern3,
+       tegra_clk_fuse,
+       tegra_clk_fuse_burn,
+       tegra_clk_gpu,
+       tegra_clk_gr2d,
+       tegra_clk_gr2d_8,
+       tegra_clk_gr3d,
+       tegra_clk_gr3d_8,
+       tegra_clk_hclk,
+       tegra_clk_hda,
+       tegra_clk_hda2codec_2x,
+       tegra_clk_hda2hdmi,
+       tegra_clk_hdmi,
+       tegra_clk_hdmi_audio,
+       tegra_clk_host1x,
+       tegra_clk_host1x_8,
+       tegra_clk_i2c1,
+       tegra_clk_i2c2,
+       tegra_clk_i2c3,
+       tegra_clk_i2c4,
+       tegra_clk_i2c5,
+       tegra_clk_i2c6,
+       tegra_clk_i2cslow,
+       tegra_clk_i2s0,
+       tegra_clk_i2s0_sync,
+       tegra_clk_i2s1,
+       tegra_clk_i2s1_sync,
+       tegra_clk_i2s2,
+       tegra_clk_i2s2_sync,
+       tegra_clk_i2s3,
+       tegra_clk_i2s3_sync,
+       tegra_clk_i2s4,
+       tegra_clk_i2s4_sync,
+       tegra_clk_isp,
+       tegra_clk_isp_8,
+       tegra_clk_ispb,
+       tegra_clk_kbc,
+       tegra_clk_kfuse,
+       tegra_clk_la,
+       tegra_clk_mipi,
+       tegra_clk_mipi_cal,
+       tegra_clk_mpe,
+       tegra_clk_mselect,
+       tegra_clk_msenc,
+       tegra_clk_ndflash,
+       tegra_clk_ndflash_8,
+       tegra_clk_ndspeed,
+       tegra_clk_ndspeed_8,
+       tegra_clk_nor,
+       tegra_clk_owr,
+       tegra_clk_pcie,
+       tegra_clk_pclk,
+       tegra_clk_pll_a,
+       tegra_clk_pll_a_out0,
+       tegra_clk_pll_c,
+       tegra_clk_pll_c2,
+       tegra_clk_pll_c3,
+       tegra_clk_pll_c4,
+       tegra_clk_pll_c_out1,
+       tegra_clk_pll_d,
+       tegra_clk_pll_d2,
+       tegra_clk_pll_d2_out0,
+       tegra_clk_pll_d_out0,
+       tegra_clk_pll_dp,
+       tegra_clk_pll_e_out0,
+       tegra_clk_pll_m,
+       tegra_clk_pll_m_out1,
+       tegra_clk_pll_p,
+       tegra_clk_pll_p_out1,
+       tegra_clk_pll_p_out2,
+       tegra_clk_pll_p_out2_int,
+       tegra_clk_pll_p_out3,
+       tegra_clk_pll_p_out4,
+       tegra_clk_pll_p_out5,
+       tegra_clk_pll_ref,
+       tegra_clk_pll_re_out,
+       tegra_clk_pll_re_vco,
+       tegra_clk_pll_u,
+       tegra_clk_pll_u_12m,
+       tegra_clk_pll_u_480m,
+       tegra_clk_pll_u_48m,
+       tegra_clk_pll_u_60m,
+       tegra_clk_pll_x,
+       tegra_clk_pll_x_out0,
+       tegra_clk_pwm,
+       tegra_clk_rtc,
+       tegra_clk_sata,
+       tegra_clk_sata_cold,
+       tegra_clk_sata_oob,
+       tegra_clk_sbc1,
+       tegra_clk_sbc1_8,
+       tegra_clk_sbc2,
+       tegra_clk_sbc2_8,
+       tegra_clk_sbc3,
+       tegra_clk_sbc3_8,
+       tegra_clk_sbc4,
+       tegra_clk_sbc4_8,
+       tegra_clk_sbc5,
+       tegra_clk_sbc5_8,
+       tegra_clk_sbc6,
+       tegra_clk_sbc6_8,
+       tegra_clk_sclk,
+       tegra_clk_sdmmc1,
+       tegra_clk_sdmmc2,
+       tegra_clk_sdmmc3,
+       tegra_clk_sdmmc4,
+       tegra_clk_se,
+       tegra_clk_soc_therm,
+       tegra_clk_sor0,
+       tegra_clk_sor0_lvds,
+       tegra_clk_spdif,
+       tegra_clk_spdif_2x,
+       tegra_clk_spdif_in,
+       tegra_clk_spdif_in_sync,
+       tegra_clk_spdif_mux,
+       tegra_clk_spdif_out,
+       tegra_clk_timer,
+       tegra_clk_trace,
+       tegra_clk_tsec,
+       tegra_clk_tsensor,
+       tegra_clk_tvdac,
+       tegra_clk_tvo,
+       tegra_clk_uarta,
+       tegra_clk_uartb,
+       tegra_clk_uartc,
+       tegra_clk_uartd,
+       tegra_clk_uarte,
+       tegra_clk_usb2,
+       tegra_clk_usb3,
+       tegra_clk_usbd,
+       tegra_clk_vcp,
+       tegra_clk_vde,
+       tegra_clk_vde_8,
+       tegra_clk_vfir,
+       tegra_clk_vi,
+       tegra_clk_vi_8,
+       tegra_clk_vi_9,
+       tegra_clk_vic03,
+       tegra_clk_vim2_clk,
+       tegra_clk_vimclk_sync,
+       tegra_clk_vi_sensor,
+       tegra_clk_vi_sensor2,
+       tegra_clk_vi_sensor_8,
+       tegra_clk_xusb_dev,
+       tegra_clk_xusb_dev_src,
+       tegra_clk_xusb_falcon_src,
+       tegra_clk_xusb_fs_src,
+       tegra_clk_xusb_host,
+       tegra_clk_xusb_host_src,
+       tegra_clk_xusb_hs_src,
+       tegra_clk_xusb_ss,
+       tegra_clk_xusb_ss_src,
+       tegra_clk_max,
+};
+
+#endif /* _TEGRA_CLK_ID_H */
index bafee9895a247905d56ebe94c6a972eb7527c1c8..507015314827b079577dd85e1bd8e8faab54d628 100644 (file)
@@ -36,8 +36,6 @@ static DEFINE_SPINLOCK(periph_ref_lock);
 
 #define read_rst(gate) \
        readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
-#define write_rst_set(val, gate) \
-       writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg))
 #define write_rst_clr(val, gate) \
        writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
 
@@ -123,26 +121,6 @@ static void clk_periph_disable(struct clk_hw *hw)
        spin_unlock_irqrestore(&periph_ref_lock, flags);
 }
 
-void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert)
-{
-       if (gate->flags & TEGRA_PERIPH_NO_RESET)
-               return;
-
-       if (assert) {
-               /*
-                * If peripheral is in the APB bus then read the APB bus to
-                * flush the write operation in apb bus. This will avoid the
-                * peripheral access after disabling clock
-                */
-               if (gate->flags & TEGRA_PERIPH_ON_APB)
-                       tegra_read_chipid();
-
-               write_rst_set(periph_clk_to_bit(gate), gate);
-       } else {
-               write_rst_clr(periph_clk_to_bit(gate), gate);
-       }
-}
-
 const struct clk_ops tegra_clk_periph_gate_ops = {
        .is_enabled = clk_periph_is_enabled,
        .enable = clk_periph_enable,
@@ -151,12 +129,16 @@ const struct clk_ops tegra_clk_periph_gate_ops = {
 
 struct clk *tegra_clk_register_periph_gate(const char *name,
                const char *parent_name, u8 gate_flags, void __iomem *clk_base,
-               unsigned long flags, int clk_num,
-               struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
+               unsigned long flags, int clk_num, int *enable_refcnt)
 {
        struct tegra_clk_periph_gate *gate;
        struct clk *clk;
        struct clk_init_data init;
+       struct tegra_clk_periph_regs *pregs;
+
+       pregs = get_reg_bank(clk_num);
+       if (!pregs)
+               return ERR_PTR(-EINVAL);
 
        gate = kzalloc(sizeof(*gate), GFP_KERNEL);
        if (!gate) {
index b2309d37a9637b70cfc823ea3ada7dc32d99c88a..c534043c0481e95ffbee7fa9a09e7af0dcee0aa7 100644 (file)
@@ -111,46 +111,6 @@ static void clk_periph_disable(struct clk_hw *hw)
        gate_ops->disable(gate_hw);
 }
 
-void tegra_periph_reset_deassert(struct clk *c)
-{
-       struct clk_hw *hw = __clk_get_hw(c);
-       struct tegra_clk_periph *periph = to_clk_periph(hw);
-       struct tegra_clk_periph_gate *gate;
-
-       if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
-               gate = to_clk_periph_gate(hw);
-               if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
-                       WARN_ON(1);
-                       return;
-               }
-       } else {
-               gate = &periph->gate;
-       }
-
-       tegra_periph_reset(gate, 0);
-}
-EXPORT_SYMBOL(tegra_periph_reset_deassert);
-
-void tegra_periph_reset_assert(struct clk *c)
-{
-       struct clk_hw *hw = __clk_get_hw(c);
-       struct tegra_clk_periph *periph = to_clk_periph(hw);
-       struct tegra_clk_periph_gate *gate;
-
-       if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
-               gate = to_clk_periph_gate(hw);
-               if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
-                       WARN_ON(1);
-                       return;
-               }
-       } else {
-               gate = &periph->gate;
-       }
-
-       tegra_periph_reset(gate, 1);
-}
-EXPORT_SYMBOL(tegra_periph_reset_assert);
-
 const struct clk_ops tegra_clk_periph_ops = {
        .get_parent = clk_periph_get_parent,
        .set_parent = clk_periph_set_parent,
@@ -170,27 +130,50 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
        .disable = clk_periph_disable,
 };
 
+const struct clk_ops tegra_clk_periph_no_gate_ops = {
+       .get_parent = clk_periph_get_parent,
+       .set_parent = clk_periph_set_parent,
+       .recalc_rate = clk_periph_recalc_rate,
+       .round_rate = clk_periph_round_rate,
+       .set_rate = clk_periph_set_rate,
+};
+
 static struct clk *_tegra_clk_register_periph(const char *name,
                        const char **parent_names, int num_parents,
                        struct tegra_clk_periph *periph,
-                       void __iomem *clk_base, u32 offset, bool div,
+                       void __iomem *clk_base, u32 offset,
                        unsigned long flags)
 {
        struct clk *clk;
        struct clk_init_data init;
+       struct tegra_clk_periph_regs *bank;
+       bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
+
+       if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
+               flags |= CLK_SET_RATE_PARENT;
+               init.ops = &tegra_clk_periph_nodiv_ops;
+       } else if (periph->gate.flags & TEGRA_PERIPH_NO_GATE)
+               init.ops = &tegra_clk_periph_no_gate_ops;
+       else
+               init.ops = &tegra_clk_periph_ops;
 
        init.name = name;
-       init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
        init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
+       bank = get_reg_bank(periph->gate.clk_num);
+       if (!bank)
+               return ERR_PTR(-EINVAL);
+
        /* Data in .init is copied by clk_register(), so stack variable OK */
        periph->hw.init = &init;
        periph->magic = TEGRA_CLK_PERIPH_MAGIC;
        periph->mux.reg = clk_base + offset;
        periph->divider.reg = div ? (clk_base + offset) : NULL;
        periph->gate.clk_base = clk_base;
+       periph->gate.regs = bank;
+       periph->gate.enable_refcnt = periph_clk_enb_refcnt;
 
        clk = clk_register(NULL, &periph->hw);
        if (IS_ERR(clk))
@@ -209,7 +192,7 @@ struct clk *tegra_clk_register_periph(const char *name,
                u32 offset, unsigned long flags)
 {
        return _tegra_clk_register_periph(name, parent_names, num_parents,
-                       periph, clk_base, offset, true, flags);
+                       periph, clk_base, offset, flags);
 }
 
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
@@ -217,6 +200,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset)
 {
+       periph->gate.flags |= TEGRA_PERIPH_NO_DIV;
        return _tegra_clk_register_periph(name, parent_names, num_parents,
-                       periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
+                       periph, clk_base, offset, CLK_SET_RATE_PARENT);
 }
index 197074a5775421371d8c17526a6799ea4212b202..2dd432266ef620d7b56aff825d7b7bbe24351cbd 100644 (file)
 #define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
 
 #define PLLE_SS_CTRL 0x68
-#define PLLE_SS_DISABLE (7 << 10)
+#define PLLE_SS_CNTL_BYPASS_SS BIT(10)
+#define PLLE_SS_CNTL_INTERP_RESET BIT(11)
+#define PLLE_SS_CNTL_SSC_BYP BIT(12)
+#define PLLE_SS_CNTL_CENTER BIT(14)
+#define PLLE_SS_CNTL_INVERT BIT(15)
+#define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\
+                               PLLE_SS_CNTL_SSC_BYP)
+#define PLLE_SS_MAX_MASK 0x1ff
+#define PLLE_SS_MAX_VAL 0x25
+#define PLLE_SS_INC_MASK (0xff << 16)
+#define PLLE_SS_INC_VAL (0x1 << 16)
+#define PLLE_SS_INCINTRV_MASK (0x3f << 24)
+#define PLLE_SS_INCINTRV_VAL (0x20 << 24)
+#define PLLE_SS_COEFFICIENTS_MASK \
+       (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK)
+#define PLLE_SS_COEFFICIENTS_VAL \
+       (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
 
 #define PLLE_AUX_PLLP_SEL      BIT(2)
 #define PLLE_AUX_ENABLE_SWCTL  BIT(4)
 #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
 #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
 
+#define PLLSS_MISC_KCP         0
+#define PLLSS_MISC_KVCO                0
+#define PLLSS_MISC_SETUP       0
+#define PLLSS_EN_SDM           0
+#define PLLSS_EN_SSC           0
+#define PLLSS_EN_DITHER2       0
+#define PLLSS_EN_DITHER                1
+#define PLLSS_SDM_RESET                0
+#define PLLSS_CLAMP            0
+#define PLLSS_SDM_SSC_MAX      0
+#define PLLSS_SDM_SSC_MIN      0
+#define PLLSS_SDM_SSC_STEP     0
+#define PLLSS_SDM_DIN          0
+#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \
+                           (PLLSS_MISC_KVCO << 24) | \
+                           PLLSS_MISC_SETUP)
+#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \
+                          (PLLSS_EN_SSC << 30) | \
+                          (PLLSS_EN_DITHER2 << 29) | \
+                          (PLLSS_EN_DITHER << 28) | \
+                          (PLLSS_SDM_RESET) << 27 | \
+                          (PLLSS_CLAMP << 22))
+#define PLLSS_CTRL1_DEFAULT \
+                       ((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN)
+#define PLLSS_CTRL2_DEFAULT \
+                       ((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN)
+#define PLLSS_LOCK_OVERRIDE    BIT(24)
+#define PLLSS_REF_SRC_SEL_SHIFT        25
+#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
+
 #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
 #define pll_readl_base(p) pll_readl(p->params->base_reg, p)
 #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
 #define mask(w) ((1 << (w)) - 1)
 #define divm_mask(p) mask(p->params->div_nmp->divm_width)
 #define divn_mask(p) mask(p->params->div_nmp->divn_width)
-#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :    \
+#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
                      mask(p->params->div_nmp->divp_width))
 
 #define divm_max(p) (divm_mask(p))
@@ -154,10 +200,10 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
 {
        u32 val;
 
-       if (!(pll->flags & TEGRA_PLL_USE_LOCK))
+       if (!(pll->params->flags & TEGRA_PLL_USE_LOCK))
                return;
 
-       if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
+       if (!(pll->params->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
                return;
 
        val = pll_readl_misc(pll);
@@ -171,13 +217,13 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
        u32 val, lock_mask;
        void __iomem *lock_addr;
 
-       if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
+       if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) {
                udelay(pll->params->lock_delay);
                return 0;
        }
 
        lock_addr = pll->clk_base;
-       if (pll->flags & TEGRA_PLL_LOCK_MISC)
+       if (pll->params->flags & TEGRA_PLL_LOCK_MISC)
                lock_addr += pll->params->misc_reg;
        else
                lock_addr += pll->params->base_reg;
@@ -204,7 +250,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        u32 val;
 
-       if (pll->flags & TEGRA_PLLM) {
+       if (pll->params->flags & TEGRA_PLLM) {
                val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
                if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
                        return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
@@ -223,12 +269,12 @@ static void _clk_pll_enable(struct clk_hw *hw)
        clk_pll_enable_lock(pll);
 
        val = pll_readl_base(pll);
-       if (pll->flags & TEGRA_PLL_BYPASS)
+       if (pll->params->flags & TEGRA_PLL_BYPASS)
                val &= ~PLL_BASE_BYPASS;
        val |= PLL_BASE_ENABLE;
        pll_writel_base(val, pll);
 
-       if (pll->flags & TEGRA_PLLM) {
+       if (pll->params->flags & TEGRA_PLLM) {
                val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
                val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
                writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
@@ -241,12 +287,12 @@ static void _clk_pll_disable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl_base(pll);
-       if (pll->flags & TEGRA_PLL_BYPASS)
+       if (pll->params->flags & TEGRA_PLL_BYPASS)
                val &= ~PLL_BASE_BYPASS;
        val &= ~PLL_BASE_ENABLE;
        pll_writel_base(val, pll);
 
-       if (pll->flags & TEGRA_PLLM) {
+       if (pll->params->flags & TEGRA_PLLM) {
                val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
                val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
                writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
@@ -326,7 +372,7 @@ static int _get_table_rate(struct clk_hw *hw,
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        struct tegra_clk_pll_freq_table *sel;
 
-       for (sel = pll->freq_table; sel->input_rate != 0; sel++)
+       for (sel = pll->params->freq_table; sel->input_rate != 0; sel++)
                if (sel->input_rate == parent_rate &&
                    sel->output_rate == rate)
                        break;
@@ -389,12 +435,11 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
        if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
            (1 << p_div) > divp_max(pll)
            || cfg->output_rate > pll->params->vco_max) {
-               pr_err("%s: Failed to set %s rate %lu\n",
-                      __func__, __clk_get_name(hw->clk), rate);
-               WARN_ON(1);
                return -EINVAL;
        }
 
+       cfg->output_rate >>= p_div;
+
        if (pll->params->pdiv_tohw) {
                ret = _p_div_to_hw(hw, 1 << p_div);
                if (ret < 0)
@@ -414,7 +459,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
        struct tegra_clk_pll_params *params = pll->params;
        struct div_nmp *div_nmp = params->div_nmp;
 
-       if ((pll->flags & TEGRA_PLLM) &&
+       if ((params->flags & TEGRA_PLLM) &&
                (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
                        PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
                val = pll_override_readl(params->pmc_divp_reg, pll);
@@ -450,7 +495,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
        struct tegra_clk_pll_params *params = pll->params;
        struct div_nmp *div_nmp = params->div_nmp;
 
-       if ((pll->flags & TEGRA_PLLM) &&
+       if ((params->flags & TEGRA_PLLM) &&
                (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
                        PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
                val = pll_override_readl(params->pmc_divp_reg, pll);
@@ -479,11 +524,11 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll,
        val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
        val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
 
-       if (pll->flags & TEGRA_PLL_SET_LFCON) {
+       if (pll->params->flags & TEGRA_PLL_SET_LFCON) {
                val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
                if (cfg->n >= PLLDU_LFCON_SET_DIVN)
                        val |= 1 << PLL_MISC_LFCON_SHIFT;
-       } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+       } else if (pll->params->flags & TEGRA_PLL_SET_DCCON) {
                val &= ~(1 << PLL_MISC_DCCON_SHIFT);
                if (rate >= (pll->params->vco_max >> 1))
                        val |= 1 << PLL_MISC_DCCON_SHIFT;
@@ -505,7 +550,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 
        _update_pll_mnp(pll, cfg);
 
-       if (pll->flags & TEGRA_PLL_HAS_CPCON)
+       if (pll->params->flags & TEGRA_PLL_HAS_CPCON)
                _update_pll_cpcon(pll, cfg, rate);
 
        if (state) {
@@ -524,11 +569,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long flags = 0;
        int ret = 0;
 
-       if (pll->flags & TEGRA_PLL_FIXED) {
-               if (rate != pll->fixed_rate) {
+       if (pll->params->flags & TEGRA_PLL_FIXED) {
+               if (rate != pll->params->fixed_rate) {
                        pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
                                __func__, __clk_get_name(hw->clk),
-                               pll->fixed_rate, rate);
+                               pll->params->fixed_rate, rate);
                        return -EINVAL;
                }
                return 0;
@@ -536,6 +581,8 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
            _calc_rate(hw, &cfg, rate, parent_rate)) {
+               pr_err("%s: Failed to set %s rate %lu\n", __func__,
+                      __clk_get_name(hw->clk), rate);
                WARN_ON(1);
                return -EINVAL;
        }
@@ -559,18 +606,16 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        struct tegra_clk_pll_freq_table cfg;
 
-       if (pll->flags & TEGRA_PLL_FIXED)
-               return pll->fixed_rate;
+       if (pll->params->flags & TEGRA_PLL_FIXED)
+               return pll->params->fixed_rate;
 
        /* PLLM is used for memory; we do not change rate */
-       if (pll->flags & TEGRA_PLLM)
+       if (pll->params->flags & TEGRA_PLLM)
                return __clk_get_rate(hw->clk);
 
        if (_get_table_rate(hw, &cfg, rate, *prate) &&
-           _calc_rate(hw, &cfg, rate, *prate)) {
-               WARN_ON(1);
+           _calc_rate(hw, &cfg, rate, *prate))
                return -EINVAL;
-       }
 
        return cfg.output_rate;
 }
@@ -586,17 +631,19 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 
        val = pll_readl_base(pll);
 
-       if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
+       if ((pll->params->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
                return parent_rate;
 
-       if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
+       if ((pll->params->flags & TEGRA_PLL_FIXED) &&
+                       !(val & PLL_BASE_OVERRIDE)) {
                struct tegra_clk_pll_freq_table sel;
-               if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
+               if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
+                                       parent_rate)) {
                        pr_err("Clock %s has unknown fixed frequency\n",
                               __clk_get_name(hw->clk));
                        BUG();
                }
-               return pll->fixed_rate;
+               return pll->params->fixed_rate;
        }
 
        _get_pll_mnp(pll, &cfg);
@@ -664,7 +711,7 @@ static int clk_plle_enable(struct clk_hw *hw)
        u32 val;
        int err;
 
-       if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+       if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
 
        clk_pll_disable(hw);
@@ -680,7 +727,7 @@ static int clk_plle_enable(struct clk_hw *hw)
                        return err;
        }
 
-       if (pll->flags & TEGRA_PLLE_CONFIGURE) {
+       if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
                /* configure dividers */
                val = pll_readl_base(pll);
                val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
@@ -744,7 +791,7 @@ const struct clk_ops tegra_clk_plle_ops = {
        .enable = clk_plle_enable,
 };
 
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
 
 static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
                           unsigned long parent_rate)
@@ -755,6 +802,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
                return 1;
 }
 
+static unsigned long _clip_vco_min(unsigned long vco_min,
+                                  unsigned long parent_rate)
+{
+       return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate;
+}
+
+static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
+                              void __iomem *clk_base,
+                              unsigned long parent_rate)
+{
+       u32 val;
+       u32 step_a, step_b;
+
+       switch (parent_rate) {
+       case 12000000:
+       case 13000000:
+       case 26000000:
+               step_a = 0x2B;
+               step_b = 0x0B;
+               break;
+       case 16800000:
+               step_a = 0x1A;
+               step_b = 0x09;
+               break;
+       case 19200000:
+               step_a = 0x12;
+               step_b = 0x08;
+               break;
+       default:
+               pr_err("%s: Unexpected reference rate %lu\n",
+                       __func__, parent_rate);
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       val = step_a << pll_params->stepa_shift;
+       val |= step_b << pll_params->stepb_shift;
+       writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
+
+       return 0;
+}
+
 static int clk_pll_iddq_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -1173,7 +1262,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        unsigned long flags = 0;
        unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
 
-       if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+       if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
 
        if (pll->lock)
@@ -1217,6 +1306,18 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        if (ret < 0)
                goto out;
 
+       val = pll_readl(PLLE_SS_CTRL, pll);
+       val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
+       val &= ~PLLE_SS_COEFFICIENTS_MASK;
+       val |= PLLE_SS_COEFFICIENTS_VAL;
+       pll_writel(val, PLLE_SS_CTRL, pll);
+       val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
+       pll_writel(val, PLLE_SS_CTRL, pll);
+       udelay(1);
+       val &= ~PLLE_SS_CNTL_INTERP_RESET;
+       pll_writel(val, PLLE_SS_CTRL, pll);
+       udelay(1);
+
        /* TODO: enable hw control of xusb brick pll */
 
 out:
@@ -1248,9 +1349,8 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw)
 #endif
 
 static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
-               void __iomem *pmc, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+               void __iomem *pmc, struct tegra_clk_pll_params *pll_params,
+               spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
 
@@ -1261,10 +1361,7 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
        pll->clk_base = clk_base;
        pll->pmc = pmc;
 
-       pll->freq_table = freq_table;
        pll->params = pll_params;
-       pll->fixed_rate = fixed_rate;
-       pll->flags = pll_flags;
        pll->lock = lock;
 
        if (!pll_params->div_nmp)
@@ -1293,17 +1390,15 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
 
 struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+               unsigned long flags, struct tegra_clk_pll_params *pll_params,
+               spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
        struct clk *clk;
 
-       pll_flags |= TEGRA_PLL_BYPASS;
-       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       pll_params->flags |= TEGRA_PLL_BYPASS;
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1317,17 +1412,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+               unsigned long flags, struct tegra_clk_pll_params *pll_params,
+               spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
        struct clk *clk;
 
-       pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
-       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1339,7 +1432,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
        return clk;
 }
 
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
 const struct clk_ops tegra_clk_pllxc_ops = {
        .is_enabled = clk_pll_is_enabled,
        .enable = clk_pll_iddq_enable,
@@ -1386,21 +1479,46 @@ const struct clk_ops tegra_clk_plle_tegra114_ops = {
 
 struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
                          void __iomem *clk_base, void __iomem *pmc,
-                         unsigned long flags, unsigned long fixed_rate,
+                         unsigned long flags,
                          struct tegra_clk_pll_params *pll_params,
-                         u32 pll_flags,
-                         struct tegra_clk_pll_freq_table *freq_table,
                          spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
-       struct clk *clk;
+       struct clk *clk, *parent;
+       unsigned long parent_rate;
+       int err;
+       u32 val, val_iddq;
+
+       parent = __clk_lookup(parent_name);
+       if (!parent) {
+               WARN(1, "parent clk %s of %s must be registered first\n",
+                       name, parent_name);
+               return ERR_PTR(-EINVAL);
+       }
 
        if (!pll_params->pdiv_tohw)
                return ERR_PTR(-EINVAL);
 
-       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       parent_rate = __clk_get_rate(parent);
+
+       pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+       err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
+       if (err)
+               return ERR_PTR(err);
+
+       val = readl_relaxed(clk_base + pll_params->base_reg);
+       val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+
+       if (val & PLL_BASE_ENABLE)
+               WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
+       else {
+               val_iddq |= BIT(pll_params->iddq_bit_idx);
+               writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+       }
+
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1414,19 +1532,19 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
 
 struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
                          void __iomem *clk_base, void __iomem *pmc,
-                         unsigned long flags, unsigned long fixed_rate,
+                         unsigned long flags,
                          struct tegra_clk_pll_params *pll_params,
-                         u32 pll_flags,
-                         struct tegra_clk_pll_freq_table *freq_table,
                          spinlock_t *lock, unsigned long parent_rate)
 {
        u32 val;
        struct tegra_clk_pll *pll;
        struct clk *clk;
 
-       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
+
+       pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1461,23 +1579,32 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
 
 struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
                          void __iomem *clk_base, void __iomem *pmc,
-                         unsigned long flags, unsigned long fixed_rate,
+                         unsigned long flags,
                          struct tegra_clk_pll_params *pll_params,
-                         u32 pll_flags,
-                         struct tegra_clk_pll_freq_table *freq_table,
                          spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
-       struct clk *clk;
+       struct clk *clk, *parent;
+       unsigned long parent_rate;
 
        if (!pll_params->pdiv_tohw)
                return ERR_PTR(-EINVAL);
 
-       pll_flags |= TEGRA_PLL_BYPASS;
-       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
-       pll_flags |= TEGRA_PLLM;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       parent = __clk_lookup(parent_name);
+       if (!parent) {
+               WARN(1, "parent clk %s of %s must be registered first\n",
+                       name, parent_name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       parent_rate = __clk_get_rate(parent);
+
+       pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+       pll_params->flags |= TEGRA_PLL_BYPASS;
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll_params->flags |= TEGRA_PLLM;
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1491,10 +1618,8 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
 
 struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
                          void __iomem *clk_base, void __iomem *pmc,
-                         unsigned long flags, unsigned long fixed_rate,
+                         unsigned long flags,
                          struct tegra_clk_pll_params *pll_params,
-                         u32 pll_flags,
-                         struct tegra_clk_pll_freq_table *freq_table,
                          spinlock_t *lock)
 {
        struct clk *parent, *clk;
@@ -1507,20 +1632,21 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
                return ERR_PTR(-EINVAL);
 
        parent = __clk_lookup(parent_name);
-       if (IS_ERR(parent)) {
+       if (!parent) {
                WARN(1, "parent clk %s of %s must be registered first\n",
                        name, parent_name);
                return ERR_PTR(-EINVAL);
        }
 
-       pll_flags |= TEGRA_PLL_BYPASS;
-       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
-                             freq_table, lock);
+       parent_rate = __clk_get_rate(parent);
+
+       pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+       pll_params->flags |= TEGRA_PLL_BYPASS;
+       pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
-       parent_rate = __clk_get_rate(parent);
-
        /*
         * Most of PLLC register fields are shadowed, and can not be read
         * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
@@ -1567,17 +1693,15 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
 struct clk *tegra_clk_register_plle_tegra114(const char *name,
                                const char *parent_name,
                                void __iomem *clk_base, unsigned long flags,
-                               unsigned long fixed_rate,
                                struct tegra_clk_pll_params *pll_params,
-                               struct tegra_clk_pll_freq_table *freq_table,
                                spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
        struct clk *clk;
        u32 val, val_aux;
 
-       pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params,
-                             TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock);
+       pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
@@ -1587,11 +1711,13 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
        val_aux = pll_readl(pll_params->aux_reg, pll);
 
        if (val & PLL_BASE_ENABLE) {
-               if (!(val_aux & PLLE_AUX_PLLRE_SEL))
+               if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
+                       (val_aux & PLLE_AUX_PLLP_SEL))
                        WARN(1, "pll_e enabled with unsupported parent %s\n",
-                         (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
+                         (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
+                                       "pll_re_vco");
        } else {
-               val_aux |= PLLE_AUX_PLLRE_SEL;
+               val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
                pll_writel(val, pll_params->aux_reg, pll);
        }
 
@@ -1603,3 +1729,92 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
        return clk;
 }
 #endif
+
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+const struct clk_ops tegra_clk_pllss_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pll_iddq_enable,
+       .disable = clk_pll_iddq_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_ramp_round_rate,
+       .set_rate = clk_pllxc_set_rate,
+};
+
+struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
+                               void __iomem *clk_base, unsigned long flags,
+                               struct tegra_clk_pll_params *pll_params,
+                               spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk, *parent;
+       struct tegra_clk_pll_freq_table cfg;
+       unsigned long parent_rate;
+       u32 val;
+       int i;
+
+       if (!pll_params->div_nmp)
+               return ERR_PTR(-EINVAL);
+
+       parent = __clk_lookup(parent_name);
+       if (!parent) {
+               WARN(1, "parent clk %s of %s must be registered first\n",
+                       name, parent_name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;
+       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       val = pll_readl_base(pll);
+       val &= ~PLLSS_REF_SRC_SEL_MASK;
+       pll_writel_base(val, pll);
+
+       parent_rate = __clk_get_rate(parent);
+
+       pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+       /* initialize PLL to minimum rate */
+
+       cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+       cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+       for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)
+               ;
+       if (!i) {
+               kfree(pll);
+               return ERR_PTR(-EINVAL);
+       }
+
+       cfg.p = pll_params->pdiv_tohw[i-1].hw_val;
+
+       _update_pll_mnp(pll, &cfg);
+
+       pll_writel_misc(PLLSS_MISC_DEFAULT, pll);
+       pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll);
+       pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll);
+       pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);
+
+       val = pll_readl_base(pll);
+       if (val & PLL_BASE_ENABLE) {
+               if (val & BIT(pll_params->iddq_bit_idx)) {
+                       WARN(1, "%s is on but IDDQ set\n", name);
+                       kfree(pll);
+                       return ERR_PTR(-EINVAL);
+               }
+       } else
+               val |= BIT(pll_params->iddq_bit_idx);
+
+       val &= ~PLLSS_LOCK_OVERRIDE;
+       pll_writel_base(val, pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                       &tegra_clk_pllss_ops);
+
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+#endif
diff --git a/drivers/clk/tegra/clk-tegra-audio.c b/drivers/clk/tegra/clk-tegra-audio.c
new file mode 100644 (file)
index 0000000..5c38aab
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define AUDIO_SYNC_CLK_I2S0 0x4a0
+#define AUDIO_SYNC_CLK_I2S1 0x4a4
+#define AUDIO_SYNC_CLK_I2S2 0x4a8
+#define AUDIO_SYNC_CLK_I2S3 0x4ac
+#define AUDIO_SYNC_CLK_I2S4 0x4b0
+#define AUDIO_SYNC_CLK_SPDIF 0x4b4
+
+#define AUDIO_SYNC_DOUBLER 0x49c
+
+#define PLLA_OUT 0xb4
+
+struct tegra_sync_source_initdata {
+       char            *name;
+       unsigned long   rate;
+       unsigned long   max_rate;
+       int             clk_id;
+};
+
+#define SYNC(_name) \
+       {\
+               .name           = #_name,\
+               .rate           = 24000000,\
+               .max_rate       = 24000000,\
+               .clk_id         = tegra_clk_ ## _name,\
+       }
+
+struct tegra_audio_clk_initdata {
+       char            *gate_name;
+       char            *mux_name;
+       u32             offset;
+       int             gate_clk_id;
+       int             mux_clk_id;
+};
+
+#define AUDIO(_name, _offset) \
+       {\
+               .gate_name      = #_name,\
+               .mux_name       = #_name"_mux",\
+               .offset         = _offset,\
+               .gate_clk_id    = tegra_clk_ ## _name,\
+               .mux_clk_id     = tegra_clk_ ## _name ## _mux,\
+       }
+
+struct tegra_audio2x_clk_initdata {
+       char            *parent;
+       char            *gate_name;
+       char            *name_2x;
+       char            *div_name;
+       int             clk_id;
+       int             clk_num;
+       u8              div_offset;
+};
+
+#define AUDIO2X(_name, _num, _offset) \
+       {\
+               .parent         = #_name,\
+               .gate_name      = #_name"_2x",\
+               .name_2x        = #_name"_doubler",\
+               .div_name       = #_name"_div",\
+               .clk_id         = tegra_clk_ ## _name ## _2x,\
+               .clk_num        = _num,\
+               .div_offset     = _offset,\
+       }
+
+static DEFINE_SPINLOCK(clk_doubler_lock);
+
+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
+       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+
+static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
+       SYNC(spdif_in_sync),
+       SYNC(i2s0_sync),
+       SYNC(i2s1_sync),
+       SYNC(i2s2_sync),
+       SYNC(i2s3_sync),
+       SYNC(i2s4_sync),
+       SYNC(vimclk_sync),
+};
+
+static struct tegra_audio_clk_initdata audio_clks[] = {
+       AUDIO(audio0, AUDIO_SYNC_CLK_I2S0),
+       AUDIO(audio1, AUDIO_SYNC_CLK_I2S1),
+       AUDIO(audio2, AUDIO_SYNC_CLK_I2S2),
+       AUDIO(audio3, AUDIO_SYNC_CLK_I2S3),
+       AUDIO(audio4, AUDIO_SYNC_CLK_I2S4),
+       AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
+};
+
+static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
+       AUDIO2X(audio0, 113, 24),
+       AUDIO2X(audio1, 114, 25),
+       AUDIO2X(audio2, 115, 26),
+       AUDIO2X(audio3, 116, 27),
+       AUDIO2X(audio4, 117, 28),
+       AUDIO2X(spdif, 118, 29),
+};
+
+void __init tegra_audio_clk_init(void __iomem *clk_base,
+                       void __iomem *pmc_base, struct tegra_clk *tegra_clks,
+                       struct tegra_clk_pll_params *pll_a_params)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+       int i;
+
+       /* PLLA */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);
+       if (dt_clk) {
+               clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,
+                               pmc_base, 0, pll_a_params, NULL);
+               *dt_clk = clk;
+       }
+
+       /* PLLA_OUT0 */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks);
+       if (dt_clk) {
+               clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+                               clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                               8, 8, 1, NULL);
+               clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+                               clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               CLK_SET_RATE_PARENT, 0, NULL);
+               *dt_clk = clk;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) {
+               struct tegra_sync_source_initdata *data;
+
+               data = &sync_source_clks[i];
+
+               dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = tegra_clk_register_sync_source(data->name,
+                                       data->rate, data->max_rate);
+               *dt_clk = clk;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {
+               struct tegra_audio_clk_initdata *data;
+
+               data = &audio_clks[i];
+               dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
+
+               if (!dt_clk)
+                       continue;
+               clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,
+                                       ARRAY_SIZE(mux_audio_sync_clk),
+                                       CLK_SET_RATE_NO_REPARENT,
+                                       clk_base + data->offset, 0, 3, 0,
+                                       NULL);
+               *dt_clk = clk;
+
+               dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
+                                       0, clk_base + data->offset, 4,
+                                       CLK_GATE_SET_TO_DISABLE, NULL);
+               *dt_clk = clk;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {
+               struct tegra_audio2x_clk_initdata *data;
+
+               data = &audio2x_clks[i];
+               dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_fixed_factor(NULL, data->name_2x,
+                               data->parent, CLK_SET_RATE_PARENT, 2, 1);
+               clk = tegra_clk_register_divider(data->div_name,
+                               data->name_2x, clk_base + AUDIO_SYNC_DOUBLER,
+                               0, 0, data->div_offset, 1, 0,
+                               &clk_doubler_lock);
+               clk = tegra_clk_register_periph_gate(data->gate_name,
+                               data->div_name, TEGRA_PERIPH_NO_RESET,
+                               clk_base, CLK_SET_RATE_PARENT, data->clk_num,
+                               periph_clk_enb_refcnt);
+               *dt_clk = clk;
+       }
+}
+
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c
new file mode 100644 (file)
index 0000000..f3b7738
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define OSC_CTRL                       0x50
+#define OSC_CTRL_OSC_FREQ_SHIFT                28
+#define OSC_CTRL_PLL_REF_DIV_SHIFT     26
+
+int __init tegra_osc_clk_init(void __iomem *clk_base,
+                               struct tegra_clk *tegra_clks,
+                               unsigned long *input_freqs, int num,
+                               unsigned long *osc_freq,
+                               unsigned long *pll_ref_freq)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+       u32 val, pll_ref_div;
+       unsigned osc_idx;
+
+       val = readl_relaxed(clk_base + OSC_CTRL);
+       osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
+
+       if (osc_idx < num)
+               *osc_freq = input_freqs[osc_idx];
+       else
+               *osc_freq = 0;
+
+       if (!*osc_freq) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);
+       if (!dt_clk)
+               return 0;
+
+       clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
+                                     *osc_freq);
+       *dt_clk = clk;
+
+       /* pll_ref */
+       val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
+       pll_ref_div = 1 << val;
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);
+       if (!dt_clk)
+               return 0;
+
+       clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+                                       0, 1, pll_ref_div);
+       *dt_clk = clk;
+
+       if (pll_ref_freq)
+               *pll_ref_freq = *osc_freq / pll_ref_div;
+
+       return 0;
+}
+
+void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+
+       /* clk_32k */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);
+       if (dt_clk) {
+               clk = clk_register_fixed_rate(NULL, "clk_32k", NULL,
+                                       CLK_IS_ROOT, 32768);
+               *dt_clk = clk;
+       }
+
+       /* clk_m_div2 */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks);
+       if (dt_clk) {
+               clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+               *dt_clk = clk;
+       }
+
+       /* clk_m_div4 */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks);
+       if (dt_clk) {
+               clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
+                                       CLK_SET_RATE_PARENT, 1, 4);
+               *dt_clk = clk;
+       }
+}
+
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
new file mode 100644 (file)
index 0000000..5c35885
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_ADX 0x638
+#define CLK_SOURCE_ADX1 0x670
+#define CLK_SOURCE_AMX 0x63c
+#define CLK_SOURCE_AMX1 0x674
+#define CLK_SOURCE_HDA 0x428
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_SBC5 0x3c8
+#define CLK_SOURCE_SBC6 0x3cc
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_NDSPEED 0x3f8
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_CVE 0x140
+#define CLK_SOURCE_TVO 0x188
+#define CLK_SOURCE_TVDAC 0x194
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_TRACE 0x634
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_I2C6 0x65c
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_MPE 0x170
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_MSENC 0x1f0
+#define CLK_SOURCE_TSEC 0x1f4
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_CILAB 0x614
+#define CLK_SOURCE_CILCD 0x618
+#define CLK_SOURCE_CILE 0x61c
+#define CLK_SOURCE_DSIALP 0x620
+#define CLK_SOURCE_DSIBLP 0x624
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_D_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTERN1 0x3ec
+#define CLK_SOURCE_EXTERN2 0x3f0
+#define CLK_SOURCE_EXTERN3 0x3f4
+#define CLK_SOURCE_I2CSLOW 0x3fc
+#define CLK_SOURCE_SE 0x42c
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_DFLL_REF 0x62c
+#define CLK_SOURCE_DFLL_SOC 0x630
+#define CLK_SOURCE_SOC_THERM 0x644
+#define CLK_SOURCE_XUSB_HOST_SRC 0x600
+#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
+#define CLK_SOURCE_XUSB_FS_SRC 0x608
+#define CLK_SOURCE_XUSB_SS_SRC 0x610
+#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
+#define CLK_SOURCE_ISP 0x144
+#define CLK_SOURCE_SOR0 0x414
+#define CLK_SOURCE_DPAUX 0x418
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_ENTROPY 0x628
+#define CLK_SOURCE_VI_SENSOR2 0x658
+#define CLK_SOURCE_HDMI_AUDIO 0x668
+#define CLK_SOURCE_VIC03 0x678
+#define CLK_SOURCE_CLK72MHZ 0x66c
+
+#define MASK(x) (BIT(x) - 1)
+
+#define MUX(_name, _parents, _offset,  \
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \
+                       _clk_num,  _gate_flags, _clk_id, _parents##_idx, 0,\
+                       NULL)
+
+#define MUX_FLAGS(_name, _parents, _offset,\
+                           _clk_num, _gate_flags, _clk_id, flags)\
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+                       _clk_num, _gate_flags, _clk_id, _parents##_idx, flags,\
+                       NULL)
+
+#define MUX8(_name, _parents, _offset, \
+                            _clk_num, _gate_flags, _clk_id)    \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+                       _clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
+                       NULL)
+
+#define MUX8_NOGATE_LOCK(_name, _parents, _offset, _clk_id, _lock)     \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,     \
+                             29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+                             0, TEGRA_PERIPH_NO_GATE, _clk_id,\
+                             _parents##_idx, 0, _lock)
+
+#define INT(_name, _parents, _offset,  \
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
+                       _clk_id, _parents##_idx, 0, NULL)
+
+#define INT_FLAGS(_name, _parents, _offset,\
+                           _clk_num, _gate_flags, _clk_id, flags)\
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num,  _gate_flags,\
+                       _clk_id, _parents##_idx, flags, NULL)
+
+#define INT8(_name, _parents, _offset,\
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
+                       _clk_id, _parents##_idx, 0, NULL)
+
+#define UART(_name, _parents, _offset,\
+                            _clk_num, _clk_id)                 \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
+                       _parents##_idx, 0, NULL)
+
+#define I2C(_name, _parents, _offset,\
+                            _clk_num, _clk_id)                 \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\
+                       _clk_num, 0, _clk_id, _parents##_idx, 0, NULL)
+
+#define XUSB(_name, _parents, _offset, \
+                            _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
+                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
+                       _clk_id, _parents##_idx, 0, NULL)
+
+#define AUDIO(_name, _offset,  _clk_num,\
+                                _gate_flags, _clk_id)          \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk,       \
+                       _offset, 16, 0xE01F, 0, 0, 8, 1,                \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,  \
+                       _clk_id, mux_d_audio_clk_idx, 0, NULL)
+
+#define NODIV(_name, _parents, _offset, \
+                             _mux_shift, _mux_mask, _clk_num, \
+                             _gate_flags, _clk_id, _lock)              \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+                       _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\
+                       _clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\
+                       _clk_id, _parents##_idx, 0, _lock)
+
+#define GATE(_name, _parent_name,      \
+                            _clk_num, _gate_flags,  _clk_id, _flags)   \
+       {                                                               \
+               .name = _name,                                          \
+               .clk_id = _clk_id,                                      \
+               .p.parent_name = _parent_name,                          \
+               .periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0,         \
+                               _clk_num, _gate_flags, 0, NULL),        \
+               .flags = _flags                                         \
+       }
+
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLP_OUTC 0x67c
+
+#define PLL_BASE_LOCK BIT(27)
+#define PLL_MISC_LOCK_ENABLE 18
+
+static DEFINE_SPINLOCK(PLLP_OUTA_lock);
+static DEFINE_SPINLOCK(PLLP_OUTB_lock);
+static DEFINE_SPINLOCK(PLLP_OUTC_lock);
+static DEFINE_SPINLOCK(sor0_lock);
+
+#define MUX_I2S_SPDIF(_id)                                             \
+static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
+                                                          #_id, "pll_p",\
+                                                          "clk_m"};
+MUX_I2S_SPDIF(audio0)
+MUX_I2S_SPDIF(audio1)
+MUX_I2S_SPDIF(audio2)
+MUX_I2S_SPDIF(audio3)
+MUX_I2S_SPDIF(audio4)
+MUX_I2S_SPDIF(audio)
+
+#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+       "pll_p", "pll_c", "pll_m", "clk_m"
+};
+#define mux_pllp_pllc_pllm_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
+#define mux_pllp_pllc_pllm_idx NULL
+
+static const char *mux_pllp_pllc_clk32_clkm[] = {
+       "pll_p", "pll_c", "clk_32k", "clk_m"
+};
+#define mux_pllp_pllc_clk32_clkm_idx NULL
+
+static const char *mux_plla_pllc_pllp_clkm[] = {
+       "pll_a_out0", "pll_c", "pll_p", "clk_m"
+};
+#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
+       "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
+};
+static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
+       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
+static const char *mux_pllp_clkm[] = {
+       "pll_p", "clk_m"
+};
+static u32 mux_pllp_clkm_idx[] = {
+       [0] = 0, [1] = 3,
+};
+
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+       "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
+
+static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+       "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
+       "pll_d2_out0", "clk_m"
+};
+#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+       "pll_m", "pll_c", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc_clkm[] = {
+       "pll_p", "pll_c", "pll_m"
+};
+static u32 mux_pllp_pllc_clkm_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3,
+};
+
+static const char *mux_pllp_pllc_clkm_clk32[] = {
+       "pll_p", "pll_c", "clk_m", "clk_32k"
+};
+#define mux_pllp_pllc_clkm_clk32_idx NULL
+
+static const char *mux_plla_clk32_pllp_clkm_plle[] = {
+       "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
+};
+#define mux_plla_clk32_pllp_clkm_plle_idx NULL
+
+static const char *mux_clkm_pllp_pllc_pllre[] = {
+       "clk_m", "pll_p", "pll_c", "pll_re_out"
+};
+static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3, [3] = 5,
+};
+
+static const char *mux_clkm_48M_pllp_480M[] = {
+       "clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
+};
+#define mux_clkm_48M_pllp_480M_idx NULL
+
+static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
+       "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
+};
+static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
+};
+
+static const char *mux_d_audio_clk[] = {
+       "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
+       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+static u32 mux_d_audio_clk_idx[] = {
+       [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
+       [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
+};
+
+static const char *mux_pllp_plld_pllc_clkm[] = {
+       "pll_p", "pll_d_out0", "pll_c", "clk_m"
+};
+#define mux_pllp_plld_pllc_clkm_idx NULL
+static const char *mux_pllm_pllc_pllp_plla_clkm_pllc4[] = {
+       "pll_m", "pll_c", "pll_p", "pll_a_out0", "clk_m", "pll_c4",
+};
+static u32 mux_pllm_pllc_pllp_plla_clkm_pllc4_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 6, [5] = 7,
+};
+
+static const char *mux_pllp_clkm1[] = {
+       "pll_p", "clk_m",
+};
+#define mux_pllp_clkm1_idx NULL
+
+static const char *mux_pllp3_pllc_clkm[] = {
+       "pll_p_out3", "pll_c", "pll_c2", "clk_m",
+};
+#define mux_pllp3_pllc_clkm_idx NULL
+
+static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = {
+       "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m"
+};
+static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = {
+       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
+static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = {
+       "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4",
+};
+static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = {
+       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7,
+};
+
+static const char *mux_clkm_plldp_sor0lvds[] = {
+       "clk_m", "pll_dp", "sor0_lvds",
+};
+#define mux_clkm_plldp_sor0lvds_idx NULL
+
+static struct tegra_periph_init_data periph_clks[] = {
+       AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio),
+       AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0),
+       AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, tegra_clk_dam1),
+       AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, tegra_clk_dam2),
+       I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, tegra_clk_i2c1),
+       I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, tegra_clk_i2c2),
+       I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3),
+       I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4),
+       I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5),
+       INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde),
+       INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi),
+       INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp),
+       INT("host1x", mux_pllm_pllc_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x),
+       INT("mpe", mux_pllm_pllc_pllp_plla, CLK_SOURCE_MPE, 60, 0, tegra_clk_mpe),
+       INT("2d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d),
+       INT("3d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d),
+       INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8),
+       INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8),
+       INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9),
+       INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8),
+       INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc),
+       INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec),
+       INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
+       INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
+       INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
+       INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
+       INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
+       INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED),
+       MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0),
+       MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1),
+       MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, tegra_clk_i2s2),
+       MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, tegra_clk_i2s3),
+       MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4),
+       MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out),
+       MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in),
+       MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),
+       MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx),
+       MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx),
+       MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
+       MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
+       MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
+       MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1),
+       MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2),
+       MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3),
+       MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4),
+       MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
+       MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
+       MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
+       MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor),
+       MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi),
+       MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor),
+       MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab),
+       MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd),
+       MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile),
+       MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, tegra_clk_dsialp),
+       MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, tegra_clk_dsiblp),
+       MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tegra_clk_tsensor),
+       MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, tegra_clk_actmon),
+       MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_ref),
+       MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_soc),
+       MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, tegra_clk_i2cslow),
+       MUX("sbc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1),
+       MUX("sbc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2),
+       MUX("sbc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3),
+       MUX("sbc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4),
+       MUX("sbc5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5),
+       MUX("sbc6", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6),
+       MUX("cve", mux_pllp_plld_pllc_clkm, CLK_SOURCE_CVE, 49, 0, tegra_clk_cve),
+       MUX("tvo", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVO, 49, 0, tegra_clk_tvo),
+       MUX("tvdac", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVDAC, 53, 0, tegra_clk_tvdac),
+       MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash),
+       MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed),
+       MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob),
+       MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
+       MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
+       MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
+       MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+       MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
+       MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
+       MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
+       MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8),
+       MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8),
+       MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8),
+       MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
+       MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
+       MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
+       MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1),
+       MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
+       MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
+       MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
+       MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
+       MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
+       MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy),
+       MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
+       MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz),
+       MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock),
+       MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED),
+       NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL),
+       NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL),
+       NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock),
+       UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta),
+       UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
+       UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
+       UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
+       UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte),
+       XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
+       XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
+       XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
+       XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
+       XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
+};
+
+static struct tegra_periph_init_data gate_clks[] = {
+       GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0),
+       GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0),
+       GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0),
+       GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
+       GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
+       GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
+       GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
+       GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
+       GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
+       GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
+       GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
+       GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
+       GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
+       GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0),
+       GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
+       GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
+       GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
+       GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
+       GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
+       GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
+       GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
+       GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),
+       GATE("dtv", "clk_m", 79, TEGRA_PERIPH_ON_APB, tegra_clk_dtv, 0),
+       GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
+       GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
+       GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
+       GATE("dsia", "dsia_mux", 48, 0, tegra_clk_dsia, 0),
+       GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0),
+       GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
+       GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
+       GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
+       GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
+       GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
+       GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
+       GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
+};
+
+struct pll_out_data {
+       char *div_name;
+       char *pll_out_name;
+       u32 offset;
+       int clk_id;
+       u8 div_shift;
+       u8 div_flags;
+       u8 rst_shift;
+       spinlock_t *lock;
+};
+
+#define PLL_OUT(_num, _offset, _div_shift, _div_flags, _rst_shift, _id) \
+       {\
+               .div_name = "pll_p_out" #_num "_div",\
+               .pll_out_name = "pll_p_out" #_num,\
+               .offset = _offset,\
+               .div_shift = _div_shift,\
+               .div_flags = _div_flags | TEGRA_DIVIDER_FIXED |\
+                                       TEGRA_DIVIDER_ROUND_UP,\
+               .rst_shift = _rst_shift,\
+               .clk_id = tegra_clk_ ## _id,\
+               .lock = &_offset ##_lock,\
+       }
+
+static struct pll_out_data pllp_out_clks[] = {
+       PLL_OUT(1, PLLP_OUTA, 8, 0, 0, pll_p_out1),
+       PLL_OUT(2, PLLP_OUTA, 24, 0, 16, pll_p_out2),
+       PLL_OUT(2, PLLP_OUTA, 24, TEGRA_DIVIDER_INT, 16, pll_p_out2_int),
+       PLL_OUT(3, PLLP_OUTB, 8, 0, 0, pll_p_out3),
+       PLL_OUT(4, PLLP_OUTB, 24, 0, 16, pll_p_out4),
+       PLL_OUT(5, PLLP_OUTC, 24, 0, 16, pll_p_out5),
+};
+
+static void __init periph_clk_init(void __iomem *clk_base,
+                               struct tegra_clk *tegra_clks)
+{
+       int i;
+       struct clk *clk;
+       struct clk **dt_clk;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
+               struct tegra_clk_periph_regs *bank;
+               struct tegra_periph_init_data *data;
+
+               data = periph_clks + i;
+
+               dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               bank = get_reg_bank(data->periph.gate.clk_num);
+               if (!bank)
+                       continue;
+
+               data->periph.gate.regs = bank;
+               clk = tegra_clk_register_periph(data->name,
+                       data->p.parent_names, data->num_parents,
+                       &data->periph, clk_base, data->offset,
+                       data->flags);
+               *dt_clk = clk;
+       }
+}
+
+static void __init gate_clk_init(void __iomem *clk_base,
+                               struct tegra_clk *tegra_clks)
+{
+       int i;
+       struct clk *clk;
+       struct clk **dt_clk;
+
+       for (i = 0; i < ARRAY_SIZE(gate_clks); i++) {
+               struct tegra_periph_init_data *data;
+
+               data = gate_clks + i;
+
+               dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = tegra_clk_register_periph_gate(data->name,
+                               data->p.parent_name, data->periph.gate.flags,
+                               clk_base, data->flags,
+                               data->periph.gate.clk_num,
+                               periph_clk_enb_refcnt);
+               *dt_clk = clk;
+       }
+}
+
+static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
+                               struct tegra_clk *tegra_clks,
+                               struct tegra_clk_pll_params *pll_params)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+       int i;
+
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p, tegra_clks);
+       if (dt_clk) {
+               /* PLLP */
+               clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base,
+                                       pmc_base, 0, pll_params, NULL);
+               clk_register_clkdev(clk, "pll_p", NULL);
+               *dt_clk = clk;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(pllp_out_clks); i++) {
+               struct pll_out_data *data;
+
+               data = pllp_out_clks + i;
+
+               dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = tegra_clk_register_divider(data->div_name, "pll_p",
+                               clk_base + data->offset, 0, data->div_flags,
+                               data->div_shift, 8, 1, data->lock);
+               clk = tegra_clk_register_pll_out(data->pll_out_name,
+                               data->div_name, clk_base + data->offset,
+                               data->rst_shift + 1, data->rst_shift,
+                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+                               data->lock);
+               *dt_clk = clk;
+       }
+}
+
+void __init tegra_periph_clk_init(void __iomem *clk_base,
+                       void __iomem *pmc_base, struct tegra_clk *tegra_clks,
+                       struct tegra_clk_pll_params *pll_params)
+{
+       init_pllp(clk_base, pmc_base, tegra_clks, pll_params);
+       periph_clk_init(clk_base, tegra_clks);
+       gate_clk_init(clk_base, tegra_clks);
+}
diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c
new file mode 100644 (file)
index 0000000..08b21c1
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define PMC_CLK_OUT_CNTRL 0x1a8
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_CTRL 0
+#define PMC_CTRL_BLINK_ENB 7
+#define PMC_BLINK_TIMER 0x40
+
+struct pmc_clk_init_data {
+       char *mux_name;
+       char *gate_name;
+       const char **parents;
+       int num_parents;
+       int mux_id;
+       int gate_id;
+       char *dev_name;
+       u8 mux_shift;
+       u8 gate_shift;
+};
+
+#define PMC_CLK(_num, _mux_shift, _gate_shift)\
+       {\
+               .mux_name = "clk_out_" #_num "_mux",\
+               .gate_name = "clk_out_" #_num,\
+               .parents = clk_out ##_num ##_parents,\
+               .num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\
+               .mux_id = tegra_clk_clk_out_ ##_num ##_mux,\
+               .gate_id = tegra_clk_clk_out_ ##_num,\
+               .dev_name = "extern" #_num,\
+               .mux_shift = _mux_shift,\
+               .gate_shift = _gate_shift,\
+       }
+
+static DEFINE_SPINLOCK(clk_out_lock);
+
+static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern1",
+};
+
+static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern2",
+};
+
+static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern3",
+};
+
+static struct pmc_clk_init_data pmc_clks[] = {
+       PMC_CLK(1, 6, 2),
+       PMC_CLK(2, 14, 10),
+       PMC_CLK(3, 22, 18),
+};
+
+void __init tegra_pmc_clk_init(void __iomem *pmc_base,
+                               struct tegra_clk *tegra_clks)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
+               struct pmc_clk_init_data *data;
+
+               data = pmc_clks + i;
+
+               dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_mux(NULL, data->mux_name, data->parents,
+                               data->num_parents, CLK_SET_RATE_NO_REPARENT,
+                               pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
+                               3, 0, &clk_out_lock);
+               *dt_clk = clk;
+
+
+               dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
+                                       0, pmc_base + PMC_CLK_OUT_CNTRL,
+                                       data->gate_shift, 0, &clk_out_lock);
+               *dt_clk = clk;
+               clk_register_clkdev(clk, data->dev_name, data->gate_name);
+       }
+
+       /* blink */
+       writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
+       clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+                               pmc_base + PMC_DPD_PADS_ORIDE,
+                               PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+
+       dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks);
+       if (!dt_clk)
+               return;
+
+       clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+                               pmc_base + PMC_CTRL,
+                               PMC_CTRL_BLINK_ENB, 0, NULL);
+       clk_register_clkdev(clk, "blink", NULL);
+       *dt_clk = clk;
+}
+
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c
new file mode 100644 (file)
index 0000000..05dce4a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+
+#define CCLKG_BURST_POLICY 0x368
+#define CCLKLP_BURST_POLICY 0x370
+#define SCLK_BURST_POLICY 0x028
+#define SYSTEM_CLK_RATE 0x030
+
+static DEFINE_SPINLOCK(sysrate_lock);
+
+static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+                              "pll_p", "pll_p_out2", "unused",
+                              "clk_32k", "pll_m_out1" };
+
+static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+                                       "pll_p", "pll_p_out4", "unused",
+                                       "unused", "pll_x" };
+
+static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+                                        "pll_p", "pll_p_out4", "unused",
+                                        "unused", "pll_x", "pll_x_out0" };
+
+static void __init tegra_sclk_init(void __iomem *clk_base,
+                               struct tegra_clk *tegra_clks)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+
+       /* SCLK */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
+       if (dt_clk) {
+               clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+                                               ARRAY_SIZE(sclk_parents),
+                                               CLK_SET_RATE_PARENT,
+                                               clk_base + SCLK_BURST_POLICY,
+                                               0, 4, 0, 0, NULL);
+               *dt_clk = clk;
+       }
+
+       /* HCLK */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_hclk, tegra_clks);
+       if (dt_clk) {
+               clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+                                  clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
+                                  &sysrate_lock);
+               clk = clk_register_gate(NULL, "hclk", "hclk_div",
+                               CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+                               clk_base + SYSTEM_CLK_RATE,
+                               7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+               *dt_clk = clk;
+       }
+
+       /* PCLK */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pclk, tegra_clks);
+       if (!dt_clk)
+               return;
+
+       clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+                                  clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
+                                  &sysrate_lock);
+       clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
+                               CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+                               3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+       *dt_clk = clk;
+}
+
+void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
+                               void __iomem *pmc_base,
+                               struct tegra_clk *tegra_clks,
+                               struct tegra_clk_pll_params *params)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+
+       /* CCLKG */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
+       if (dt_clk) {
+               clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
+                                       ARRAY_SIZE(cclk_g_parents),
+                                       CLK_SET_RATE_PARENT,
+                                       clk_base + CCLKG_BURST_POLICY,
+                                       0, 4, 0, 0, NULL);
+               *dt_clk = clk;
+       }
+
+       /* CCLKLP */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
+       if (dt_clk) {
+               clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
+                                       ARRAY_SIZE(cclk_lp_parents),
+                                       CLK_SET_RATE_PARENT,
+                                       clk_base + CCLKLP_BURST_POLICY,
+                                       0, 4, 8, 9, NULL);
+               *dt_clk = clk;
+       }
+
+       tegra_sclk_init(clk_base, tegra_clks);
+
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
+       /* PLLX */
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
+       if (!dt_clk)
+               return;
+
+       clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
+                       pmc_base, CLK_IGNORE_UNUSED, params, NULL);
+       *dt_clk = clk;
+
+       /* PLLX_OUT0 */
+
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
+       if (!dt_clk)
+               return;
+       clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       *dt_clk = clk;
+#endif
+}
+
index 9467da7dee4918a60762700442d9685fc658ab3c..90d9d25f2228195308f328a9d7c05c1a5bbe5a40 100644 (file)
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
+#include <dt-bindings/clock/tegra114-car.h>
 
 #include "clk.h"
+#include "clk-id.h"
 
-#define RST_DEVICES_L                  0x004
-#define RST_DEVICES_H                  0x008
-#define RST_DEVICES_U                  0x00C
 #define RST_DFLL_DVCO                  0x2F4
-#define RST_DEVICES_V                  0x358
-#define RST_DEVICES_W                  0x35C
-#define RST_DEVICES_X                  0x28C
-#define RST_DEVICES_SET_L              0x300
-#define RST_DEVICES_CLR_L              0x304
-#define RST_DEVICES_SET_H              0x308
-#define RST_DEVICES_CLR_H              0x30c
-#define RST_DEVICES_SET_U              0x310
-#define RST_DEVICES_CLR_U              0x314
-#define RST_DEVICES_SET_V              0x430
-#define RST_DEVICES_CLR_V              0x434
-#define RST_DEVICES_SET_W              0x438
-#define RST_DEVICES_CLR_W              0x43c
 #define CPU_FINETRIM_SELECT            0x4d4   /* override default prop dlys */
 #define CPU_FINETRIM_DR                        0x4d8   /* rise->rise prop dly A */
 #define CPU_FINETRIM_R                 0x4e4   /* rise->rise prop dly inc A */
-#define RST_DEVICES_NUM                        5
 
 /* RST_DFLL_DVCO bitfields */
 #define DVFS_DFLL_RESET_SHIFT          0
 #define CPU_FINETRIM_R_FCPU_6_SHIFT    10              /* ftop */
 #define CPU_FINETRIM_R_FCPU_6_MASK     (0x3 << CPU_FINETRIM_R_FCPU_6_SHIFT)
 
-#define CLK_OUT_ENB_L                  0x010
-#define CLK_OUT_ENB_H                  0x014
-#define CLK_OUT_ENB_U                  0x018
-#define CLK_OUT_ENB_V                  0x360
-#define CLK_OUT_ENB_W                  0x364
-#define CLK_OUT_ENB_X                  0x280
-#define CLK_OUT_ENB_SET_L              0x320
-#define CLK_OUT_ENB_CLR_L              0x324
-#define CLK_OUT_ENB_SET_H              0x328
-#define CLK_OUT_ENB_CLR_H              0x32c
-#define CLK_OUT_ENB_SET_U              0x330
-#define CLK_OUT_ENB_CLR_U              0x334
-#define CLK_OUT_ENB_SET_V              0x440
-#define CLK_OUT_ENB_CLR_V              0x444
-#define CLK_OUT_ENB_SET_W              0x448
-#define CLK_OUT_ENB_CLR_W              0x44c
-#define CLK_OUT_ENB_SET_X              0x284
-#define CLK_OUT_ENB_CLR_X              0x288
-#define CLK_OUT_ENB_NUM                        6
+#define TEGRA114_CLK_PERIPH_BANKS      5
 
 #define PLLC_BASE 0x80
 #define PLLC_MISC2 0x88
 #define PLLE_AUX 0x48c
 #define PLLC_OUT 0x84
 #define PLLM_OUT 0x94
-#define PLLP_OUTA 0xa4
-#define PLLP_OUTB 0xa8
-#define PLLA_OUT 0xb4
-
-#define AUDIO_SYNC_CLK_I2S0 0x4a0
-#define AUDIO_SYNC_CLK_I2S1 0x4a4
-#define AUDIO_SYNC_CLK_I2S2 0x4a8
-#define AUDIO_SYNC_CLK_I2S3 0x4ac
-#define AUDIO_SYNC_CLK_I2S4 0x4b0
-#define AUDIO_SYNC_CLK_SPDIF 0x4b4
-
-#define AUDIO_SYNC_DOUBLER 0x49c
-
-#define PMC_CLK_OUT_CNTRL 0x1a8
-#define PMC_DPD_PADS_ORIDE 0x1c
-#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
-#define PMC_CTRL 0
-#define PMC_CTRL_BLINK_ENB 7
-#define PMC_BLINK_TIMER 0x40
 
 #define OSC_CTRL                       0x50
 #define OSC_CTRL_OSC_FREQ_SHIFT                28
 #define PLLXC_SW_MAX_P                 6
 
 #define CCLKG_BURST_POLICY 0x368
-#define CCLKLP_BURST_POLICY 0x370
-#define SCLK_BURST_POLICY 0x028
-#define SYSTEM_CLK_RATE 0x030
 
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
 #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE    BIT(1)
 #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL       BIT(0)
 
-#define CLK_SOURCE_I2S0 0x1d8
-#define CLK_SOURCE_I2S1 0x100
-#define CLK_SOURCE_I2S2 0x104
-#define CLK_SOURCE_NDFLASH 0x160
-#define CLK_SOURCE_I2S3 0x3bc
-#define CLK_SOURCE_I2S4 0x3c0
-#define CLK_SOURCE_SPDIF_OUT 0x108
-#define CLK_SOURCE_SPDIF_IN 0x10c
-#define CLK_SOURCE_PWM 0x110
-#define CLK_SOURCE_ADX 0x638
-#define CLK_SOURCE_AMX 0x63c
-#define CLK_SOURCE_HDA 0x428
-#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
-#define CLK_SOURCE_SBC1 0x134
-#define CLK_SOURCE_SBC2 0x118
-#define CLK_SOURCE_SBC3 0x11c
-#define CLK_SOURCE_SBC4 0x1b4
-#define CLK_SOURCE_SBC5 0x3c8
-#define CLK_SOURCE_SBC6 0x3cc
-#define CLK_SOURCE_SATA_OOB 0x420
-#define CLK_SOURCE_SATA 0x424
-#define CLK_SOURCE_NDSPEED 0x3f8
-#define CLK_SOURCE_VFIR 0x168
-#define CLK_SOURCE_SDMMC1 0x150
-#define CLK_SOURCE_SDMMC2 0x154
-#define CLK_SOURCE_SDMMC3 0x1bc
-#define CLK_SOURCE_SDMMC4 0x164
-#define CLK_SOURCE_VDE 0x1c8
 #define CLK_SOURCE_CSITE 0x1d4
-#define CLK_SOURCE_LA 0x1f8
-#define CLK_SOURCE_TRACE 0x634
-#define CLK_SOURCE_OWR 0x1cc
-#define CLK_SOURCE_NOR 0x1d0
-#define CLK_SOURCE_MIPI 0x174
-#define CLK_SOURCE_I2C1 0x124
-#define CLK_SOURCE_I2C2 0x198
-#define CLK_SOURCE_I2C3 0x1b8
-#define CLK_SOURCE_I2C4 0x3c4
-#define CLK_SOURCE_I2C5 0x128
-#define CLK_SOURCE_UARTA 0x178
-#define CLK_SOURCE_UARTB 0x17c
-#define CLK_SOURCE_UARTC 0x1a0
-#define CLK_SOURCE_UARTD 0x1c0
-#define CLK_SOURCE_UARTE 0x1c4
-#define CLK_SOURCE_UARTA_DBG 0x178
-#define CLK_SOURCE_UARTB_DBG 0x17c
-#define CLK_SOURCE_UARTC_DBG 0x1a0
-#define CLK_SOURCE_UARTD_DBG 0x1c0
-#define CLK_SOURCE_UARTE_DBG 0x1c4
-#define CLK_SOURCE_3D 0x158
-#define CLK_SOURCE_2D 0x15c
-#define CLK_SOURCE_VI_SENSOR 0x1a8
-#define CLK_SOURCE_VI 0x148
-#define CLK_SOURCE_EPP 0x16c
-#define CLK_SOURCE_MSENC 0x1f0
-#define CLK_SOURCE_TSEC 0x1f4
-#define CLK_SOURCE_HOST1X 0x180
-#define CLK_SOURCE_HDMI 0x18c
-#define CLK_SOURCE_DISP1 0x138
-#define CLK_SOURCE_DISP2 0x13c
-#define CLK_SOURCE_CILAB 0x614
-#define CLK_SOURCE_CILCD 0x618
-#define CLK_SOURCE_CILE 0x61c
-#define CLK_SOURCE_DSIALP 0x620
-#define CLK_SOURCE_DSIBLP 0x624
-#define CLK_SOURCE_TSENSOR 0x3b8
-#define CLK_SOURCE_D_AUDIO 0x3d0
-#define CLK_SOURCE_DAM0 0x3d8
-#define CLK_SOURCE_DAM1 0x3dc
-#define CLK_SOURCE_DAM2 0x3e0
-#define CLK_SOURCE_ACTMON 0x3e8
-#define CLK_SOURCE_EXTERN1 0x3ec
-#define CLK_SOURCE_EXTERN2 0x3f0
-#define CLK_SOURCE_EXTERN3 0x3f4
-#define CLK_SOURCE_I2CSLOW 0x3fc
-#define CLK_SOURCE_SE 0x42c
-#define CLK_SOURCE_MSELECT 0x3b4
-#define CLK_SOURCE_DFLL_REF 0x62c
-#define CLK_SOURCE_DFLL_SOC 0x630
-#define CLK_SOURCE_SOC_THERM 0x644
-#define CLK_SOURCE_XUSB_HOST_SRC 0x600
-#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
-#define CLK_SOURCE_XUSB_FS_SRC 0x608
 #define CLK_SOURCE_XUSB_SS_SRC 0x610
-#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
 #define CLK_SOURCE_EMC 0x19c
 
 /* PLLM override registers */
@@ -298,19 +160,13 @@ static struct cpu_clk_suspend_context {
 } tegra114_cpu_clk_sctx;
 #endif
 
-static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
-
 static void __iomem *clk_base;
 static void __iomem *pmc_base;
 
 static DEFINE_SPINLOCK(pll_d_lock);
 static DEFINE_SPINLOCK(pll_d2_lock);
 static DEFINE_SPINLOCK(pll_u_lock);
-static DEFINE_SPINLOCK(pll_div_lock);
 static DEFINE_SPINLOCK(pll_re_lock);
-static DEFINE_SPINLOCK(clk_doubler_lock);
-static DEFINE_SPINLOCK(clk_out_lock);
-static DEFINE_SPINLOCK(sysrate_lock);
 
 static struct div_nmp pllxc_nmp = {
        .divm_shift = 0,
@@ -370,6 +226,8 @@ static struct tegra_clk_pll_params pll_c_params = {
        .stepb_shift = 9,
        .pdiv_tohw = pllxc_p,
        .div_nmp = &pllxc_nmp,
+       .freq_table = pll_c_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct div_nmp pllcx_nmp = {
@@ -417,6 +275,8 @@ static struct tegra_clk_pll_params pll_c2_params = {
        .ext_misc_reg[0] = 0x4f0,
        .ext_misc_reg[1] = 0x4f4,
        .ext_misc_reg[2] = 0x4f8,
+       .freq_table = pll_cx_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_c3_params = {
@@ -437,6 +297,8 @@ static struct tegra_clk_pll_params pll_c3_params = {
        .ext_misc_reg[0] = 0x504,
        .ext_misc_reg[1] = 0x508,
        .ext_misc_reg[2] = 0x50c,
+       .freq_table = pll_cx_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct div_nmp pllm_nmp = {
@@ -483,6 +345,8 @@ static struct tegra_clk_pll_params pll_m_params = {
        .div_nmp = &pllm_nmp,
        .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
        .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
+       .freq_table = pll_m_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct div_nmp pllp_nmp = {
@@ -516,6 +380,9 @@ static struct tegra_clk_pll_params pll_p_params = {
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .div_nmp = &pllp_nmp,
+       .freq_table = pll_p_freq_table,
+       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+       .fixed_rate = 408000000,
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
@@ -543,6 +410,8 @@ static struct tegra_clk_pll_params pll_a_params = {
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .div_nmp = &pllp_nmp,
+       .freq_table = pll_a_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
@@ -579,6 +448,9 @@ static struct tegra_clk_pll_params pll_d_params = {
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .div_nmp = &pllp_nmp,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_d2_params = {
@@ -594,6 +466,9 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .div_nmp = &pllp_nmp,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
 };
 
 static struct pdiv_map pllu_p[] = {
@@ -634,6 +509,9 @@ static struct tegra_clk_pll_params pll_u_params = {
        .lock_delay = 1000,
        .pdiv_tohw = pllu_p,
        .div_nmp = &pllu_nmp,
+       .freq_table = pll_u_freq_table,
+       .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
@@ -667,12 +545,15 @@ static struct tegra_clk_pll_params pll_x_params = {
        .stepb_shift = 24,
        .pdiv_tohw = pllxc_p,
        .div_nmp = &pllxc_nmp,
+       .freq_table = pll_x_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
        /* PLLE special case: use cpcon field to store cml divider value */
        {336000000, 100000000, 100, 21, 16, 11},
        {312000000, 100000000, 200, 26, 24, 13},
+       {12000000, 100000000, 200,  1,  24, 13},
        {0, 0, 0, 0, 0, 0},
 };
 
@@ -699,6 +580,9 @@ static struct tegra_clk_pll_params pll_e_params = {
        .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .div_nmp = &plle_nmp,
+       .freq_table = pll_e_freq_table,
+       .flags = TEGRA_PLL_FIXED,
+       .fixed_rate = 100000000,
 };
 
 static struct div_nmp pllre_nmp = {
@@ -725,53 +609,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
        .iddq_reg = PLLRE_MISC,
        .iddq_bit_idx = PLLRE_IDDQ_BIT,
        .div_nmp = &pllre_nmp,
-};
-
-/* Peripheral clock registers */
-
-static struct tegra_clk_periph_regs periph_l_regs = {
-       .enb_reg = CLK_OUT_ENB_L,
-       .enb_set_reg = CLK_OUT_ENB_SET_L,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_L,
-       .rst_reg = RST_DEVICES_L,
-       .rst_set_reg = RST_DEVICES_SET_L,
-       .rst_clr_reg = RST_DEVICES_CLR_L,
-};
-
-static struct tegra_clk_periph_regs periph_h_regs = {
-       .enb_reg = CLK_OUT_ENB_H,
-       .enb_set_reg = CLK_OUT_ENB_SET_H,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_H,
-       .rst_reg = RST_DEVICES_H,
-       .rst_set_reg = RST_DEVICES_SET_H,
-       .rst_clr_reg = RST_DEVICES_CLR_H,
-};
-
-static struct tegra_clk_periph_regs periph_u_regs = {
-       .enb_reg = CLK_OUT_ENB_U,
-       .enb_set_reg = CLK_OUT_ENB_SET_U,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_U,
-       .rst_reg = RST_DEVICES_U,
-       .rst_set_reg = RST_DEVICES_SET_U,
-       .rst_clr_reg = RST_DEVICES_CLR_U,
-};
-
-static struct tegra_clk_periph_regs periph_v_regs = {
-       .enb_reg = CLK_OUT_ENB_V,
-       .enb_set_reg = CLK_OUT_ENB_SET_V,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_V,
-       .rst_reg = RST_DEVICES_V,
-       .rst_set_reg = RST_DEVICES_SET_V,
-       .rst_clr_reg = RST_DEVICES_CLR_V,
-};
-
-static struct tegra_clk_periph_regs periph_w_regs = {
-       .enb_reg = CLK_OUT_ENB_W,
-       .enb_set_reg = CLK_OUT_ENB_SET_W,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_W,
-       .rst_reg = RST_DEVICES_W,
-       .rst_set_reg = RST_DEVICES_SET_W,
-       .rst_clr_reg = RST_DEVICES_CLR_W,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 /* possible OSC frequencies in Hz */
@@ -787,120 +625,6 @@ static unsigned long tegra114_input_freq[] = {
 
 #define MASK(x) (BIT(x) - 1)
 
-#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num,    \
-                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
-                       _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
-                           _clk_num, _regs, _gate_flags, _clk_id, flags)\
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num,    \
-                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
-                       _parents##_idx, flags)
-
-#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
-                            _clk_num, _regs, _gate_flags, _clk_id)     \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num,    \
-                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
-                       _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id, _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
-                           _clk_num, _regs, _gate_flags, _clk_id, flags)\
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id, _parents##_idx, flags)
-
-#define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id, _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
-                            _clk_num, _regs, _clk_id)                  \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\
-                       _clk_num, periph_clk_enb_refcnt, 0, _clk_id,    \
-                       _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\
-                            _clk_num, _regs, _clk_id)                  \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num,   \
-                       periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
-                             _mux_shift, _mux_mask, _clk_num, _regs,   \
-                             _gate_flags, _clk_id)                     \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
-                       _mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs,    \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id, _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \
-                            _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \
-                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,    \
-                       _clk_id, _parents##_idx, 0)
-
-#define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset,  _clk_num,\
-                                _regs, _gate_flags, _clk_id)           \
-       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \
-                       _offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \
-                       periph_clk_enb_refcnt, _gate_flags , _clk_id,   \
-                       mux_d_audio_clk_idx, 0)
-
-enum tegra114_clk {
-       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
-       ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19,
-       gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27,
-       host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40,
-       sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48,
-       mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56,
-       emc, usb2, usb3, vde = 61, bsea = 62, bsev = 63, uartd = 65,
-       i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73,
-       la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80,
-       i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91,
-       csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102,
-       i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1,
-       dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,
-       audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120,
-       extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128,
-       cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148,
-       dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192,
-       vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k,
-       clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2,
-       pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3,
-       pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0,
-       pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0,
-       pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync,
-       i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0,
-       audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
-       blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src,
-       xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
-       dfll_ref = 264, dfll_soc,
-
-       /* Mux clocks */
-
-       audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux,
-       spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux,
-       dsib_mux, clk_max,
-};
-
 struct utmi_clk_param {
        /* Oscillator Frequency in KHz */
        u32 osc_frequency;
@@ -934,122 +658,11 @@ static const struct utmi_clk_param utmi_parameters[] = {
 
 /* peripheral mux definitions */
 
-#define MUX_I2S_SPDIF(_id)                                             \
-static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
-                                                          #_id, "pll_p",\
-                                                          "clk_m"};
-MUX_I2S_SPDIF(audio0)
-MUX_I2S_SPDIF(audio1)
-MUX_I2S_SPDIF(audio2)
-MUX_I2S_SPDIF(audio3)
-MUX_I2S_SPDIF(audio4)
-MUX_I2S_SPDIF(audio)
-
-#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
-#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
-#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
-#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
-#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
-#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
-
-static const char *mux_pllp_pllc_pllm_clkm[] = {
-       "pll_p", "pll_c", "pll_m", "clk_m"
-};
-#define mux_pllp_pllc_pllm_clkm_idx NULL
-
-static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
-#define mux_pllp_pllc_pllm_idx NULL
-
-static const char *mux_pllp_pllc_clk32_clkm[] = {
-       "pll_p", "pll_c", "clk_32k", "clk_m"
-};
-#define mux_pllp_pllc_clk32_clkm_idx NULL
-
-static const char *mux_plla_pllc_pllp_clkm[] = {
-       "pll_a_out0", "pll_c", "pll_p", "clk_m"
-};
-#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
-
-static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
-       "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
-};
-static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
-       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
-};
-
-static const char *mux_pllp_clkm[] = {
-       "pll_p", "clk_m"
-};
-static u32 mux_pllp_clkm_idx[] = {
-       [0] = 0, [1] = 3,
-};
-
-static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
-       "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
-};
-#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
-
-static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
-       "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
-       "pll_d2_out0", "clk_m"
-};
-#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
-
-static const char *mux_pllm_pllc_pllp_plla[] = {
-       "pll_m", "pll_c", "pll_p", "pll_a_out0"
-};
-#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
-
-static const char *mux_pllp_pllc_clkm[] = {
-       "pll_p", "pll_c", "pll_m"
-};
-static u32 mux_pllp_pllc_clkm_idx[] = {
-       [0] = 0, [1] = 1, [2] = 3,
-};
-
-static const char *mux_pllp_pllc_clkm_clk32[] = {
-       "pll_p", "pll_c", "clk_m", "clk_32k"
-};
-#define mux_pllp_pllc_clkm_clk32_idx NULL
-
-static const char *mux_plla_clk32_pllp_clkm_plle[] = {
-       "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
-};
-#define mux_plla_clk32_pllp_clkm_plle_idx NULL
-
-static const char *mux_clkm_pllp_pllc_pllre[] = {
-       "clk_m", "pll_p", "pll_c", "pll_re_out"
-};
-static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
-       [0] = 0, [1] = 1, [2] = 3, [3] = 5,
-};
-
-static const char *mux_clkm_48M_pllp_480M[] = {
-       "clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
-};
-#define mux_clkm_48M_pllp_480M_idx NULL
-
-static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
-       "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
-};
-static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
-       [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
-};
-
 static const char *mux_plld_out0_plld2_out0[] = {
        "pll_d_out0", "pll_d2_out0",
 };
 #define mux_plld_out0_plld2_out0_idx NULL
 
-static const char *mux_d_audio_clk[] = {
-       "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
-       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
-};
-static u32 mux_d_audio_clk_idx[] = {
-       [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
-       [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
-};
-
 static const char *mux_pllmcp_clkm[] = {
        "pll_m_out0", "pll_c_out0", "pll_p_out0", "clk_m", "pll_m_ud",
 };
@@ -1064,8 +677,253 @@ static const struct clk_div_table pll_re_div_table[] = {
        { .val = 0, .div = 0 },
 };
 
-static struct clk *clks[clk_max];
-static struct clk_onecell_data clk_data;
+static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
+       [tegra_clk_rtc] = { .dt_id = TEGRA114_CLK_RTC, .present = true },
+       [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true },
+       [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true },
+       [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true },
+       [tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true },
+       [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true },
+       [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true },
+       [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true },
+       [tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true },
+       [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true },
+       [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true },
+       [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true },
+       [tegra_clk_epp_8] = { .dt_id = TEGRA114_CLK_EPP, .present = true },
+       [tegra_clk_gr2d_8] = { .dt_id = TEGRA114_CLK_GR2D, .present = true },
+       [tegra_clk_usbd] = { .dt_id = TEGRA114_CLK_USBD, .present = true },
+       [tegra_clk_isp] = { .dt_id = TEGRA114_CLK_ISP, .present = true },
+       [tegra_clk_gr3d_8] = { .dt_id = TEGRA114_CLK_GR3D, .present = true },
+       [tegra_clk_disp2] = { .dt_id = TEGRA114_CLK_DISP2, .present = true },
+       [tegra_clk_disp1] = { .dt_id = TEGRA114_CLK_DISP1, .present = true },
+       [tegra_clk_host1x_8] = { .dt_id = TEGRA114_CLK_HOST1X, .present = true },
+       [tegra_clk_vcp] = { .dt_id = TEGRA114_CLK_VCP, .present = true },
+       [tegra_clk_apbdma] = { .dt_id = TEGRA114_CLK_APBDMA, .present = true },
+       [tegra_clk_kbc] = { .dt_id = TEGRA114_CLK_KBC, .present = true },
+       [tegra_clk_kfuse] = { .dt_id = TEGRA114_CLK_KFUSE, .present = true },
+       [tegra_clk_sbc1_8] = { .dt_id = TEGRA114_CLK_SBC1, .present = true },
+       [tegra_clk_nor] = { .dt_id = TEGRA114_CLK_NOR, .present = true },
+       [tegra_clk_sbc2_8] = { .dt_id = TEGRA114_CLK_SBC2, .present = true },
+       [tegra_clk_sbc3_8] = { .dt_id = TEGRA114_CLK_SBC3, .present = true },
+       [tegra_clk_i2c5] = { .dt_id = TEGRA114_CLK_I2C5, .present = true },
+       [tegra_clk_dsia] = { .dt_id = TEGRA114_CLK_DSIA, .present = true },
+       [tegra_clk_mipi] = { .dt_id = TEGRA114_CLK_MIPI, .present = true },
+       [tegra_clk_hdmi] = { .dt_id = TEGRA114_CLK_HDMI, .present = true },
+       [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true },
+       [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true },
+       [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true },
+       [tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true },
+       [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true },
+       [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true },
+       [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true },
+       [tegra_clk_vde_8] = { .dt_id = TEGRA114_CLK_VDE, .present = true },
+       [tegra_clk_bsea] = { .dt_id = TEGRA114_CLK_BSEA, .present = true },
+       [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true },
+       [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true },
+       [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true },
+       [tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true },
+       [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true },
+       [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true },
+       [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true },
+       [tegra_clk_trace] = { .dt_id = TEGRA114_CLK_TRACE, .present = true },
+       [tegra_clk_soc_therm] = { .dt_id = TEGRA114_CLK_SOC_THERM, .present = true },
+       [tegra_clk_dtv] = { .dt_id = TEGRA114_CLK_DTV, .present = true },
+       [tegra_clk_ndspeed] = { .dt_id = TEGRA114_CLK_NDSPEED, .present = true },
+       [tegra_clk_i2cslow] = { .dt_id = TEGRA114_CLK_I2CSLOW, .present = true },
+       [tegra_clk_dsib] = { .dt_id = TEGRA114_CLK_DSIB, .present = true },
+       [tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true },
+       [tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true },
+       [tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true },
+       [tegra_clk_csus] = { .dt_id = TEGRA114_CLK_CSUS, .present = true },
+       [tegra_clk_mselect] = { .dt_id = TEGRA114_CLK_MSELECT, .present = true },
+       [tegra_clk_tsensor] = { .dt_id = TEGRA114_CLK_TSENSOR, .present = true },
+       [tegra_clk_i2s3] = { .dt_id = TEGRA114_CLK_I2S3, .present = true },
+       [tegra_clk_i2s4] = { .dt_id = TEGRA114_CLK_I2S4, .present = true },
+       [tegra_clk_i2c4] = { .dt_id = TEGRA114_CLK_I2C4, .present = true },
+       [tegra_clk_sbc5_8] = { .dt_id = TEGRA114_CLK_SBC5, .present = true },
+       [tegra_clk_sbc6_8] = { .dt_id = TEGRA114_CLK_SBC6, .present = true },
+       [tegra_clk_d_audio] = { .dt_id = TEGRA114_CLK_D_AUDIO, .present = true },
+       [tegra_clk_apbif] = { .dt_id = TEGRA114_CLK_APBIF, .present = true },
+       [tegra_clk_dam0] = { .dt_id = TEGRA114_CLK_DAM0, .present = true },
+       [tegra_clk_dam1] = { .dt_id = TEGRA114_CLK_DAM1, .present = true },
+       [tegra_clk_dam2] = { .dt_id = TEGRA114_CLK_DAM2, .present = true },
+       [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA114_CLK_HDA2CODEC_2X, .present = true },
+       [tegra_clk_audio0_2x] = { .dt_id = TEGRA114_CLK_AUDIO0_2X, .present = true },
+       [tegra_clk_audio1_2x] = { .dt_id = TEGRA114_CLK_AUDIO1_2X, .present = true },
+       [tegra_clk_audio2_2x] = { .dt_id = TEGRA114_CLK_AUDIO2_2X, .present = true },
+       [tegra_clk_audio3_2x] = { .dt_id = TEGRA114_CLK_AUDIO3_2X, .present = true },
+       [tegra_clk_audio4_2x] = { .dt_id = TEGRA114_CLK_AUDIO4_2X, .present = true },
+       [tegra_clk_spdif_2x] = { .dt_id = TEGRA114_CLK_SPDIF_2X, .present = true },
+       [tegra_clk_actmon] = { .dt_id = TEGRA114_CLK_ACTMON, .present = true },
+       [tegra_clk_extern1] = { .dt_id = TEGRA114_CLK_EXTERN1, .present = true },
+       [tegra_clk_extern2] = { .dt_id = TEGRA114_CLK_EXTERN2, .present = true },
+       [tegra_clk_extern3] = { .dt_id = TEGRA114_CLK_EXTERN3, .present = true },
+       [tegra_clk_hda] = { .dt_id = TEGRA114_CLK_HDA, .present = true },
+       [tegra_clk_se] = { .dt_id = TEGRA114_CLK_SE, .present = true },
+       [tegra_clk_hda2hdmi] = { .dt_id = TEGRA114_CLK_HDA2HDMI, .present = true },
+       [tegra_clk_cilab] = { .dt_id = TEGRA114_CLK_CILAB, .present = true },
+       [tegra_clk_cilcd] = { .dt_id = TEGRA114_CLK_CILCD, .present = true },
+       [tegra_clk_cile] = { .dt_id = TEGRA114_CLK_CILE, .present = true },
+       [tegra_clk_dsialp] = { .dt_id = TEGRA114_CLK_DSIALP, .present = true },
+       [tegra_clk_dsiblp] = { .dt_id = TEGRA114_CLK_DSIBLP, .present = true },
+       [tegra_clk_dds] = { .dt_id = TEGRA114_CLK_DDS, .present = true },
+       [tegra_clk_dp2] = { .dt_id = TEGRA114_CLK_DP2, .present = true },
+       [tegra_clk_amx] = { .dt_id = TEGRA114_CLK_AMX, .present = true },
+       [tegra_clk_adx] = { .dt_id = TEGRA114_CLK_ADX, .present = true },
+       [tegra_clk_xusb_ss] = { .dt_id = TEGRA114_CLK_XUSB_SS, .present = true },
+       [tegra_clk_uartb] = { .dt_id = TEGRA114_CLK_UARTB, .present = true },
+       [tegra_clk_vfir] = { .dt_id = TEGRA114_CLK_VFIR, .present = true },
+       [tegra_clk_spdif_in] = { .dt_id = TEGRA114_CLK_SPDIF_IN, .present = true },
+       [tegra_clk_spdif_out] = { .dt_id = TEGRA114_CLK_SPDIF_OUT, .present = true },
+       [tegra_clk_vi_8] = { .dt_id = TEGRA114_CLK_VI, .present = true },
+       [tegra_clk_vi_sensor_8] = { .dt_id = TEGRA114_CLK_VI_SENSOR, .present = true },
+       [tegra_clk_fuse] = { .dt_id = TEGRA114_CLK_FUSE, .present = true },
+       [tegra_clk_fuse_burn] = { .dt_id = TEGRA114_CLK_FUSE_BURN, .present = true },
+       [tegra_clk_clk_32k] = { .dt_id = TEGRA114_CLK_CLK_32K, .present = true },
+       [tegra_clk_clk_m] = { .dt_id = TEGRA114_CLK_CLK_M, .present = true },
+       [tegra_clk_clk_m_div2] = { .dt_id = TEGRA114_CLK_CLK_M_DIV2, .present = true },
+       [tegra_clk_clk_m_div4] = { .dt_id = TEGRA114_CLK_CLK_M_DIV4, .present = true },
+       [tegra_clk_pll_ref] = { .dt_id = TEGRA114_CLK_PLL_REF, .present = true },
+       [tegra_clk_pll_c] = { .dt_id = TEGRA114_CLK_PLL_C, .present = true },
+       [tegra_clk_pll_c_out1] = { .dt_id = TEGRA114_CLK_PLL_C_OUT1, .present = true },
+       [tegra_clk_pll_c2] = { .dt_id = TEGRA114_CLK_PLL_C2, .present = true },
+       [tegra_clk_pll_c3] = { .dt_id = TEGRA114_CLK_PLL_C3, .present = true },
+       [tegra_clk_pll_m] = { .dt_id = TEGRA114_CLK_PLL_M, .present = true },
+       [tegra_clk_pll_m_out1] = { .dt_id = TEGRA114_CLK_PLL_M_OUT1, .present = true },
+       [tegra_clk_pll_p] = { .dt_id = TEGRA114_CLK_PLL_P, .present = true },
+       [tegra_clk_pll_p_out1] = { .dt_id = TEGRA114_CLK_PLL_P_OUT1, .present = true },
+       [tegra_clk_pll_p_out2_int] = { .dt_id = TEGRA114_CLK_PLL_P_OUT2, .present = true },
+       [tegra_clk_pll_p_out3] = { .dt_id = TEGRA114_CLK_PLL_P_OUT3, .present = true },
+       [tegra_clk_pll_p_out4] = { .dt_id = TEGRA114_CLK_PLL_P_OUT4, .present = true },
+       [tegra_clk_pll_a] = { .dt_id = TEGRA114_CLK_PLL_A, .present = true },
+       [tegra_clk_pll_a_out0] = { .dt_id = TEGRA114_CLK_PLL_A_OUT0, .present = true },
+       [tegra_clk_pll_d] = { .dt_id = TEGRA114_CLK_PLL_D, .present = true },
+       [tegra_clk_pll_d_out0] = { .dt_id = TEGRA114_CLK_PLL_D_OUT0, .present = true },
+       [tegra_clk_pll_d2] = { .dt_id = TEGRA114_CLK_PLL_D2, .present = true },
+       [tegra_clk_pll_d2_out0] = { .dt_id = TEGRA114_CLK_PLL_D2_OUT0, .present = true },
+       [tegra_clk_pll_u] = { .dt_id = TEGRA114_CLK_PLL_U, .present = true },
+       [tegra_clk_pll_u_480m] = { .dt_id = TEGRA114_CLK_PLL_U_480M, .present = true },
+       [tegra_clk_pll_u_60m] = { .dt_id = TEGRA114_CLK_PLL_U_60M, .present = true },
+       [tegra_clk_pll_u_48m] = { .dt_id = TEGRA114_CLK_PLL_U_48M, .present = true },
+       [tegra_clk_pll_u_12m] = { .dt_id = TEGRA114_CLK_PLL_U_12M, .present = true },
+       [tegra_clk_pll_x] = { .dt_id = TEGRA114_CLK_PLL_X, .present = true },
+       [tegra_clk_pll_x_out0] = { .dt_id = TEGRA114_CLK_PLL_X_OUT0, .present = true },
+       [tegra_clk_pll_re_vco] = { .dt_id = TEGRA114_CLK_PLL_RE_VCO, .present = true },
+       [tegra_clk_pll_re_out] = { .dt_id = TEGRA114_CLK_PLL_RE_OUT, .present = true },
+       [tegra_clk_pll_e_out0] = { .dt_id = TEGRA114_CLK_PLL_E_OUT0, .present = true },
+       [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA114_CLK_SPDIF_IN_SYNC, .present = true },
+       [tegra_clk_i2s0_sync] = { .dt_id = TEGRA114_CLK_I2S0_SYNC, .present = true },
+       [tegra_clk_i2s1_sync] = { .dt_id = TEGRA114_CLK_I2S1_SYNC, .present = true },
+       [tegra_clk_i2s2_sync] = { .dt_id = TEGRA114_CLK_I2S2_SYNC, .present = true },
+       [tegra_clk_i2s3_sync] = { .dt_id = TEGRA114_CLK_I2S3_SYNC, .present = true },
+       [tegra_clk_i2s4_sync] = { .dt_id = TEGRA114_CLK_I2S4_SYNC, .present = true },
+       [tegra_clk_vimclk_sync] = { .dt_id = TEGRA114_CLK_VIMCLK_SYNC, .present = true },
+       [tegra_clk_audio0] = { .dt_id = TEGRA114_CLK_AUDIO0, .present = true },
+       [tegra_clk_audio1] = { .dt_id = TEGRA114_CLK_AUDIO1, .present = true },
+       [tegra_clk_audio2] = { .dt_id = TEGRA114_CLK_AUDIO2, .present = true },
+       [tegra_clk_audio3] = { .dt_id = TEGRA114_CLK_AUDIO3, .present = true },
+       [tegra_clk_audio4] = { .dt_id = TEGRA114_CLK_AUDIO4, .present = true },
+       [tegra_clk_spdif] = { .dt_id = TEGRA114_CLK_SPDIF, .present = true },
+       [tegra_clk_clk_out_1] = { .dt_id = TEGRA114_CLK_CLK_OUT_1, .present = true },
+       [tegra_clk_clk_out_2] = { .dt_id = TEGRA114_CLK_CLK_OUT_2, .present = true },
+       [tegra_clk_clk_out_3] = { .dt_id = TEGRA114_CLK_CLK_OUT_3, .present = true },
+       [tegra_clk_blink] = { .dt_id = TEGRA114_CLK_BLINK, .present = true },
+       [tegra_clk_xusb_host_src] = { .dt_id = TEGRA114_CLK_XUSB_HOST_SRC, .present = true },
+       [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA114_CLK_XUSB_FALCON_SRC, .present = true },
+       [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA114_CLK_XUSB_FS_SRC, .present = true },
+       [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA114_CLK_XUSB_SS_SRC, .present = true },
+       [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA114_CLK_XUSB_DEV_SRC, .present = true },
+       [tegra_clk_xusb_dev] = { .dt_id = TEGRA114_CLK_XUSB_DEV, .present = true },
+       [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA114_CLK_XUSB_HS_SRC, .present = true },
+       [tegra_clk_sclk] = { .dt_id = TEGRA114_CLK_SCLK, .present = true },
+       [tegra_clk_hclk] = { .dt_id = TEGRA114_CLK_HCLK, .present = true },
+       [tegra_clk_pclk] = { .dt_id = TEGRA114_CLK_PCLK, .present = true },
+       [tegra_clk_cclk_g] = { .dt_id = TEGRA114_CLK_CCLK_G, .present = true },
+       [tegra_clk_cclk_lp] = { .dt_id = TEGRA114_CLK_CCLK_LP, .present = true },
+       [tegra_clk_dfll_ref] = { .dt_id = TEGRA114_CLK_DFLL_REF, .present = true },
+       [tegra_clk_dfll_soc] = { .dt_id = TEGRA114_CLK_DFLL_SOC, .present = true },
+       [tegra_clk_audio0_mux] = { .dt_id = TEGRA114_CLK_AUDIO0_MUX, .present = true },
+       [tegra_clk_audio1_mux] = { .dt_id = TEGRA114_CLK_AUDIO1_MUX, .present = true },
+       [tegra_clk_audio2_mux] = { .dt_id = TEGRA114_CLK_AUDIO2_MUX, .present = true },
+       [tegra_clk_audio3_mux] = { .dt_id = TEGRA114_CLK_AUDIO3_MUX, .present = true },
+       [tegra_clk_audio4_mux] = { .dt_id = TEGRA114_CLK_AUDIO4_MUX, .present = true },
+       [tegra_clk_spdif_mux] = { .dt_id = TEGRA114_CLK_SPDIF_MUX, .present = true },
+       [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_1_MUX, .present = true },
+       [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_2_MUX, .present = true },
+       [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true },
+       [tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true },
+       [tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true },
+};
+
+static struct tegra_devclk devclks[] __initdata = {
+       { .con_id = "clk_m", .dt_id = TEGRA114_CLK_CLK_M },
+       { .con_id = "pll_ref", .dt_id = TEGRA114_CLK_PLL_REF },
+       { .con_id = "clk_32k", .dt_id = TEGRA114_CLK_CLK_32K },
+       { .con_id = "clk_m_div2", .dt_id = TEGRA114_CLK_CLK_M_DIV2 },
+       { .con_id = "clk_m_div4", .dt_id = TEGRA114_CLK_CLK_M_DIV4 },
+       { .con_id = "pll_c", .dt_id = TEGRA114_CLK_PLL_C },
+       { .con_id = "pll_c_out1", .dt_id = TEGRA114_CLK_PLL_C_OUT1 },
+       { .con_id = "pll_c2", .dt_id = TEGRA114_CLK_PLL_C2 },
+       { .con_id = "pll_c3", .dt_id = TEGRA114_CLK_PLL_C3 },
+       { .con_id = "pll_p", .dt_id = TEGRA114_CLK_PLL_P },
+       { .con_id = "pll_p_out1", .dt_id = TEGRA114_CLK_PLL_P_OUT1 },
+       { .con_id = "pll_p_out2", .dt_id = TEGRA114_CLK_PLL_P_OUT2 },
+       { .con_id = "pll_p_out3", .dt_id = TEGRA114_CLK_PLL_P_OUT3 },
+       { .con_id = "pll_p_out4", .dt_id = TEGRA114_CLK_PLL_P_OUT4 },
+       { .con_id = "pll_m", .dt_id = TEGRA114_CLK_PLL_M },
+       { .con_id = "pll_m_out1", .dt_id = TEGRA114_CLK_PLL_M_OUT1 },
+       { .con_id = "pll_x", .dt_id = TEGRA114_CLK_PLL_X },
+       { .con_id = "pll_x_out0", .dt_id = TEGRA114_CLK_PLL_X_OUT0 },
+       { .con_id = "pll_u", .dt_id = TEGRA114_CLK_PLL_U },
+       { .con_id = "pll_u_480M", .dt_id = TEGRA114_CLK_PLL_U_480M },
+       { .con_id = "pll_u_60M", .dt_id = TEGRA114_CLK_PLL_U_60M },
+       { .con_id = "pll_u_48M", .dt_id = TEGRA114_CLK_PLL_U_48M },
+       { .con_id = "pll_u_12M", .dt_id = TEGRA114_CLK_PLL_U_12M },
+       { .con_id = "pll_d", .dt_id = TEGRA114_CLK_PLL_D },
+       { .con_id = "pll_d_out0", .dt_id = TEGRA114_CLK_PLL_D_OUT0 },
+       { .con_id = "pll_d2", .dt_id = TEGRA114_CLK_PLL_D2 },
+       { .con_id = "pll_d2_out0", .dt_id = TEGRA114_CLK_PLL_D2_OUT0 },
+       { .con_id = "pll_a", .dt_id = TEGRA114_CLK_PLL_A },
+       { .con_id = "pll_a_out0", .dt_id = TEGRA114_CLK_PLL_A_OUT0 },
+       { .con_id = "pll_re_vco", .dt_id = TEGRA114_CLK_PLL_RE_VCO },
+       { .con_id = "pll_re_out", .dt_id = TEGRA114_CLK_PLL_RE_OUT },
+       { .con_id = "pll_e_out0", .dt_id = TEGRA114_CLK_PLL_E_OUT0 },
+       { .con_id = "spdif_in_sync", .dt_id = TEGRA114_CLK_SPDIF_IN_SYNC },
+       { .con_id = "i2s0_sync", .dt_id = TEGRA114_CLK_I2S0_SYNC },
+       { .con_id = "i2s1_sync", .dt_id = TEGRA114_CLK_I2S1_SYNC },
+       { .con_id = "i2s2_sync", .dt_id = TEGRA114_CLK_I2S2_SYNC },
+       { .con_id = "i2s3_sync", .dt_id = TEGRA114_CLK_I2S3_SYNC },
+       { .con_id = "i2s4_sync", .dt_id = TEGRA114_CLK_I2S4_SYNC },
+       { .con_id = "vimclk_sync", .dt_id = TEGRA114_CLK_VIMCLK_SYNC },
+       { .con_id = "audio0", .dt_id = TEGRA114_CLK_AUDIO0 },
+       { .con_id = "audio1", .dt_id = TEGRA114_CLK_AUDIO1 },
+       { .con_id = "audio2", .dt_id = TEGRA114_CLK_AUDIO2 },
+       { .con_id = "audio3", .dt_id = TEGRA114_CLK_AUDIO3 },
+       { .con_id = "audio4", .dt_id = TEGRA114_CLK_AUDIO4 },
+       { .con_id = "spdif", .dt_id = TEGRA114_CLK_SPDIF },
+       { .con_id = "audio0_2x", .dt_id = TEGRA114_CLK_AUDIO0_2X },
+       { .con_id = "audio1_2x", .dt_id = TEGRA114_CLK_AUDIO1_2X },
+       { .con_id = "audio2_2x", .dt_id = TEGRA114_CLK_AUDIO2_2X },
+       { .con_id = "audio3_2x", .dt_id = TEGRA114_CLK_AUDIO3_2X },
+       { .con_id = "audio4_2x", .dt_id = TEGRA114_CLK_AUDIO4_2X },
+       { .con_id = "spdif_2x", .dt_id = TEGRA114_CLK_SPDIF_2X },
+       { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA114_CLK_EXTERN1 },
+       { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA114_CLK_EXTERN2 },
+       { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA114_CLK_EXTERN3 },
+       { .con_id = "blink", .dt_id = TEGRA114_CLK_BLINK },
+       { .con_id = "cclk_g", .dt_id = TEGRA114_CLK_CCLK_G },
+       { .con_id = "cclk_lp", .dt_id = TEGRA114_CLK_CCLK_LP },
+       { .con_id = "sclk", .dt_id = TEGRA114_CLK_SCLK },
+       { .con_id = "hclk", .dt_id = TEGRA114_CLK_HCLK },
+       { .con_id = "pclk", .dt_id = TEGRA114_CLK_PCLK },
+       { .con_id = "fuse", .dt_id = TEGRA114_CLK_FUSE },
+       { .dev_id = "rtc-tegra", .dt_id = TEGRA114_CLK_RTC },
+       { .dev_id = "timer", .dt_id = TEGRA114_CLK_TIMER },
+};
+
+static struct clk **clks;
 
 static unsigned long osc_freq;
 static unsigned long pll_ref_freq;
@@ -1086,16 +944,14 @@ static int __init tegra114_osc_clk_init(void __iomem *clk_base)
        /* clk_m */
        clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
                                      osc_freq);
-       clk_register_clkdev(clk, "clk_m", NULL);
-       clks[clk_m] = clk;
+       clks[TEGRA114_CLK_CLK_M] = clk;
 
        /* pll_ref */
        val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
        pll_ref_div = 1 << val;
        clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
                                        CLK_SET_RATE_PARENT, 1, pll_ref_div);
-       clk_register_clkdev(clk, "pll_ref", NULL);
-       clks[pll_ref] = clk;
+       clks[TEGRA114_CLK_PLL_REF] = clk;
 
        pll_ref_freq = osc_freq / pll_ref_div;
 
@@ -1109,20 +965,17 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
        /* clk_32k */
        clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
                                      32768);
-       clk_register_clkdev(clk, "clk_32k", NULL);
-       clks[clk_32k] = clk;
+       clks[TEGRA114_CLK_CLK_32K] = clk;
 
        /* clk_m_div2 */
        clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "clk_m_div2", NULL);
-       clks[clk_m_div2] = clk;
+       clks[TEGRA114_CLK_CLK_M_DIV2] = clk;
 
        /* clk_m_div4 */
        clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
                                        CLK_SET_RATE_PARENT, 1, 4);
-       clk_register_clkdev(clk, "clk_m_div4", NULL);
-       clks[clk_m_div4] = clk;
+       clks[TEGRA114_CLK_CLK_M_DIV4] = clk;
 
 }
 
@@ -1208,63 +1061,6 @@ static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
        writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
 }
 
-static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params)
-{
-       pll_params->vco_min =
-               DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq;
-}
-
-static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
-                                     void __iomem *clk_base)
-{
-       u32 val;
-       u32 step_a, step_b;
-
-       switch (pll_ref_freq) {
-       case 12000000:
-       case 13000000:
-       case 26000000:
-               step_a = 0x2B;
-               step_b = 0x0B;
-               break;
-       case 16800000:
-               step_a = 0x1A;
-               step_b = 0x09;
-               break;
-       case 19200000:
-               step_a = 0x12;
-               step_b = 0x08;
-               break;
-       default:
-               pr_err("%s: Unexpected reference rate %lu\n",
-                       __func__, pll_ref_freq);
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       val = step_a << pll_params->stepa_shift;
-       val |= step_b << pll_params->stepb_shift;
-       writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
-
-       return 0;
-}
-
-static void __init _init_iddq(struct tegra_clk_pll_params *pll_params,
-                             void __iomem *clk_base)
-{
-       u32 val, val_iddq;
-
-       val = readl_relaxed(clk_base + pll_params->base_reg);
-       val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
-
-       if (val & BIT(30))
-               WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
-       else {
-               val_iddq |= BIT(pll_params->iddq_bit_idx);
-               writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
-       }
-}
-
 static void __init tegra114_pll_init(void __iomem *clk_base,
                                     void __iomem *pmc)
 {
@@ -1272,104 +1068,34 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
        struct clk *clk;
 
        /* PLLC */
-       _clip_vco_min(&pll_c_params);
-       if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) {
-               _init_iddq(&pll_c_params, clk_base);
-               clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
-                               pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
-                               pll_c_freq_table, NULL);
-               clk_register_clkdev(clk, "pll_c", NULL);
-               clks[pll_c] = clk;
-
-               /* PLLC_OUT1 */
-               clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
-                               clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, NULL);
-               clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
-                                       clk_base + PLLC_OUT, 1, 0,
-                                       CLK_SET_RATE_PARENT, 0, NULL);
-               clk_register_clkdev(clk, "pll_c_out1", NULL);
-               clks[pll_c_out1] = clk;
-       }
+       clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+                       pmc, 0, &pll_c_params, NULL);
+       clks[TEGRA114_CLK_PLL_C] = clk;
+
+       /* PLLC_OUT1 */
+       clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+                       clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                       8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+                               clk_base + PLLC_OUT, 1, 0,
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clks[TEGRA114_CLK_PLL_C_OUT1] = clk;
 
        /* PLLC2 */
-       _clip_vco_min(&pll_c2_params);
-       clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
-                            &pll_c2_params, TEGRA_PLL_USE_LOCK,
-                            pll_cx_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_c2", NULL);
-       clks[pll_c2] = clk;
+       clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0,
+                            &pll_c2_params, NULL);
+       clks[TEGRA114_CLK_PLL_C2] = clk;
 
        /* PLLC3 */
-       _clip_vco_min(&pll_c3_params);
-       clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
-                            &pll_c3_params, TEGRA_PLL_USE_LOCK,
-                            pll_cx_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_c3", NULL);
-       clks[pll_c3] = clk;
-
-       /* PLLP */
-       clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0,
-                           408000000, &pll_p_params,
-                           TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
-                           pll_p_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_p", NULL);
-       clks[pll_p] = clk;
-
-       /* PLLP_OUT1 */
-       clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
-                               clk_base + PLLP_OUTA, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out1", NULL);
-       clks[pll_p_out1] = clk;
-
-       /* PLLP_OUT2 */
-       clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP | TEGRA_DIVIDER_INT, 24,
-                               8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
-                               clk_base + PLLP_OUTA, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out2", NULL);
-       clks[pll_p_out2] = clk;
-
-       /* PLLP_OUT3 */
-       clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
-                               clk_base + PLLP_OUTB, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out3", NULL);
-       clks[pll_p_out3] = clk;
-
-       /* PLLP_OUT4 */
-       clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
-                               &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
-                               clk_base + PLLP_OUTB, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out4", NULL);
-       clks[pll_p_out4] = clk;
+       clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0,
+                            &pll_c3_params, NULL);
+       clks[TEGRA114_CLK_PLL_C3] = clk;
 
        /* PLLM */
-       _clip_vco_min(&pll_m_params);
        clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
-                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
-                            &pll_m_params, TEGRA_PLL_USE_LOCK,
-                            pll_m_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_m", NULL);
-       clks[pll_m] = clk;
+                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+                            &pll_m_params, NULL);
+       clks[TEGRA114_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
        clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
@@ -1378,41 +1104,20 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
                                clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
                                CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_m_out1", NULL);
-       clks[pll_m_out1] = clk;
+       clks[TEGRA114_CLK_PLL_M_OUT1] = clk;
 
        /* PLLM_UD */
        clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
                                        CLK_SET_RATE_PARENT, 1, 1);
 
-       /* PLLX */
-       _clip_vco_min(&pll_x_params);
-       if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) {
-               _init_iddq(&pll_x_params, clk_base);
-               clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
-                               pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
-                               TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
-               clk_register_clkdev(clk, "pll_x", NULL);
-               clks[pll_x] = clk;
-       }
-
-       /* PLLX_OUT0 */
-       clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
-                                       CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_x_out0", NULL);
-       clks[pll_x_out0] = clk;
-
        /* PLLU */
        val = readl(clk_base + pll_u_params.base_reg);
        val &= ~BIT(24); /* disable PLLU_OVERRIDE */
        writel(val, clk_base + pll_u_params.base_reg);
 
        clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
-                           0, &pll_u_params, TEGRA_PLLU |
-                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-                           TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock);
-       clk_register_clkdev(clk, "pll_u", NULL);
-       clks[pll_u] = clk;
+                           &pll_u_params, &pll_u_lock);
+       clks[TEGRA114_CLK_PLL_U] = clk;
 
        tegra114_utmi_param_configure(clk_base);
 
@@ -1420,731 +1125,97 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
        clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
                                CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
                                22, 0, &pll_u_lock);
-       clk_register_clkdev(clk, "pll_u_480M", NULL);
-       clks[pll_u_480M] = clk;
+       clks[TEGRA114_CLK_PLL_U_480M] = clk;
 
        /* PLLU_60M */
        clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u",
                                        CLK_SET_RATE_PARENT, 1, 8);
-       clk_register_clkdev(clk, "pll_u_60M", NULL);
-       clks[pll_u_60M] = clk;
+       clks[TEGRA114_CLK_PLL_U_60M] = clk;
 
        /* PLLU_48M */
        clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u",
                                        CLK_SET_RATE_PARENT, 1, 10);
-       clk_register_clkdev(clk, "pll_u_48M", NULL);
-       clks[pll_u_48M] = clk;
+       clks[TEGRA114_CLK_PLL_U_48M] = clk;
 
        /* PLLU_12M */
        clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u",
                                        CLK_SET_RATE_PARENT, 1, 40);
-       clk_register_clkdev(clk, "pll_u_12M", NULL);
-       clks[pll_u_12M] = clk;
+       clks[TEGRA114_CLK_PLL_U_12M] = clk;
 
        /* PLLD */
        clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
-                           0, &pll_d_params,
-                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-                           TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock);
-       clk_register_clkdev(clk, "pll_d", NULL);
-       clks[pll_d] = clk;
+                           &pll_d_params, &pll_d_lock);
+       clks[TEGRA114_CLK_PLL_D] = clk;
 
        /* PLLD_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_d_out0", NULL);
-       clks[pll_d_out0] = clk;
+       clks[TEGRA114_CLK_PLL_D_OUT0] = clk;
 
        /* PLLD2 */
        clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0,
-                           0, &pll_d2_params,
-                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
-                           TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock);
-       clk_register_clkdev(clk, "pll_d2", NULL);
-       clks[pll_d2] = clk;
+                           &pll_d2_params, &pll_d2_lock);
+       clks[TEGRA114_CLK_PLL_D2] = clk;
 
        /* PLLD2_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_d2_out0", NULL);
-       clks[pll_d2_out0] = clk;
-
-       /* PLLA */
-       clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0,
-                           0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_a", NULL);
-       clks[pll_a] = clk;
-
-       /* PLLA_OUT0 */
-       clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
-                               clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, NULL);
-       clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
-                               clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
-                               CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_a_out0", NULL);
-       clks[pll_a_out0] = clk;
+       clks[TEGRA114_CLK_PLL_D2_OUT0] = clk;
 
        /* PLLRE */
-       _clip_vco_min(&pll_re_vco_params);
        clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
-                            0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
-                            NULL, &pll_re_lock, pll_ref_freq);
-       clk_register_clkdev(clk, "pll_re_vco", NULL);
-       clks[pll_re_vco] = clk;
+                            0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq);
+       clks[TEGRA114_CLK_PLL_RE_VCO] = clk;
 
        clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
                                         clk_base + PLLRE_BASE, 16, 4, 0,
                                         pll_re_div_table, &pll_re_lock);
-       clk_register_clkdev(clk, "pll_re_out", NULL);
-       clks[pll_re_out] = clk;
+       clks[TEGRA114_CLK_PLL_RE_OUT] = clk;
 
        /* PLLE */
-       clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco",
-                                     clk_base, 0, 100000000, &pll_e_params,
-                                     pll_e_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_e_out0", NULL);
-       clks[pll_e_out0] = clk;
-}
-
-static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
-       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
-};
-
-static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
-       "clk_m_div4", "extern1",
-};
-
-static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
-       "clk_m_div4", "extern2",
-};
-
-static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
-       "clk_m_div4", "extern3",
-};
-
-static void __init tegra114_audio_clk_init(void __iomem *clk_base)
-{
-       struct clk *clk;
-
-       /* spdif_in_sync */
-       clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
-                                            24000000);
-       clk_register_clkdev(clk, "spdif_in_sync", NULL);
-       clks[spdif_in_sync] = clk;
-
-       /* i2s0_sync */
-       clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s0_sync", NULL);
-       clks[i2s0_sync] = clk;
-
-       /* i2s1_sync */
-       clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s1_sync", NULL);
-       clks[i2s1_sync] = clk;
-
-       /* i2s2_sync */
-       clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s2_sync", NULL);
-       clks[i2s2_sync] = clk;
-
-       /* i2s3_sync */
-       clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s3_sync", NULL);
-       clks[i2s3_sync] = clk;
-
-       /* i2s4_sync */
-       clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s4_sync", NULL);
-       clks[i2s4_sync] = clk;
-
-       /* vimclk_sync */
-       clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "vimclk_sync", NULL);
-       clks[vimclk_sync] = clk;
-
-       /* audio0 */
-       clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
-                              NULL);
-       clks[audio0_mux] = clk;
-       clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S0, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio0", NULL);
-       clks[audio0] = clk;
-
-       /* audio1 */
-       clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
-                              NULL);
-       clks[audio1_mux] = clk;
-       clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S1, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio1", NULL);
-       clks[audio1] = clk;
-
-       /* audio2 */
-       clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
-                              NULL);
-       clks[audio2_mux] = clk;
-       clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S2, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio2", NULL);
-       clks[audio2] = clk;
-
-       /* audio3 */
-       clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
-                              NULL);
-       clks[audio3_mux] = clk;
-       clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S3, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio3", NULL);
-       clks[audio3] = clk;
-
-       /* audio4 */
-       clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
-                              NULL);
-       clks[audio4_mux] = clk;
-       clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S4, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio4", NULL);
-       clks[audio4] = clk;
-
-       /* spdif */
-       clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk),
-                              CLK_SET_RATE_NO_REPARENT,
-                              clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
-                              NULL);
-       clks[spdif_mux] = clk;
-       clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "spdif", NULL);
-       clks[spdif] = clk;
-
-       /* audio0_2x */
-       clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 113, &periph_v_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio0_2x", NULL);
-       clks[audio0_2x] = clk;
-
-       /* audio1_2x */
-       clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 114, &periph_v_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio1_2x", NULL);
-       clks[audio1_2x] = clk;
-
-       /* audio2_2x */
-       clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 115, &periph_v_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio2_2x", NULL);
-       clks[audio2_2x] = clk;
-
-       /* audio3_2x */
-       clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 116, &periph_v_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio3_2x", NULL);
-       clks[audio3_2x] = clk;
-
-       /* audio4_2x */
-       clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 117, &periph_v_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio4_2x", NULL);
-       clks[audio4_2x] = clk;
-
-       /* spdif_2x */
-       clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1,
-                               0, &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
-                                 TEGRA_PERIPH_NO_RESET, clk_base,
-                                 CLK_SET_RATE_PARENT, 118,
-                                 &periph_v_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "spdif_2x", NULL);
-       clks[spdif_2x] = clk;
-}
-
-static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
-{
-       struct clk *clk;
-
-       /* clk_out_1 */
-       clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
-                              ARRAY_SIZE(clk_out1_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
-                              &clk_out_lock);
-       clks[clk_out_1_mux] = clk;
-       clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern1", "clk_out_1");
-       clks[clk_out_1] = clk;
-
-       /* clk_out_2 */
-       clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
-                              ARRAY_SIZE(clk_out2_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
-                              &clk_out_lock);
-       clks[clk_out_2_mux] = clk;
-       clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern2", "clk_out_2");
-       clks[clk_out_2] = clk;
-
-       /* clk_out_3 */
-       clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
-                              ARRAY_SIZE(clk_out3_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
-                              &clk_out_lock);
-       clks[clk_out_3_mux] = clk;
-       clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern3", "clk_out_3");
-       clks[clk_out_3] = clk;
-
-       /* blink */
-       /* clear the blink timer register to directly output clk_32k */
-       writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
-       clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
-                               pmc_base + PMC_DPD_PADS_ORIDE,
-                               PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
-       clk = clk_register_gate(NULL, "blink", "blink_override", 0,
-                               pmc_base + PMC_CTRL,
-                               PMC_CTRL_BLINK_ENB, 0, NULL);
-       clk_register_clkdev(clk, "blink", NULL);
-       clks[blink] = clk;
-
+       clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_ref",
+                                     clk_base, 0, &pll_e_params, NULL);
+       clks[TEGRA114_CLK_PLL_E_OUT0] = clk;
 }
 
-static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
-                              "pll_p", "pll_p_out2", "unused",
-                              "clk_32k", "pll_m_out1" };
-
-static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
-                                       "pll_p", "pll_p_out4", "unused",
-                                       "unused", "pll_x" };
-
-static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
-                                        "pll_p", "pll_p_out4", "unused",
-                                        "unused", "pll_x", "pll_x_out0" };
-
-static void __init tegra114_super_clk_init(void __iomem *clk_base)
+static __init void tegra114_periph_clk_init(void __iomem *clk_base,
+                                           void __iomem *pmc_base)
 {
        struct clk *clk;
+       u32 val;
 
-       /* CCLKG */
-       clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
-                                       ARRAY_SIZE(cclk_g_parents),
-                                       CLK_SET_RATE_PARENT,
-                                       clk_base + CCLKG_BURST_POLICY,
-                                       0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "cclk_g", NULL);
-       clks[cclk_g] = clk;
-
-       /* CCLKLP */
-       clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
-                                       ARRAY_SIZE(cclk_lp_parents),
-                                       CLK_SET_RATE_PARENT,
-                                       clk_base + CCLKLP_BURST_POLICY,
-                                       0, 4, 8, 9, NULL);
-       clk_register_clkdev(clk, "cclk_lp", NULL);
-       clks[cclk_lp] = clk;
-
-       /* SCLK */
-       clk = tegra_clk_register_super_mux("sclk", sclk_parents,
-                                       ARRAY_SIZE(sclk_parents),
-                                       CLK_SET_RATE_PARENT,
-                                       clk_base + SCLK_BURST_POLICY,
-                                       0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "sclk", NULL);
-       clks[sclk] = clk;
-
-       /* HCLK */
-       clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
-                                  clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT |
-                               CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
-                               7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "hclk", NULL);
-       clks[hclk] = clk;
-
-       /* PCLK */
-       clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
-                                  clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
-                               CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
-                               3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "pclk", NULL);
-       clks[pclk] = clk;
-}
-
-static struct tegra_periph_init_data tegra_periph_clk_list[] = {
-       TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
-       TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
-       TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
-       TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
-       TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
-       TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
-       TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
-       TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm),
-       TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx),
-       TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx),
-       TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda),
-       TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x),
-       TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
-       TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
-       TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
-       TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
-       TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
-       TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
-       TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
-       TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
-       TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
-       TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1),
-       TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2),
-       TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3),
-       TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4),
-       TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde),
-       TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite, CLK_IGNORE_UNUSED),
-       TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la),
-       TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace),
-       TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
-       TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor),
-       TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
-       TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1),
-       TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2),
-       TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3),
-       TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4),
-       TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5),
-       TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta),
-       TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb),
-       TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc),
-       TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd),
-       TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d),
-       TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d),
-       TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
-       TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
-       TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
-       TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, msenc),
-       TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
-       TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
-       TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
-       TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab),
-       TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd),
-       TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile),
-       TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp),
-       TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp),
-       TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
-       TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon),
-       TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1),
-       TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2),
-       TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3),
-       TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
-       TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
-       TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
-       TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_ref),
-       TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_soc),
-       TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
-       TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
-       TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
-       TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src),
-       TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src),
-       TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src),
-       TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio),
-       TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0),
-       TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1),
-       TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2),
-};
-
-static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
-       TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, disp1),
-       TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, disp2),
-};
+       /* xusb_hs_src */
+       val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
+       val |= BIT(25); /* always select PLLU_60M */
+       writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
 
-static __init void tegra114_periph_clk_init(void __iomem *clk_base)
-{
-       struct tegra_periph_init_data *data;
-       struct clk *clk;
-       int i;
-       u32 val;
+       clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
+                                       1, 1);
+       clks[TEGRA114_CLK_XUSB_HS_SRC] = clk;
 
-       /* apbdma */
-       clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base,
-                                 0, 34, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[apbdma] = clk;
-
-       /* rtc */
-       clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
-                                   TEGRA_PERIPH_ON_APB |
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   0, 4, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "rtc-tegra");
-       clks[rtc] = clk;
-
-       /* kbc */
-       clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
-                                   TEGRA_PERIPH_ON_APB |
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   0, 36, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clks[kbc] = clk;
-
-       /* timer */
-       clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
-                                 0, 5, &periph_l_regs,
-                                 periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "timer");
-       clks[timer] = clk;
-
-       /* kfuse */
-       clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 40,
-                                 &periph_h_regs, periph_clk_enb_refcnt);
-       clks[kfuse] = clk;
-
-       /* fuse */
-       clk = tegra_clk_register_periph_gate("fuse", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
-                                 &periph_h_regs, periph_clk_enb_refcnt);
-       clks[fuse] = clk;
-
-       /* fuse_burn */
-       clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
-                                 &periph_h_regs, periph_clk_enb_refcnt);
-       clks[fuse_burn] = clk;
-
-       /* apbif */
-       clk = tegra_clk_register_periph_gate("apbif", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 107,
-                                 &periph_v_regs, periph_clk_enb_refcnt);
-       clks[apbif] = clk;
-
-       /* hda2hdmi */
-       clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
-                                   TEGRA_PERIPH_ON_APB, clk_base,  0, 128,
-                                   &periph_w_regs, periph_clk_enb_refcnt);
-       clks[hda2hdmi] = clk;
-
-       /* vcp */
-       clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base,  0,
-                                 29, &periph_l_regs,
-                                 periph_clk_enb_refcnt);
-       clks[vcp] = clk;
-
-       /* bsea */
-       clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base,
-                                 0, 62, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[bsea] = clk;
-
-       /* bsev */
-       clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base,
-                                 0, 63, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[bsev] = clk;
-
-       /* mipi-cal */
-       clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
-                                  0, 56, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[mipi_cal] = clk;
-
-       /* usbd */
-       clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base,
-                                 0, 22, &periph_l_regs,
-                                 periph_clk_enb_refcnt);
-       clks[usbd] = clk;
-
-       /* usb2 */
-       clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base,
-                                 0, 58, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[usb2] = clk;
-
-       /* usb3 */
-       clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base,
-                                 0, 59, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[usb3] = clk;
-
-       /* csi */
-       clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
-                                  0, 52, &periph_h_regs,
-                                 periph_clk_enb_refcnt);
-       clks[csi] = clk;
-
-       /* isp */
-       clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0,
-                                 23, &periph_l_regs,
-                                 periph_clk_enb_refcnt);
-       clks[isp] = clk;
-
-       /* csus */
-       clk = tegra_clk_register_periph_gate("csus", "clk_m",
-                                 TEGRA_PERIPH_NO_RESET, clk_base, 0, 92,
-                                 &periph_u_regs, periph_clk_enb_refcnt);
-       clks[csus] = clk;
-
-       /* dds */
-       clk = tegra_clk_register_periph_gate("dds", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base, 0, 150,
-                                 &periph_w_regs, periph_clk_enb_refcnt);
-       clks[dds] = clk;
-
-       /* dp2 */
-       clk = tegra_clk_register_periph_gate("dp2", "clk_m",
-                                 TEGRA_PERIPH_ON_APB, clk_base, 0, 152,
-                                 &periph_w_regs, periph_clk_enb_refcnt);
-       clks[dp2] = clk;
-
-       /* dtv */
-       clk = tegra_clk_register_periph_gate("dtv", "clk_m",
-                                   TEGRA_PERIPH_ON_APB, clk_base, 0, 79,
-                                   &periph_u_regs, periph_clk_enb_refcnt);
-       clks[dtv] = clk;
-
-       /* dsia */
+       /* dsia mux */
        clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
                               ARRAY_SIZE(mux_plld_out0_plld2_out0),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
-       clks[dsia_mux] = clk;
-       clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
-                                   0, 48, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clks[dsia] = clk;
+       clks[TEGRA114_CLK_DSIA_MUX] = clk;
 
-       /* dsib */
+       /* dsib mux */
        clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
                               ARRAY_SIZE(mux_plld_out0_plld2_out0),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
-       clks[dsib_mux] = clk;
-       clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
-                                   0, 82, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clks[dsib] = clk;
+       clks[TEGRA114_CLK_DSIB_MUX] = clk;
 
-       /* xusb_hs_src */
-       val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
-       val |= BIT(25); /* always select PLLU_60M */
-       writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
-
-       clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
-                                       1, 1);
-       clks[xusb_hs_src] = clk;
-
-       /* xusb_host */
-       clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
-                                   clk_base, 0, 89, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clks[xusb_host] = clk;
-
-       /* xusb_ss */
-       clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
-                                   clk_base, 0, 156, &periph_w_regs,
-                                   periph_clk_enb_refcnt);
-       clks[xusb_host] = clk;
-
-       /* xusb_dev */
-       clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
-                                   clk_base, 0, 95, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clks[xusb_dev] = clk;
-
-       /* emc */
+       /* emc mux */
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
                               ARRAY_SIZE(mux_pllmcp_clkm),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
                               29, 3, 0, NULL);
-       clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base,
-                               CLK_IGNORE_UNUSED, 57, &periph_h_regs,
-                               periph_clk_enb_refcnt);
-       clks[emc] = clk;
-
-       for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
-               data = &tegra_periph_clk_list[i];
-               clk = tegra_clk_register_periph(data->name, data->parent_names,
-                               data->num_parents, &data->periph,
-                               clk_base, data->offset, data->flags);
-               clks[data->clk_id] = clk;
-       }
 
-       for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
-               data = &tegra_periph_nodiv_clk_list[i];
-               clk = tegra_clk_register_periph_nodiv(data->name,
-                               data->parent_names, data->num_parents,
-                               &data->periph, clk_base, data->offset);
-               clks[data->clk_id] = clk;
-       }
+       tegra_periph_clk_init(clk_base, pmc_base, tegra114_clks,
+                               &pll_p_params);
 }
 
 /* Tegra114 CPU clock and reset control functions */
@@ -2207,28 +1278,37 @@ static const struct of_device_id pmc_match[] __initconst = {
  * breaks
  */
 static struct tegra_clk_init_table init_table[] __initdata = {
-       {uarta, pll_p, 408000000, 0},
-       {uartb, pll_p, 408000000, 0},
-       {uartc, pll_p, 408000000, 0},
-       {uartd, pll_p, 408000000, 0},
-       {pll_a, clk_max, 564480000, 1},
-       {pll_a_out0, clk_max, 11289600, 1},
-       {extern1, pll_a_out0, 0, 1},
-       {clk_out_1_mux, extern1, 0, 1},
-       {clk_out_1, clk_max, 0, 1},
-       {i2s0, pll_a_out0, 11289600, 0},
-       {i2s1, pll_a_out0, 11289600, 0},
-       {i2s2, pll_a_out0, 11289600, 0},
-       {i2s3, pll_a_out0, 11289600, 0},
-       {i2s4, pll_a_out0, 11289600, 0},
-       {dfll_soc, pll_p, 51000000, 1},
-       {dfll_ref, pll_p, 51000000, 1},
-       {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+       {TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0},
+       {TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0},
+       {TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0},
+       {TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0},
+       {TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1},
+       {TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1},
+       {TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1},
+       {TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1},
+       {TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1},
+       {TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0},
+       {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1},
+       {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1},
+       {TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0},
+       {TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0},
+       {TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0},
+       {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0},
+       {TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0},
+       {TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0},
+
+       /* This MUST be the last entry. */
+       {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0},
 };
 
 static void __init tegra114_clock_apply_init_table(void)
 {
-       tegra_init_from_table(init_table, clks, clk_max);
+       tegra_init_from_table(init_table, clks, TEGRA114_CLK_CLK_MAX);
 }
 
 
@@ -2359,7 +1439,6 @@ EXPORT_SYMBOL(tegra114_clock_deassert_dfll_dvco_reset);
 static void __init tegra114_clock_init(struct device_node *np)
 {
        struct device_node *node;
-       int i;
 
        clk_base = of_iomap(np, 0);
        if (!clk_base) {
@@ -2381,29 +1460,24 @@ static void __init tegra114_clock_init(struct device_node *np)
                return;
        }
 
+       clks = tegra_clk_init(clk_base, TEGRA114_CLK_CLK_MAX,
+                               TEGRA114_CLK_PERIPH_BANKS);
+       if (!clks)
+               return;
+
        if (tegra114_osc_clk_init(clk_base) < 0)
                return;
 
        tegra114_fixed_clk_init(clk_base);
        tegra114_pll_init(clk_base, pmc_base);
-       tegra114_periph_clk_init(clk_base);
-       tegra114_audio_clk_init(clk_base);
-       tegra114_pmc_clk_init(pmc_base);
-       tegra114_super_clk_init(clk_base);
-
-       for (i = 0; i < ARRAY_SIZE(clks); i++) {
-               if (IS_ERR(clks[i])) {
-                       pr_err
-                           ("Tegra114 clk %d: register failed with %ld\n",
-                            i, PTR_ERR(clks[i]));
-               }
-               if (!clks[i])
-                       clks[i] = ERR_PTR(-EINVAL);
-       }
-
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       tegra114_periph_clk_init(clk_base, pmc_base);
+       tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params);
+       tegra_pmc_clk_init(pmc_base, tegra114_clks);
+       tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
+                                       &pll_x_params);
+
+       tegra_add_of_provider(np);
+       tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
        tegra_clk_apply_init_table = tegra114_clock_apply_init_table;
 
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
new file mode 100644 (file)
index 0000000..aff86b5
--- /dev/null
@@ -0,0 +1,1424 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+#include <dt-bindings/clock/tegra124-car.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_EMC 0x19c
+#define CLK_SOURCE_XUSB_SS_SRC 0x610
+
+#define PLLC_BASE 0x80
+#define PLLC_OUT 0x84
+#define PLLC_MISC2 0x88
+#define PLLC_MISC 0x8c
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC 0x4ec
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC 0x500
+#define PLLM_BASE 0x90
+#define PLLM_OUT 0x94
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define PLLE_AUX 0x48c
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC 0x4c8
+#define PLLDP_BASE 0x590
+#define PLLDP_MISC 0x594
+#define PLLC4_BASE 0x5a4
+#define PLLC4_MISC 0x5a8
+
+#define PLLC_IDDQ_BIT 26
+#define PLLRE_IDDQ_BIT 16
+#define PLLSS_IDDQ_BIT 19
+
+#define PLL_BASE_LOCK BIT(27)
+#define PLLE_MISC_LOCK BIT(11)
+#define PLLRE_MISC_LOCK BIT(24)
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLC_MISC_LOCK_ENABLE 24
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+#define PLLSS_MISC_LOCK_ENABLE 30
+
+#define PLLXC_SW_MAX_P 6
+
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0                  0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE  BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE       BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET      BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE    BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL     BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE    BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL       BIT(0)
+
+/* Tegra CPU clock and reset control regs */
+#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS    0x470
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+       u32 clk_csite_src;
+} tegra124_cpu_clk_sctx;
+#endif
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_d2_lock);
+static DEFINE_SPINLOCK(pll_e_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra124_input_freq[] = {
+       [0] = 13000000,
+       [1] = 16800000,
+       [4] = 19200000,
+       [5] = 38400000,
+       [8] = 12000000,
+       [9] = 48000000,
+       [12] = 260000000,
+};
+
+static const char *mux_plld_out0_plld2_out0[] = {
+       "pll_d_out0", "pll_d2_out0",
+};
+#define mux_plld_out0_plld2_out0_idx NULL
+
+static const char *mux_pllmcp_clkm[] = {
+       "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
+};
+#define mux_pllmcp_clkm_idx NULL
+
+static struct div_nmp pllxc_nmp = {
+       .divm_shift = 0,
+       .divm_width = 8,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .divp_shift = 20,
+       .divp_width = 4,
+};
+
+static struct pdiv_map pllxc_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 3, .hw_val = 2 },
+       { .pdiv = 4, .hw_val = 3 },
+       { .pdiv = 5, .hw_val = 4 },
+       { .pdiv = 6, .hw_val = 5 },
+       { .pdiv = 8, .hw_val = 6 },
+       { .pdiv = 10, .hw_val = 7 },
+       { .pdiv = 12, .hw_val = 8 },
+       { .pdiv = 16, .hw_val = 9 },
+       { .pdiv = 12, .hw_val = 10 },
+       { .pdiv = 16, .hw_val = 11 },
+       { .pdiv = 20, .hw_val = 12 },
+       { .pdiv = 24, .hw_val = 13 },
+       { .pdiv = 32, .hw_val = 14 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+       /* 1 GHz */
+       {12000000, 1000000000, 83, 0, 1},       /* actual: 996.0 MHz */
+       {13000000, 1000000000, 76, 0, 1},       /* actual: 988.0 MHz */
+       {16800000, 1000000000, 59, 0, 1},       /* actual: 991.2 MHz */
+       {19200000, 1000000000, 52, 0, 1},       /* actual: 998.4 MHz */
+       {26000000, 1000000000, 76, 1, 1},       /* actual: 988.0 MHz */
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+       .input_min = 12000000,
+       .input_max = 800000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 700000000,
+       .vco_max = 3000000000UL,
+       .base_reg = PLLX_BASE,
+       .misc_reg = PLLX_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLX_MISC3,
+       .iddq_bit_idx = 3,
+       .max_p = 6,
+       .dyn_ramp_reg = PLLX_MISC2,
+       .stepa_shift = 16,
+       .stepb_shift = 24,
+       .pdiv_tohw = pllxc_p,
+       .div_nmp = &pllxc_nmp,
+       .freq_table = pll_x_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+       { 12000000, 624000000, 104, 1, 2},
+       { 12000000, 600000000, 100, 1, 2},
+       { 13000000, 600000000,  92, 1, 2},      /* actual: 598.0 MHz */
+       { 16800000, 600000000,  71, 1, 2},      /* actual: 596.4 MHz */
+       { 19200000, 600000000,  62, 1, 2},      /* actual: 595.2 MHz */
+       { 26000000, 600000000,  92, 2, 2},      /* actual: 598.0 MHz */
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c_params = {
+       .input_min = 12000000,
+       .input_max = 800000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 600000000,
+       .vco_max = 1400000000,
+       .base_reg = PLLC_BASE,
+       .misc_reg = PLLC_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLC_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLC_MISC,
+       .iddq_bit_idx = PLLC_IDDQ_BIT,
+       .max_p = PLLXC_SW_MAX_P,
+       .dyn_ramp_reg = PLLC_MISC2,
+       .stepa_shift = 17,
+       .stepb_shift = 9,
+       .pdiv_tohw = pllxc_p,
+       .div_nmp = &pllxc_nmp,
+       .freq_table = pll_c_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct div_nmp pllcx_nmp = {
+       .divm_shift = 0,
+       .divm_width = 2,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .divp_shift = 20,
+       .divp_width = 3,
+};
+
+static struct pdiv_map pllc_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 3, .hw_val = 2 },
+       { .pdiv = 4, .hw_val = 3 },
+       { .pdiv = 6, .hw_val = 4 },
+       { .pdiv = 8, .hw_val = 5 },
+       { .pdiv = 12, .hw_val = 6 },
+       { .pdiv = 16, .hw_val = 7 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
+       {12000000, 600000000, 100, 1, 2},
+       {13000000, 600000000, 92, 1, 2},        /* actual: 598.0 MHz */
+       {16800000, 600000000, 71, 1, 2},        /* actual: 596.4 MHz */
+       {19200000, 600000000, 62, 1, 2},        /* actual: 595.2 MHz */
+       {26000000, 600000000, 92, 2, 2},        /* actual: 598.0 MHz */
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_c2_params = {
+       .input_min = 12000000,
+       .input_max = 48000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLC2_BASE,
+       .misc_reg = PLLC2_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .pdiv_tohw = pllc_p,
+       .div_nmp = &pllcx_nmp,
+       .max_p = 7,
+       .ext_misc_reg[0] = 0x4f0,
+       .ext_misc_reg[1] = 0x4f4,
+       .ext_misc_reg[2] = 0x4f8,
+       .freq_table = pll_cx_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_params pll_c3_params = {
+       .input_min = 12000000,
+       .input_max = 48000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLC3_BASE,
+       .misc_reg = PLLC3_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .pdiv_tohw = pllc_p,
+       .div_nmp = &pllcx_nmp,
+       .max_p = 7,
+       .ext_misc_reg[0] = 0x504,
+       .ext_misc_reg[1] = 0x508,
+       .ext_misc_reg[2] = 0x50c,
+       .freq_table = pll_cx_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct div_nmp pllss_nmp = {
+       .divm_shift = 0,
+       .divm_width = 8,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .divp_shift = 20,
+       .divp_width = 4,
+};
+
+static struct pdiv_map pll12g_ssd_esd_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 3, .hw_val = 2 },
+       { .pdiv = 4, .hw_val = 3 },
+       { .pdiv = 5, .hw_val = 4 },
+       { .pdiv = 6, .hw_val = 5 },
+       { .pdiv = 8, .hw_val = 6 },
+       { .pdiv = 10, .hw_val = 7 },
+       { .pdiv = 12, .hw_val = 8 },
+       { .pdiv = 16, .hw_val = 9 },
+       { .pdiv = 12, .hw_val = 10 },
+       { .pdiv = 16, .hw_val = 11 },
+       { .pdiv = 20, .hw_val = 12 },
+       { .pdiv = 24, .hw_val = 13 },
+       { .pdiv = 32, .hw_val = 14 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_c4_freq_table[] = {
+       { 12000000, 600000000, 100, 1, 1},
+       { 13000000, 600000000,  92, 1, 1},      /* actual: 598.0 MHz */
+       { 16800000, 600000000,  71, 1, 1},      /* actual: 596.4 MHz */
+       { 19200000, 600000000,  62, 1, 1},      /* actual: 595.2 MHz */
+       { 26000000, 600000000,  92, 2, 1},      /* actual: 598.0 MHz */
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c4_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLC4_BASE,
+       .misc_reg = PLLC4_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLC4_BASE,
+       .iddq_bit_idx = PLLSS_IDDQ_BIT,
+       .pdiv_tohw = pll12g_ssd_esd_p,
+       .div_nmp = &pllss_nmp,
+       .ext_misc_reg[0] = 0x5ac,
+       .ext_misc_reg[1] = 0x5b0,
+       .ext_misc_reg[2] = 0x5b4,
+       .freq_table = pll_c4_freq_table,
+};
+
+static struct pdiv_map pllm_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+       {12000000, 800000000, 66, 1, 1},        /* actual: 792.0 MHz */
+       {13000000, 800000000, 61, 1, 1},        /* actual: 793.0 MHz */
+       {16800000, 800000000, 47, 1, 1},        /* actual: 789.6 MHz */
+       {19200000, 800000000, 41, 1, 1},        /* actual: 787.2 MHz */
+       {26000000, 800000000, 61, 2, 1},        /* actual: 793.0 MHz */
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct div_nmp pllm_nmp = {
+       .divm_shift = 0,
+       .divm_width = 8,
+       .override_divm_shift = 0,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .override_divn_shift = 8,
+       .divp_shift = 20,
+       .divp_width = 1,
+       .override_divp_shift = 27,
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+       .input_min = 12000000,
+       .input_max = 500000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 400000000,
+       .vco_max = 1066000000,
+       .base_reg = PLLM_BASE,
+       .misc_reg = PLLM_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .max_p = 2,
+       .pdiv_tohw = pllm_p,
+       .div_nmp = &pllm_nmp,
+       .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
+       .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
+       .freq_table = pll_m_freq_table,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+       /* PLLE special case: use cpcon field to store cml divider value */
+       {336000000, 100000000, 100, 21, 16, 11},
+       {312000000, 100000000, 200, 26, 24, 13},
+       {13000000,  100000000, 200, 1,  26, 13},
+       {12000000,  100000000, 200, 1,  24, 13},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct div_nmp plle_nmp = {
+       .divm_shift = 0,
+       .divm_width = 8,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .divp_shift = 24,
+       .divp_width = 4,
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 75000000,
+       .vco_min = 1600000000,
+       .vco_max = 2400000000U,
+       .base_reg = PLLE_BASE,
+       .misc_reg = PLLE_MISC,
+       .aux_reg = PLLE_AUX,
+       .lock_mask = PLLE_MISC_LOCK,
+       .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .div_nmp = &plle_nmp,
+       .freq_table = pll_e_freq_table,
+       .flags = TEGRA_PLL_FIXED,
+       .fixed_rate = 100000000,
+};
+
+static const struct clk_div_table pll_re_div_table[] = {
+       { .val = 0, .div = 1 },
+       { .val = 1, .div = 2 },
+       { .val = 2, .div = 3 },
+       { .val = 3, .div = 4 },
+       { .val = 4, .div = 5 },
+       { .val = 5, .div = 6 },
+       { .val = 0, .div = 0 },
+};
+
+static struct div_nmp pllre_nmp = {
+       .divm_shift = 0,
+       .divm_width = 8,
+       .divn_shift = 8,
+       .divn_width = 8,
+       .divp_shift = 16,
+       .divp_width = 4,
+};
+
+static struct tegra_clk_pll_params pll_re_vco_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+       .vco_min = 300000000,
+       .vco_max = 600000000,
+       .base_reg = PLLRE_BASE,
+       .misc_reg = PLLRE_MISC,
+       .lock_mask = PLLRE_MISC_LOCK,
+       .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLRE_MISC,
+       .iddq_bit_idx = PLLRE_IDDQ_BIT,
+       .div_nmp = &pllre_nmp,
+       .flags = TEGRA_PLL_USE_LOCK,
+};
+
+static struct div_nmp pllp_nmp = {
+       .divm_shift = 0,
+       .divm_width = 5,
+       .divn_shift = 8,
+       .divn_width = 10,
+       .divp_shift = 20,
+       .divp_width = 3,
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+       {12000000, 216000000, 432, 12, 1, 8},
+       {13000000, 216000000, 432, 13, 1, 8},
+       {16800000, 216000000, 360, 14, 1, 8},
+       {19200000, 216000000, 360, 16, 1, 8},
+       {26000000, 216000000, 432, 26, 1, 8},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 200000000,
+       .vco_max = 700000000,
+       .base_reg = PLLP_BASE,
+       .misc_reg = PLLP_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .div_nmp = &pllp_nmp,
+       .freq_table = pll_p_freq_table,
+       .fixed_rate = 408000000,
+       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+       {9600000, 282240000, 147, 5, 0, 4},
+       {9600000, 368640000, 192, 5, 0, 4},
+       {9600000, 240000000, 200, 8, 0, 8},
+
+       {28800000, 282240000, 245, 25, 0, 8},
+       {28800000, 368640000, 320, 25, 0, 8},
+       {28800000, 240000000, 200, 24, 0, 8},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_a_params = {
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 200000000,
+       .vco_max = 700000000,
+       .base_reg = PLLA_BASE,
+       .misc_reg = PLLA_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .div_nmp = &pllp_nmp,
+       .freq_table = pll_a_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+       {12000000, 216000000, 864, 12, 4, 12},
+       {13000000, 216000000, 864, 13, 4, 12},
+       {16800000, 216000000, 720, 14, 4, 12},
+       {19200000, 216000000, 720, 16, 4, 12},
+       {26000000, 216000000, 864, 26, 4, 12},
+
+       {12000000, 594000000, 594, 12, 1, 12},
+       {13000000, 594000000, 594, 13, 1, 12},
+       {16800000, 594000000, 495, 14, 1, 12},
+       {19200000, 594000000, 495, 16, 1, 12},
+       {26000000, 594000000, 594, 26, 1, 12},
+
+       {12000000, 1000000000, 1000, 12, 1, 12},
+       {13000000, 1000000000, 1000, 13, 1, 12},
+       {19200000, 1000000000, 625, 12, 1, 12},
+       {26000000, 1000000000, 1000, 26, 1, 12},
+
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 500000000,
+       .vco_max = 1000000000,
+       .base_reg = PLLD_BASE,
+       .misc_reg = PLLD_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+       .lock_delay = 1000,
+       .div_nmp = &pllp_nmp,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
+};
+
+static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = {
+       { 12000000, 148500000,  99, 1, 8},
+       { 12000000, 594000000,  99, 1, 1},
+       { 13000000, 594000000,  91, 1, 1},      /* actual: 591.5 MHz */
+       { 16800000, 594000000,  71, 1, 1},      /* actual: 596.4 MHz */
+       { 19200000, 594000000,  62, 1, 1},      /* actual: 595.2 MHz */
+       { 26000000, 594000000,  91, 2, 1},      /* actual: 591.5 MHz */
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params tegra124_pll_d2_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLD2_BASE,
+       .misc_reg = PLLD2_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLD2_BASE,
+       .iddq_bit_idx = PLLSS_IDDQ_BIT,
+       .pdiv_tohw = pll12g_ssd_esd_p,
+       .div_nmp = &pllss_nmp,
+       .ext_misc_reg[0] = 0x570,
+       .ext_misc_reg[1] = 0x574,
+       .ext_misc_reg[2] = 0x578,
+       .max_p = 15,
+       .freq_table = tegra124_pll_d2_freq_table,
+};
+
+static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = {
+       { 12000000, 600000000, 100, 1, 1},
+       { 13000000, 600000000,  92, 1, 1},      /* actual: 598.0 MHz */
+       { 16800000, 600000000,  71, 1, 1},      /* actual: 596.4 MHz */
+       { 19200000, 600000000,  62, 1, 1},      /* actual: 595.2 MHz */
+       { 26000000, 600000000,  92, 2, 1},      /* actual: 598.0 MHz */
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_dp_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLDP_BASE,
+       .misc_reg = PLLDP_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLDP_BASE,
+       .iddq_bit_idx = PLLSS_IDDQ_BIT,
+       .pdiv_tohw = pll12g_ssd_esd_p,
+       .div_nmp = &pllss_nmp,
+       .ext_misc_reg[0] = 0x598,
+       .ext_misc_reg[1] = 0x59c,
+       .ext_misc_reg[2] = 0x5a0,
+       .max_p = 5,
+       .freq_table = pll_dp_freq_table,
+};
+
+static struct pdiv_map pllu_p[] = {
+       { .pdiv = 1, .hw_val = 1 },
+       { .pdiv = 2, .hw_val = 0 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct div_nmp pllu_nmp = {
+       .divm_shift = 0,
+       .divm_width = 5,
+       .divn_shift = 8,
+       .divn_width = 10,
+       .divp_shift = 20,
+       .divp_width = 1,
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+       {12000000, 480000000, 960, 12, 2, 12},
+       {13000000, 480000000, 960, 13, 2, 12},
+       {16800000, 480000000, 400, 7, 2, 5},
+       {19200000, 480000000, 200, 4, 2, 3},
+       {26000000, 480000000, 960, 26, 2, 12},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 480000000,
+       .vco_max = 960000000,
+       .base_reg = PLLU_BASE,
+       .misc_reg = PLLU_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+       .lock_delay = 1000,
+       .pdiv_tohw = pllu_p,
+       .div_nmp = &pllu_nmp,
+       .freq_table = pll_u_freq_table,
+       .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
+};
+
+struct utmi_clk_param {
+       /* Oscillator Frequency in KHz */
+       u32 osc_frequency;
+       /* UTMIP PLL Enable Delay Count  */
+       u8 enable_delay_count;
+       /* UTMIP PLL Stable count */
+       u8 stable_count;
+       /*  UTMIP PLL Active delay count */
+       u8 active_delay_count;
+       /* UTMIP PLL Xtal frequency count */
+       u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+       {.osc_frequency = 13000000, .enable_delay_count = 0x02,
+        .stable_count = 0x33, .active_delay_count = 0x05,
+        .xtal_freq_count = 0x7F},
+       {.osc_frequency = 19200000, .enable_delay_count = 0x03,
+        .stable_count = 0x4B, .active_delay_count = 0x06,
+        .xtal_freq_count = 0xBB},
+       {.osc_frequency = 12000000, .enable_delay_count = 0x02,
+        .stable_count = 0x2F, .active_delay_count = 0x04,
+        .xtal_freq_count = 0x76},
+       {.osc_frequency = 26000000, .enable_delay_count = 0x04,
+        .stable_count = 0x66, .active_delay_count = 0x09,
+        .xtal_freq_count = 0xFE},
+       {.osc_frequency = 16800000, .enable_delay_count = 0x03,
+        .stable_count = 0x41, .active_delay_count = 0x0A,
+        .xtal_freq_count = 0xA4},
+};
+
+static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
+       [tegra_clk_ispb] = { .dt_id = TEGRA124_CLK_ISPB, .present = true },
+       [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true },
+       [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true },
+       [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true },
+       [tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
+       [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true },
+       [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true },
+       [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true },
+       [tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
+       [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true },
+       [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true },
+       [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true },
+       [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true },
+       [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true },
+       [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true },
+       [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true },
+       [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true },
+       [tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true },
+       [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true },
+       [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true },
+       [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true },
+       [tegra_clk_kbc] = { .dt_id = TEGRA124_CLK_KBC, .present = true },
+       [tegra_clk_kfuse] = { .dt_id = TEGRA124_CLK_KFUSE, .present = true },
+       [tegra_clk_sbc1] = { .dt_id = TEGRA124_CLK_SBC1, .present = true },
+       [tegra_clk_nor] = { .dt_id = TEGRA124_CLK_NOR, .present = true },
+       [tegra_clk_sbc2] = { .dt_id = TEGRA124_CLK_SBC2, .present = true },
+       [tegra_clk_sbc3] = { .dt_id = TEGRA124_CLK_SBC3, .present = true },
+       [tegra_clk_i2c5] = { .dt_id = TEGRA124_CLK_I2C5, .present = true },
+       [tegra_clk_dsia] = { .dt_id = TEGRA124_CLK_DSIA, .present = true },
+       [tegra_clk_mipi] = { .dt_id = TEGRA124_CLK_MIPI, .present = true },
+       [tegra_clk_hdmi] = { .dt_id = TEGRA124_CLK_HDMI, .present = true },
+       [tegra_clk_csi] = { .dt_id = TEGRA124_CLK_CSI, .present = true },
+       [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true },
+       [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true },
+       [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true },
+       [tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true },
+       [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true },
+       [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true },
+       [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true },
+       [tegra_clk_bsea] = { .dt_id = TEGRA124_CLK_BSEA, .present = true },
+       [tegra_clk_bsev] = { .dt_id = TEGRA124_CLK_BSEV, .present = true },
+       [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true },
+       [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true },
+       [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true },
+       [tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true },
+       [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true },
+       [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true },
+       [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true },
+       [tegra_clk_csite] = { .dt_id = TEGRA124_CLK_CSITE, .present = true },
+       [tegra_clk_la] = { .dt_id = TEGRA124_CLK_LA, .present = true },
+       [tegra_clk_trace] = { .dt_id = TEGRA124_CLK_TRACE, .present = true },
+       [tegra_clk_soc_therm] = { .dt_id = TEGRA124_CLK_SOC_THERM, .present = true },
+       [tegra_clk_dtv] = { .dt_id = TEGRA124_CLK_DTV, .present = true },
+       [tegra_clk_ndspeed] = { .dt_id = TEGRA124_CLK_NDSPEED, .present = true },
+       [tegra_clk_i2cslow] = { .dt_id = TEGRA124_CLK_I2CSLOW, .present = true },
+       [tegra_clk_dsib] = { .dt_id = TEGRA124_CLK_DSIB, .present = true },
+       [tegra_clk_tsec] = { .dt_id = TEGRA124_CLK_TSEC, .present = true },
+       [tegra_clk_xusb_host] = { .dt_id = TEGRA124_CLK_XUSB_HOST, .present = true },
+       [tegra_clk_msenc] = { .dt_id = TEGRA124_CLK_MSENC, .present = true },
+       [tegra_clk_csus] = { .dt_id = TEGRA124_CLK_CSUS, .present = true },
+       [tegra_clk_mselect] = { .dt_id = TEGRA124_CLK_MSELECT, .present = true },
+       [tegra_clk_tsensor] = { .dt_id = TEGRA124_CLK_TSENSOR, .present = true },
+       [tegra_clk_i2s3] = { .dt_id = TEGRA124_CLK_I2S3, .present = true },
+       [tegra_clk_i2s4] = { .dt_id = TEGRA124_CLK_I2S4, .present = true },
+       [tegra_clk_i2c4] = { .dt_id = TEGRA124_CLK_I2C4, .present = true },
+       [tegra_clk_sbc5] = { .dt_id = TEGRA124_CLK_SBC5, .present = true },
+       [tegra_clk_sbc6] = { .dt_id = TEGRA124_CLK_SBC6, .present = true },
+       [tegra_clk_d_audio] = { .dt_id = TEGRA124_CLK_D_AUDIO, .present = true },
+       [tegra_clk_apbif] = { .dt_id = TEGRA124_CLK_APBIF, .present = true },
+       [tegra_clk_dam0] = { .dt_id = TEGRA124_CLK_DAM0, .present = true },
+       [tegra_clk_dam1] = { .dt_id = TEGRA124_CLK_DAM1, .present = true },
+       [tegra_clk_dam2] = { .dt_id = TEGRA124_CLK_DAM2, .present = true },
+       [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA124_CLK_HDA2CODEC_2X, .present = true },
+       [tegra_clk_audio0_2x] = { .dt_id = TEGRA124_CLK_AUDIO0_2X, .present = true },
+       [tegra_clk_audio1_2x] = { .dt_id = TEGRA124_CLK_AUDIO1_2X, .present = true },
+       [tegra_clk_audio2_2x] = { .dt_id = TEGRA124_CLK_AUDIO2_2X, .present = true },
+       [tegra_clk_audio3_2x] = { .dt_id = TEGRA124_CLK_AUDIO3_2X, .present = true },
+       [tegra_clk_audio4_2x] = { .dt_id = TEGRA124_CLK_AUDIO4_2X, .present = true },
+       [tegra_clk_spdif_2x] = { .dt_id = TEGRA124_CLK_SPDIF_2X, .present = true },
+       [tegra_clk_actmon] = { .dt_id = TEGRA124_CLK_ACTMON, .present = true },
+       [tegra_clk_extern1] = { .dt_id = TEGRA124_CLK_EXTERN1, .present = true },
+       [tegra_clk_extern2] = { .dt_id = TEGRA124_CLK_EXTERN2, .present = true },
+       [tegra_clk_extern3] = { .dt_id = TEGRA124_CLK_EXTERN3, .present = true },
+       [tegra_clk_sata_oob] = { .dt_id = TEGRA124_CLK_SATA_OOB, .present = true },
+       [tegra_clk_sata] = { .dt_id = TEGRA124_CLK_SATA, .present = true },
+       [tegra_clk_hda] = { .dt_id = TEGRA124_CLK_HDA, .present = true },
+       [tegra_clk_se] = { .dt_id = TEGRA124_CLK_SE, .present = true },
+       [tegra_clk_hda2hdmi] = { .dt_id = TEGRA124_CLK_HDA2HDMI, .present = true },
+       [tegra_clk_sata_cold] = { .dt_id = TEGRA124_CLK_SATA_COLD, .present = true },
+       [tegra_clk_cilab] = { .dt_id = TEGRA124_CLK_CILAB, .present = true },
+       [tegra_clk_cilcd] = { .dt_id = TEGRA124_CLK_CILCD, .present = true },
+       [tegra_clk_cile] = { .dt_id = TEGRA124_CLK_CILE, .present = true },
+       [tegra_clk_dsialp] = { .dt_id = TEGRA124_CLK_DSIALP, .present = true },
+       [tegra_clk_dsiblp] = { .dt_id = TEGRA124_CLK_DSIBLP, .present = true },
+       [tegra_clk_entropy] = { .dt_id = TEGRA124_CLK_ENTROPY, .present = true },
+       [tegra_clk_dds] = { .dt_id = TEGRA124_CLK_DDS, .present = true },
+       [tegra_clk_dp2] = { .dt_id = TEGRA124_CLK_DP2, .present = true },
+       [tegra_clk_amx] = { .dt_id = TEGRA124_CLK_AMX, .present = true },
+       [tegra_clk_adx] = { .dt_id = TEGRA124_CLK_ADX, .present = true },
+       [tegra_clk_xusb_ss] = { .dt_id = TEGRA124_CLK_XUSB_SS, .present = true },
+       [tegra_clk_i2c6] = { .dt_id = TEGRA124_CLK_I2C6, .present = true },
+       [tegra_clk_vim2_clk] = { .dt_id = TEGRA124_CLK_VIM2_CLK, .present = true },
+       [tegra_clk_hdmi_audio] = { .dt_id = TEGRA124_CLK_HDMI_AUDIO, .present = true },
+       [tegra_clk_clk72Mhz] = { .dt_id = TEGRA124_CLK_CLK72MHZ, .present = true },
+       [tegra_clk_vic03] = { .dt_id = TEGRA124_CLK_VIC03, .present = true },
+       [tegra_clk_adx1] = { .dt_id = TEGRA124_CLK_ADX1, .present = true },
+       [tegra_clk_dpaux] = { .dt_id = TEGRA124_CLK_DPAUX, .present = true },
+       [tegra_clk_sor0] = { .dt_id = TEGRA124_CLK_SOR0, .present = true },
+       [tegra_clk_sor0_lvds] = { .dt_id = TEGRA124_CLK_SOR0_LVDS, .present = true },
+       [tegra_clk_gpu] = { .dt_id = TEGRA124_CLK_GPU, .present = true },
+       [tegra_clk_amx1] = { .dt_id = TEGRA124_CLK_AMX1, .present = true },
+       [tegra_clk_uartb] = { .dt_id = TEGRA124_CLK_UARTB, .present = true },
+       [tegra_clk_vfir] = { .dt_id = TEGRA124_CLK_VFIR, .present = true },
+       [tegra_clk_spdif_in] = { .dt_id = TEGRA124_CLK_SPDIF_IN, .present = true },
+       [tegra_clk_spdif_out] = { .dt_id = TEGRA124_CLK_SPDIF_OUT, .present = true },
+       [tegra_clk_vi_9] = { .dt_id = TEGRA124_CLK_VI, .present = true },
+       [tegra_clk_vi_sensor] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true },
+       [tegra_clk_fuse] = { .dt_id = TEGRA124_CLK_FUSE, .present = true },
+       [tegra_clk_fuse_burn] = { .dt_id = TEGRA124_CLK_FUSE_BURN, .present = true },
+       [tegra_clk_clk_32k] = { .dt_id = TEGRA124_CLK_CLK_32K, .present = true },
+       [tegra_clk_clk_m] = { .dt_id = TEGRA124_CLK_CLK_M, .present = true },
+       [tegra_clk_clk_m_div2] = { .dt_id = TEGRA124_CLK_CLK_M_DIV2, .present = true },
+       [tegra_clk_clk_m_div4] = { .dt_id = TEGRA124_CLK_CLK_M_DIV4, .present = true },
+       [tegra_clk_pll_ref] = { .dt_id = TEGRA124_CLK_PLL_REF, .present = true },
+       [tegra_clk_pll_c] = { .dt_id = TEGRA124_CLK_PLL_C, .present = true },
+       [tegra_clk_pll_c_out1] = { .dt_id = TEGRA124_CLK_PLL_C_OUT1, .present = true },
+       [tegra_clk_pll_c2] = { .dt_id = TEGRA124_CLK_PLL_C2, .present = true },
+       [tegra_clk_pll_c3] = { .dt_id = TEGRA124_CLK_PLL_C3, .present = true },
+       [tegra_clk_pll_m] = { .dt_id = TEGRA124_CLK_PLL_M, .present = true },
+       [tegra_clk_pll_m_out1] = { .dt_id = TEGRA124_CLK_PLL_M_OUT1, .present = true },
+       [tegra_clk_pll_p] = { .dt_id = TEGRA124_CLK_PLL_P, .present = true },
+       [tegra_clk_pll_p_out1] = { .dt_id = TEGRA124_CLK_PLL_P_OUT1, .present = true },
+       [tegra_clk_pll_p_out2] = { .dt_id = TEGRA124_CLK_PLL_P_OUT2, .present = true },
+       [tegra_clk_pll_p_out3] = { .dt_id = TEGRA124_CLK_PLL_P_OUT3, .present = true },
+       [tegra_clk_pll_p_out4] = { .dt_id = TEGRA124_CLK_PLL_P_OUT4, .present = true },
+       [tegra_clk_pll_a] = { .dt_id = TEGRA124_CLK_PLL_A, .present = true },
+       [tegra_clk_pll_a_out0] = { .dt_id = TEGRA124_CLK_PLL_A_OUT0, .present = true },
+       [tegra_clk_pll_d] = { .dt_id = TEGRA124_CLK_PLL_D, .present = true },
+       [tegra_clk_pll_d_out0] = { .dt_id = TEGRA124_CLK_PLL_D_OUT0, .present = true },
+       [tegra_clk_pll_d2] = { .dt_id = TEGRA124_CLK_PLL_D2, .present = true },
+       [tegra_clk_pll_d2_out0] = { .dt_id = TEGRA124_CLK_PLL_D2_OUT0, .present = true },
+       [tegra_clk_pll_u] = { .dt_id = TEGRA124_CLK_PLL_U, .present = true },
+       [tegra_clk_pll_u_480m] = { .dt_id = TEGRA124_CLK_PLL_U_480M, .present = true },
+       [tegra_clk_pll_u_60m] = { .dt_id = TEGRA124_CLK_PLL_U_60M, .present = true },
+       [tegra_clk_pll_u_48m] = { .dt_id = TEGRA124_CLK_PLL_U_48M, .present = true },
+       [tegra_clk_pll_u_12m] = { .dt_id = TEGRA124_CLK_PLL_U_12M, .present = true },
+       [tegra_clk_pll_x] = { .dt_id = TEGRA124_CLK_PLL_X, .present = true },
+       [tegra_clk_pll_x_out0] = { .dt_id = TEGRA124_CLK_PLL_X_OUT0, .present = true },
+       [tegra_clk_pll_re_vco] = { .dt_id = TEGRA124_CLK_PLL_RE_VCO, .present = true },
+       [tegra_clk_pll_re_out] = { .dt_id = TEGRA124_CLK_PLL_RE_OUT, .present = true },
+       [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA124_CLK_SPDIF_IN_SYNC, .present = true },
+       [tegra_clk_i2s0_sync] = { .dt_id = TEGRA124_CLK_I2S0_SYNC, .present = true },
+       [tegra_clk_i2s1_sync] = { .dt_id = TEGRA124_CLK_I2S1_SYNC, .present = true },
+       [tegra_clk_i2s2_sync] = { .dt_id = TEGRA124_CLK_I2S2_SYNC, .present = true },
+       [tegra_clk_i2s3_sync] = { .dt_id = TEGRA124_CLK_I2S3_SYNC, .present = true },
+       [tegra_clk_i2s4_sync] = { .dt_id = TEGRA124_CLK_I2S4_SYNC, .present = true },
+       [tegra_clk_vimclk_sync] = { .dt_id = TEGRA124_CLK_VIMCLK_SYNC, .present = true },
+       [tegra_clk_audio0] = { .dt_id = TEGRA124_CLK_AUDIO0, .present = true },
+       [tegra_clk_audio1] = { .dt_id = TEGRA124_CLK_AUDIO1, .present = true },
+       [tegra_clk_audio2] = { .dt_id = TEGRA124_CLK_AUDIO2, .present = true },
+       [tegra_clk_audio3] = { .dt_id = TEGRA124_CLK_AUDIO3, .present = true },
+       [tegra_clk_audio4] = { .dt_id = TEGRA124_CLK_AUDIO4, .present = true },
+       [tegra_clk_spdif] = { .dt_id = TEGRA124_CLK_SPDIF, .present = true },
+       [tegra_clk_clk_out_1] = { .dt_id = TEGRA124_CLK_CLK_OUT_1, .present = true },
+       [tegra_clk_clk_out_2] = { .dt_id = TEGRA124_CLK_CLK_OUT_2, .present = true },
+       [tegra_clk_clk_out_3] = { .dt_id = TEGRA124_CLK_CLK_OUT_3, .present = true },
+       [tegra_clk_blink] = { .dt_id = TEGRA124_CLK_BLINK, .present = true },
+       [tegra_clk_xusb_host_src] = { .dt_id = TEGRA124_CLK_XUSB_HOST_SRC, .present = true },
+       [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA124_CLK_XUSB_FALCON_SRC, .present = true },
+       [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA124_CLK_XUSB_FS_SRC, .present = true },
+       [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA124_CLK_XUSB_SS_SRC, .present = true },
+       [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA124_CLK_XUSB_DEV_SRC, .present = true },
+       [tegra_clk_xusb_dev] = { .dt_id = TEGRA124_CLK_XUSB_DEV, .present = true },
+       [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA124_CLK_XUSB_HS_SRC, .present = true },
+       [tegra_clk_sclk] = { .dt_id = TEGRA124_CLK_SCLK, .present = true },
+       [tegra_clk_hclk] = { .dt_id = TEGRA124_CLK_HCLK, .present = true },
+       [tegra_clk_pclk] = { .dt_id = TEGRA124_CLK_PCLK, .present = true },
+       [tegra_clk_cclk_g] = { .dt_id = TEGRA124_CLK_CCLK_G, .present = true },
+       [tegra_clk_cclk_lp] = { .dt_id = TEGRA124_CLK_CCLK_LP, .present = true },
+       [tegra_clk_dfll_ref] = { .dt_id = TEGRA124_CLK_DFLL_REF, .present = true },
+       [tegra_clk_dfll_soc] = { .dt_id = TEGRA124_CLK_DFLL_SOC, .present = true },
+       [tegra_clk_vi_sensor2] = { .dt_id = TEGRA124_CLK_VI_SENSOR2, .present = true },
+       [tegra_clk_pll_p_out5] = { .dt_id = TEGRA124_CLK_PLL_P_OUT5, .present = true },
+       [tegra_clk_pll_c4] = { .dt_id = TEGRA124_CLK_PLL_C4, .present = true },
+       [tegra_clk_pll_dp] = { .dt_id = TEGRA124_CLK_PLL_DP, .present = true },
+       [tegra_clk_audio0_mux] = { .dt_id = TEGRA124_CLK_AUDIO0_MUX, .present = true },
+       [tegra_clk_audio1_mux] = { .dt_id = TEGRA124_CLK_AUDIO1_MUX, .present = true },
+       [tegra_clk_audio2_mux] = { .dt_id = TEGRA124_CLK_AUDIO2_MUX, .present = true },
+       [tegra_clk_audio3_mux] = { .dt_id = TEGRA124_CLK_AUDIO3_MUX, .present = true },
+       [tegra_clk_audio4_mux] = { .dt_id = TEGRA124_CLK_AUDIO4_MUX, .present = true },
+       [tegra_clk_spdif_mux] = { .dt_id = TEGRA124_CLK_SPDIF_MUX, .present = true },
+       [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true },
+       [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true },
+       [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
+       [tegra_clk_dsia_mux] = { .dt_id = TEGRA124_CLK_DSIA_MUX, .present = true },
+       [tegra_clk_dsib_mux] = { .dt_id = TEGRA124_CLK_DSIB_MUX, .present = true },
+       [tegra_clk_uarte] = { .dt_id = TEGRA124_CLK_UARTE, .present = true },
+};
+
+static struct tegra_devclk devclks[] __initdata = {
+       { .con_id = "clk_m", .dt_id = TEGRA124_CLK_CLK_M },
+       { .con_id = "pll_ref", .dt_id = TEGRA124_CLK_PLL_REF },
+       { .con_id = "clk_32k", .dt_id = TEGRA124_CLK_CLK_32K },
+       { .con_id = "clk_m_div2", .dt_id = TEGRA124_CLK_CLK_M_DIV2 },
+       { .con_id = "clk_m_div4", .dt_id = TEGRA124_CLK_CLK_M_DIV4 },
+       { .con_id = "pll_c", .dt_id = TEGRA124_CLK_PLL_C },
+       { .con_id = "pll_c_out1", .dt_id = TEGRA124_CLK_PLL_C_OUT1 },
+       { .con_id = "pll_c2", .dt_id = TEGRA124_CLK_PLL_C2 },
+       { .con_id = "pll_c3", .dt_id = TEGRA124_CLK_PLL_C3 },
+       { .con_id = "pll_p", .dt_id = TEGRA124_CLK_PLL_P },
+       { .con_id = "pll_p_out1", .dt_id = TEGRA124_CLK_PLL_P_OUT1 },
+       { .con_id = "pll_p_out2", .dt_id = TEGRA124_CLK_PLL_P_OUT2 },
+       { .con_id = "pll_p_out3", .dt_id = TEGRA124_CLK_PLL_P_OUT3 },
+       { .con_id = "pll_p_out4", .dt_id = TEGRA124_CLK_PLL_P_OUT4 },
+       { .con_id = "pll_m", .dt_id = TEGRA124_CLK_PLL_M },
+       { .con_id = "pll_m_out1", .dt_id = TEGRA124_CLK_PLL_M_OUT1 },
+       { .con_id = "pll_x", .dt_id = TEGRA124_CLK_PLL_X },
+       { .con_id = "pll_x_out0", .dt_id = TEGRA124_CLK_PLL_X_OUT0 },
+       { .con_id = "pll_u", .dt_id = TEGRA124_CLK_PLL_U },
+       { .con_id = "pll_u_480M", .dt_id = TEGRA124_CLK_PLL_U_480M },
+       { .con_id = "pll_u_60M", .dt_id = TEGRA124_CLK_PLL_U_60M },
+       { .con_id = "pll_u_48M", .dt_id = TEGRA124_CLK_PLL_U_48M },
+       { .con_id = "pll_u_12M", .dt_id = TEGRA124_CLK_PLL_U_12M },
+       { .con_id = "pll_d", .dt_id = TEGRA124_CLK_PLL_D },
+       { .con_id = "pll_d_out0", .dt_id = TEGRA124_CLK_PLL_D_OUT0 },
+       { .con_id = "pll_d2", .dt_id = TEGRA124_CLK_PLL_D2 },
+       { .con_id = "pll_d2_out0", .dt_id = TEGRA124_CLK_PLL_D2_OUT0 },
+       { .con_id = "pll_a", .dt_id = TEGRA124_CLK_PLL_A },
+       { .con_id = "pll_a_out0", .dt_id = TEGRA124_CLK_PLL_A_OUT0 },
+       { .con_id = "pll_re_vco", .dt_id = TEGRA124_CLK_PLL_RE_VCO },
+       { .con_id = "pll_re_out", .dt_id = TEGRA124_CLK_PLL_RE_OUT },
+       { .con_id = "spdif_in_sync", .dt_id = TEGRA124_CLK_SPDIF_IN_SYNC },
+       { .con_id = "i2s0_sync", .dt_id = TEGRA124_CLK_I2S0_SYNC },
+       { .con_id = "i2s1_sync", .dt_id = TEGRA124_CLK_I2S1_SYNC },
+       { .con_id = "i2s2_sync", .dt_id = TEGRA124_CLK_I2S2_SYNC },
+       { .con_id = "i2s3_sync", .dt_id = TEGRA124_CLK_I2S3_SYNC },
+       { .con_id = "i2s4_sync", .dt_id = TEGRA124_CLK_I2S4_SYNC },
+       { .con_id = "vimclk_sync", .dt_id = TEGRA124_CLK_VIMCLK_SYNC },
+       { .con_id = "audio0", .dt_id = TEGRA124_CLK_AUDIO0 },
+       { .con_id = "audio1", .dt_id = TEGRA124_CLK_AUDIO1 },
+       { .con_id = "audio2", .dt_id = TEGRA124_CLK_AUDIO2 },
+       { .con_id = "audio3", .dt_id = TEGRA124_CLK_AUDIO3 },
+       { .con_id = "audio4", .dt_id = TEGRA124_CLK_AUDIO4 },
+       { .con_id = "spdif", .dt_id = TEGRA124_CLK_SPDIF },
+       { .con_id = "audio0_2x", .dt_id = TEGRA124_CLK_AUDIO0_2X },
+       { .con_id = "audio1_2x", .dt_id = TEGRA124_CLK_AUDIO1_2X },
+       { .con_id = "audio2_2x", .dt_id = TEGRA124_CLK_AUDIO2_2X },
+       { .con_id = "audio3_2x", .dt_id = TEGRA124_CLK_AUDIO3_2X },
+       { .con_id = "audio4_2x", .dt_id = TEGRA124_CLK_AUDIO4_2X },
+       { .con_id = "spdif_2x", .dt_id = TEGRA124_CLK_SPDIF_2X },
+       { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA124_CLK_EXTERN1 },
+       { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA124_CLK_EXTERN2 },
+       { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA124_CLK_EXTERN3 },
+       { .con_id = "blink", .dt_id = TEGRA124_CLK_BLINK },
+       { .con_id = "cclk_g", .dt_id = TEGRA124_CLK_CCLK_G },
+       { .con_id = "cclk_lp", .dt_id = TEGRA124_CLK_CCLK_LP },
+       { .con_id = "sclk", .dt_id = TEGRA124_CLK_SCLK },
+       { .con_id = "hclk", .dt_id = TEGRA124_CLK_HCLK },
+       { .con_id = "pclk", .dt_id = TEGRA124_CLK_PCLK },
+       { .con_id = "fuse", .dt_id = TEGRA124_CLK_FUSE },
+       { .dev_id = "rtc-tegra", .dt_id = TEGRA124_CLK_RTC },
+       { .dev_id = "timer", .dt_id = TEGRA124_CLK_TIMER },
+};
+
+static struct clk **clks;
+
+static void tegra124_utmi_param_configure(void __iomem *clk_base)
+{
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (osc_freq == utmi_parameters[i].osc_frequency)
+                       break;
+       }
+
+       if (i >= ARRAY_SIZE(utmi_parameters)) {
+               pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+                      osc_freq);
+               return;
+       }
+
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL stable and active counts */
+       /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+       reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+       reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].
+                                           active_delay_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].
+                                           enable_delay_count);
+
+       reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].
+                                          xtal_freq_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       /* Setup HW control of UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       udelay(1);
+
+       /* Setup SW override of UTMIPLL assuming USB2.0
+          ports are assigned to USB2 */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       /* Enable HW control UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static __init void tegra124_periph_clk_init(void __iomem *clk_base,
+                                           void __iomem *pmc_base)
+{
+       struct clk *clk;
+       u32 val;
+
+       /* xusb_hs_src */
+       val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
+       val |= BIT(25); /* always select PLLU_60M */
+       writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
+
+       clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
+                                       1, 1);
+       clks[TEGRA124_CLK_XUSB_HS_SRC] = clk;
+
+       /* dsia mux */
+       clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
+       clks[TEGRA124_CLK_DSIA_MUX] = clk;
+
+       /* dsib mux */
+       clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
+       clks[TEGRA124_CLK_DSIB_MUX] = clk;
+
+       /* emc mux */
+       clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+                              ARRAY_SIZE(mux_pllmcp_clkm), 0,
+                              clk_base + CLK_SOURCE_EMC,
+                              29, 3, 0, NULL);
+
+       /* cml0 */
+       clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
+                               0, 0, &pll_e_lock);
+       clk_register_clkdev(clk, "cml0", NULL);
+       clks[TEGRA124_CLK_CML0] = clk;
+
+       /* cml1 */
+       clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX,
+                               1, 0, &pll_e_lock);
+       clk_register_clkdev(clk, "cml1", NULL);
+       clks[TEGRA124_CLK_CML1] = clk;
+
+       tegra_periph_clk_init(clk_base, pmc_base, tegra124_clks, &pll_p_params);
+}
+
+static void __init tegra124_pll_init(void __iomem *clk_base,
+                                    void __iomem *pmc)
+{
+       u32 val;
+       struct clk *clk;
+
+       /* PLLC */
+       clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+                       pmc, 0, &pll_c_params, NULL);
+       clk_register_clkdev(clk, "pll_c", NULL);
+       clks[TEGRA124_CLK_PLL_C] = clk;
+
+       /* PLLC_OUT1 */
+       clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+                       clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                       8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+                               clk_base + PLLC_OUT, 1, 0,
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clk_register_clkdev(clk, "pll_c_out1", NULL);
+       clks[TEGRA124_CLK_PLL_C_OUT1] = clk;
+
+       /* PLLC2 */
+       clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0,
+                            &pll_c2_params, NULL);
+       clk_register_clkdev(clk, "pll_c2", NULL);
+       clks[TEGRA124_CLK_PLL_C2] = clk;
+
+       /* PLLC3 */
+       clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0,
+                            &pll_c3_params, NULL);
+       clk_register_clkdev(clk, "pll_c3", NULL);
+       clks[TEGRA124_CLK_PLL_C3] = clk;
+
+       /* PLLM */
+       clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
+                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+                            &pll_m_params, NULL);
+       clk_register_clkdev(clk, "pll_m", NULL);
+       clks[TEGRA124_CLK_PLL_M] = clk;
+
+       /* PLLM_OUT1 */
+       clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+                               clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                               8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+                               clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clk_register_clkdev(clk, "pll_m_out1", NULL);
+       clks[TEGRA124_CLK_PLL_M_OUT1] = clk;
+
+       /* PLLM_UD */
+       clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
+                                       CLK_SET_RATE_PARENT, 1, 1);
+
+       /* PLLU */
+       val = readl(clk_base + pll_u_params.base_reg);
+       val &= ~BIT(24); /* disable PLLU_OVERRIDE */
+       writel(val, clk_base + pll_u_params.base_reg);
+
+       clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
+                           &pll_u_params, &pll_u_lock);
+       clk_register_clkdev(clk, "pll_u", NULL);
+       clks[TEGRA124_CLK_PLL_U] = clk;
+
+       tegra124_utmi_param_configure(clk_base);
+
+       /* PLLU_480M */
+       clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
+                               CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+                               22, 0, &pll_u_lock);
+       clk_register_clkdev(clk, "pll_u_480M", NULL);
+       clks[TEGRA124_CLK_PLL_U_480M] = clk;
+
+       /* PLLU_60M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 8);
+       clk_register_clkdev(clk, "pll_u_60M", NULL);
+       clks[TEGRA124_CLK_PLL_U_60M] = clk;
+
+       /* PLLU_48M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 10);
+       clk_register_clkdev(clk, "pll_u_48M", NULL);
+       clks[TEGRA124_CLK_PLL_U_48M] = clk;
+
+       /* PLLU_12M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 40);
+       clk_register_clkdev(clk, "pll_u_12M", NULL);
+       clks[TEGRA124_CLK_PLL_U_12M] = clk;
+
+       /* PLLD */
+       clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
+                           &pll_d_params, &pll_d_lock);
+       clk_register_clkdev(clk, "pll_d", NULL);
+       clks[TEGRA124_CLK_PLL_D] = clk;
+
+       /* PLLD_OUT0 */
+       clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "pll_d_out0", NULL);
+       clks[TEGRA124_CLK_PLL_D_OUT0] = clk;
+
+       /* PLLRE */
+       clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
+                            0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq);
+       clk_register_clkdev(clk, "pll_re_vco", NULL);
+       clks[TEGRA124_CLK_PLL_RE_VCO] = clk;
+
+       clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
+                                        clk_base + PLLRE_BASE, 16, 4, 0,
+                                        pll_re_div_table, &pll_re_lock);
+       clk_register_clkdev(clk, "pll_re_out", NULL);
+       clks[TEGRA124_CLK_PLL_RE_OUT] = clk;
+
+       /* PLLE */
+       clk = tegra_clk_register_plle_tegra114("pll_e", "pll_ref",
+                                     clk_base, 0, &pll_e_params, NULL);
+       clk_register_clkdev(clk, "pll_e", NULL);
+       clks[TEGRA124_CLK_PLL_E] = clk;
+
+       /* PLLC4 */
+       clk = tegra_clk_register_pllss("pll_c4", "pll_ref", clk_base, 0,
+                                       &pll_c4_params, NULL);
+       clk_register_clkdev(clk, "pll_c4", NULL);
+       clks[TEGRA124_CLK_PLL_C4] = clk;
+
+       /* PLLDP */
+       clk = tegra_clk_register_pllss("pll_dp", "pll_ref", clk_base, 0,
+                                       &pll_dp_params, NULL);
+       clk_register_clkdev(clk, "pll_dp", NULL);
+       clks[TEGRA124_CLK_PLL_DP] = clk;
+
+       /* PLLD2 */
+       clk = tegra_clk_register_pllss("pll_d2", "pll_ref", clk_base, 0,
+                                       &tegra124_pll_d2_params, NULL);
+       clk_register_clkdev(clk, "pll_d2", NULL);
+       clks[TEGRA124_CLK_PLL_D2] = clk;
+
+       /* PLLD2_OUT0 ?? */
+       clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "pll_d2_out0", NULL);
+       clks[TEGRA124_CLK_PLL_D2_OUT0] = clk;
+
+}
+
+/* Tegra124 CPU clock and reset control functions */
+static void tegra124_wait_cpu_in_reset(u32 cpu)
+{
+       unsigned int reg;
+
+       do {
+               reg = readl(clk_base + CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+               cpu_relax();
+       } while (!(reg & (1 << cpu)));  /* check CPU been reset or not */
+}
+
+static void tegra124_disable_cpu_clock(u32 cpu)
+{
+       /* flow controller would take care in the power sequence. */
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void tegra124_cpu_clock_suspend(void)
+{
+       /* switch coresite to clk_m, save off original source */
+       tegra124_cpu_clk_sctx.clk_csite_src =
+                               readl(clk_base + CLK_SOURCE_CSITE);
+       writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+}
+
+static void tegra124_cpu_clock_resume(void)
+{
+       writel(tegra124_cpu_clk_sctx.clk_csite_src,
+                               clk_base + CLK_SOURCE_CSITE);
+}
+#endif
+
+static struct tegra_cpu_car_ops tegra124_cpu_car_ops = {
+       .wait_for_reset = tegra124_wait_cpu_in_reset,
+       .disable_clock  = tegra124_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+       .suspend        = tegra124_cpu_clock_suspend,
+       .resume         = tegra124_cpu_clock_resume,
+#endif
+};
+
+static const struct of_device_id pmc_match[] __initconst = {
+       { .compatible = "nvidia,tegra124-pmc" },
+       {},
+};
+
+static struct tegra_clk_init_table init_table[] __initdata = {
+       {TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0},
+       {TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0},
+       {TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0},
+       {TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0},
+       {TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1},
+       {TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1},
+       {TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1},
+       {TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1},
+       {TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1},
+       {TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0},
+       {TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1},
+       {TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1},
+       {TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1},
+       {TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1},
+       {TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0},
+       {TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0},
+       {TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1},
+       {TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0},
+       {TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0},
+       /* This MUST be the last entry. */
+       {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+};
+
+static void __init tegra124_clock_apply_init_table(void)
+{
+       tegra_init_from_table(init_table, clks, TEGRA124_CLK_CLK_MAX);
+}
+
+static void __init tegra124_clock_init(struct device_node *np)
+{
+       struct device_node *node;
+
+       clk_base = of_iomap(np, 0);
+       if (!clk_base) {
+               pr_err("ioremap tegra124 CAR failed\n");
+               return;
+       }
+
+       node = of_find_matching_node(NULL, pmc_match);
+       if (!node) {
+               pr_err("Failed to find pmc node\n");
+               WARN_ON(1);
+               return;
+       }
+
+       pmc_base = of_iomap(node, 0);
+       if (!pmc_base) {
+               pr_err("Can't map pmc registers\n");
+               WARN_ON(1);
+               return;
+       }
+
+       clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX, 6);
+       if (!clks)
+               return;
+
+       if (tegra_osc_clk_init(clk_base, tegra124_clks, tegra124_input_freq,
+               ARRAY_SIZE(tegra124_input_freq), &osc_freq, &pll_ref_freq) < 0)
+               return;
+
+       tegra_fixed_clk_init(tegra124_clks);
+       tegra124_pll_init(clk_base, pmc_base);
+       tegra124_periph_clk_init(clk_base, pmc_base);
+       tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params);
+       tegra_pmc_clk_init(pmc_base, tegra124_clks);
+
+       tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
+                                       &pll_x_params);
+       tegra_add_of_provider(np);
+       tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
+
+       tegra_clk_apply_init_table = tegra124_clock_apply_init_table;
+
+       tegra_cpu_car_ops = &tegra124_cpu_car_ops;
+}
+CLK_OF_DECLARE(tegra124, "nvidia,tegra124-car", tegra124_clock_init);
index 056f649d0d8908b7f6de919a3ca7fc95c3d4e089..dbace152b2faa9e4f1699b8369d935683900df89 100644 (file)
 #include <linux/of_address.h>
 #include <linux/clk/tegra.h>
 #include <linux/delay.h>
+#include <dt-bindings/clock/tegra20-car.h>
 
 #include "clk.h"
-
-#define RST_DEVICES_L 0x004
-#define RST_DEVICES_H 0x008
-#define RST_DEVICES_U 0x00c
-#define RST_DEVICES_SET_L 0x300
-#define RST_DEVICES_CLR_L 0x304
-#define RST_DEVICES_SET_H 0x308
-#define RST_DEVICES_CLR_H 0x30c
-#define RST_DEVICES_SET_U 0x310
-#define RST_DEVICES_CLR_U 0x314
-#define RST_DEVICES_NUM 3
-
-#define CLK_OUT_ENB_L 0x010
-#define CLK_OUT_ENB_H 0x014
-#define CLK_OUT_ENB_U 0x018
-#define CLK_OUT_ENB_SET_L 0x320
-#define CLK_OUT_ENB_CLR_L 0x324
-#define CLK_OUT_ENB_SET_H 0x328
-#define CLK_OUT_ENB_CLR_H 0x32c
-#define CLK_OUT_ENB_SET_U 0x330
-#define CLK_OUT_ENB_CLR_U 0x334
-#define CLK_OUT_ENB_NUM 3
+#include "clk-id.h"
 
 #define OSC_CTRL 0x50
 #define OSC_CTRL_OSC_FREQ_MASK (3<<30)
@@ -67,6 +47,8 @@
 #define OSC_FREQ_DET_BUSY (1<<31)
 #define OSC_FREQ_DET_CNT_MASK 0xFFFF
 
+#define TEGRA20_CLK_PERIPH_BANKS       3
+
 #define PLLS_BASE 0xf0
 #define PLLS_MISC 0xf4
 #define PLLC_BASE 0x80
 
 #define CLK_SOURCE_I2S1 0x100
 #define CLK_SOURCE_I2S2 0x104
-#define CLK_SOURCE_SPDIF_OUT 0x108
-#define CLK_SOURCE_SPDIF_IN 0x10c
 #define CLK_SOURCE_PWM 0x110
 #define CLK_SOURCE_SPI 0x114
-#define CLK_SOURCE_SBC1 0x134
-#define CLK_SOURCE_SBC2 0x118
-#define CLK_SOURCE_SBC3 0x11c
-#define CLK_SOURCE_SBC4 0x1b4
 #define CLK_SOURCE_XIO 0x120
 #define CLK_SOURCE_TWC 0x12c
 #define CLK_SOURCE_IDE 0x144
-#define CLK_SOURCE_NDFLASH 0x160
-#define CLK_SOURCE_VFIR 0x168
-#define CLK_SOURCE_SDMMC1 0x150
-#define CLK_SOURCE_SDMMC2 0x154
-#define CLK_SOURCE_SDMMC3 0x1bc
-#define CLK_SOURCE_SDMMC4 0x164
-#define CLK_SOURCE_CVE 0x140
-#define CLK_SOURCE_TVO 0x188
-#define CLK_SOURCE_TVDAC 0x194
 #define CLK_SOURCE_HDMI 0x18c
 #define CLK_SOURCE_DISP1 0x138
 #define CLK_SOURCE_DISP2 0x13c
 #define CLK_SOURCE_CSITE 0x1d4
-#define CLK_SOURCE_LA 0x1f8
-#define CLK_SOURCE_OWR 0x1cc
-#define CLK_SOURCE_NOR 0x1d0
-#define CLK_SOURCE_MIPI 0x174
 #define CLK_SOURCE_I2C1 0x124
 #define CLK_SOURCE_I2C2 0x198
 #define CLK_SOURCE_I2C3 0x1b8
 #define CLK_SOURCE_UARTC 0x1a0
 #define CLK_SOURCE_UARTD 0x1c0
 #define CLK_SOURCE_UARTE 0x1c4
-#define CLK_SOURCE_3D 0x158
-#define CLK_SOURCE_2D 0x15c
-#define CLK_SOURCE_MPE 0x170
-#define CLK_SOURCE_EPP 0x16c
-#define CLK_SOURCE_HOST1X 0x180
-#define CLK_SOURCE_VDE 0x1c8
-#define CLK_SOURCE_VI 0x148
-#define CLK_SOURCE_VI_SENSOR 0x1a8
 #define CLK_SOURCE_EMC 0x19c
 
 #define AUDIO_SYNC_CLK 0x38
 
-#define PMC_CTRL 0x0
-#define PMC_CTRL_BLINK_ENB 7
-#define PMC_DPD_PADS_ORIDE 0x1c
-#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
-#define PMC_BLINK_TIMER 0x40
-
 /* Tegra CPU clock and reset control regs */
 #define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX         0x4c
 #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET     0x340
@@ -188,64 +137,32 @@ static struct cpu_clk_suspend_context {
 } tegra20_cpu_clk_sctx;
 #endif
 
-static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
-
 static void __iomem *clk_base;
 static void __iomem *pmc_base;
 
-static DEFINE_SPINLOCK(pll_div_lock);
-static DEFINE_SPINLOCK(sysrate_lock);
-
-#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
+#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset,  \
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
                        30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,      \
-                       _regs, _clk_num, periph_clk_enb_refcnt,         \
+                       _clk_num, \
                        _gate_flags, _clk_id)
 
-#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,    \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id)
-
-#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \
-                             _clk_num, _regs, _gate_flags, _clk_id)    \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+#define TEGRA_INIT_DATA_DIV16(_name, _parents, _offset, \
+                             _clk_num, _gate_flags, _clk_id)   \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \
+                       _clk_num, _gate_flags,  \
                        _clk_id)
 
-#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
-                             _mux_shift, _mux_width, _clk_num, _regs,  \
+#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \
+                             _mux_shift, _mux_width, _clk_num, \
                              _gate_flags, _clk_id)                     \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs,   \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       _mux_shift, _mux_width, 0, 0, 0, 0, 0, \
+                       _clk_num, _gate_flags,  \
                        _clk_id)
 
-/* IDs assigned here must be in sync with DT bindings definition
- * for Tegra20 clocks .
- */
-enum tegra20_clk {
-       cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1,
-       ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp,
-       gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma,
-       kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3,
-       dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
-       usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
-       pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb,
-       iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev2, cdev1,
-       uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve,
-       osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0,
-       pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1,
-       pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_s, pll_u,
-       pll_x, cop, audio, pll_ref, twd, clk_max,
-};
-
-static struct clk *clks[clk_max];
-static struct clk_onecell_data clk_data;
+static struct clk **clks;
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
        { 12000000, 600000000, 600, 12, 0, 8 },
@@ -383,6 +300,8 @@ static struct tegra_clk_pll_params pll_c_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_c_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON,
 };
 
 static struct tegra_clk_pll_params pll_m_params = {
@@ -397,6 +316,8 @@ static struct tegra_clk_pll_params pll_m_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_m_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON,
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -411,6 +332,9 @@ static struct tegra_clk_pll_params pll_p_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_p_freq_table,
+       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON,
+       .fixed_rate =  216000000,
 };
 
 static struct tegra_clk_pll_params pll_a_params = {
@@ -425,6 +349,8 @@ static struct tegra_clk_pll_params pll_a_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_a_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON,
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -439,6 +365,8 @@ static struct tegra_clk_pll_params pll_d_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON,
 };
 
 static struct pdiv_map pllu_p[] = {
@@ -460,6 +388,8 @@ static struct tegra_clk_pll_params pll_u_params = {
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .pdiv_tohw = pllu_p,
+       .freq_table = pll_u_freq_table,
+       .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -474,6 +404,8 @@ static struct tegra_clk_pll_params pll_x_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_x_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON,
 };
 
 static struct tegra_clk_pll_params pll_e_params = {
@@ -488,34 +420,160 @@ static struct tegra_clk_pll_params pll_e_params = {
        .lock_mask = PLLE_MISC_LOCK,
        .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
        .lock_delay = 0,
+       .freq_table = pll_e_freq_table,
+       .flags = TEGRA_PLL_FIXED,
+       .fixed_rate = 100000000,
 };
 
-/* Peripheral clock registers */
-static struct tegra_clk_periph_regs periph_l_regs = {
-       .enb_reg = CLK_OUT_ENB_L,
-       .enb_set_reg = CLK_OUT_ENB_SET_L,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_L,
-       .rst_reg = RST_DEVICES_L,
-       .rst_set_reg = RST_DEVICES_SET_L,
-       .rst_clr_reg = RST_DEVICES_CLR_L,
-};
-
-static struct tegra_clk_periph_regs periph_h_regs = {
-       .enb_reg = CLK_OUT_ENB_H,
-       .enb_set_reg = CLK_OUT_ENB_SET_H,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_H,
-       .rst_reg = RST_DEVICES_H,
-       .rst_set_reg = RST_DEVICES_SET_H,
-       .rst_clr_reg = RST_DEVICES_CLR_H,
+static struct tegra_devclk devclks[] __initdata = {
+       { .con_id = "pll_c", .dt_id = TEGRA20_CLK_PLL_C },
+       { .con_id = "pll_c_out1", .dt_id = TEGRA20_CLK_PLL_C_OUT1 },
+       { .con_id = "pll_p", .dt_id = TEGRA20_CLK_PLL_P },
+       { .con_id = "pll_p_out1", .dt_id = TEGRA20_CLK_PLL_P_OUT1 },
+       { .con_id = "pll_p_out2", .dt_id = TEGRA20_CLK_PLL_P_OUT2 },
+       { .con_id = "pll_p_out3", .dt_id = TEGRA20_CLK_PLL_P_OUT3 },
+       { .con_id = "pll_p_out4", .dt_id = TEGRA20_CLK_PLL_P_OUT4 },
+       { .con_id = "pll_m", .dt_id = TEGRA20_CLK_PLL_M },
+       { .con_id = "pll_m_out1", .dt_id = TEGRA20_CLK_PLL_M_OUT1 },
+       { .con_id = "pll_x", .dt_id = TEGRA20_CLK_PLL_X },
+       { .con_id = "pll_u", .dt_id = TEGRA20_CLK_PLL_U },
+       { .con_id = "pll_d", .dt_id = TEGRA20_CLK_PLL_D },
+       { .con_id = "pll_d_out0", .dt_id = TEGRA20_CLK_PLL_D_OUT0 },
+       { .con_id = "pll_a", .dt_id = TEGRA20_CLK_PLL_A },
+       { .con_id = "pll_a_out0", .dt_id = TEGRA20_CLK_PLL_A_OUT0 },
+       { .con_id = "pll_e", .dt_id = TEGRA20_CLK_PLL_E },
+       { .con_id = "cclk", .dt_id = TEGRA20_CLK_CCLK },
+       { .con_id = "sclk", .dt_id = TEGRA20_CLK_SCLK },
+       { .con_id = "hclk", .dt_id = TEGRA20_CLK_HCLK },
+       { .con_id = "pclk", .dt_id = TEGRA20_CLK_PCLK },
+       { .con_id = "fuse", .dt_id = TEGRA20_CLK_FUSE },
+       { .con_id = "twd", .dt_id = TEGRA20_CLK_TWD },
+       { .con_id = "audio", .dt_id = TEGRA20_CLK_AUDIO },
+       { .con_id = "audio_2x", .dt_id = TEGRA20_CLK_AUDIO_2X },
+       { .dev_id = "tegra20-ac97", .dt_id = TEGRA20_CLK_AC97 },
+       { .dev_id = "tegra-apbdma", .dt_id = TEGRA20_CLK_APBDMA },
+       { .dev_id = "rtc-tegra", .dt_id = TEGRA20_CLK_RTC },
+       { .dev_id = "timer", .dt_id = TEGRA20_CLK_TIMER },
+       { .dev_id = "tegra-kbc", .dt_id = TEGRA20_CLK_KBC },
+       { .con_id = "csus", .dev_id =  "tegra_camera", .dt_id = TEGRA20_CLK_CSUS },
+       { .con_id = "vcp", .dev_id = "tegra-avp", .dt_id = TEGRA20_CLK_VCP },
+       { .con_id = "bsea", .dev_id = "tegra-avp", .dt_id = TEGRA20_CLK_BSEA },
+       { .con_id = "bsev", .dev_id = "tegra-aes", .dt_id = TEGRA20_CLK_BSEV },
+       { .con_id = "emc", .dt_id = TEGRA20_CLK_EMC },
+       { .dev_id = "fsl-tegra-udc", .dt_id = TEGRA20_CLK_USBD },
+       { .dev_id = "tegra-ehci.1", .dt_id = TEGRA20_CLK_USB2 },
+       { .dev_id = "tegra-ehci.2", .dt_id = TEGRA20_CLK_USB3 },
+       { .dev_id = "dsi", .dt_id = TEGRA20_CLK_DSI },
+       { .con_id = "csi", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_CSI },
+       { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_ISP },
+       { .con_id = "pex", .dt_id = TEGRA20_CLK_PEX },
+       { .con_id = "afi", .dt_id = TEGRA20_CLK_AFI },
+       { .con_id = "cdev1", .dt_id = TEGRA20_CLK_CDEV1 },
+       { .con_id = "cdev2", .dt_id = TEGRA20_CLK_CDEV2 },
+       { .con_id = "clk_32k", .dt_id = TEGRA20_CLK_CLK_32K },
+       { .con_id = "blink", .dt_id = TEGRA20_CLK_BLINK },
+       { .con_id = "clk_m", .dt_id = TEGRA20_CLK_CLK_M },
+       { .con_id = "pll_ref", .dt_id = TEGRA20_CLK_PLL_REF },
+       { .dev_id = "tegra20-i2s.0", .dt_id = TEGRA20_CLK_I2S1 },
+       { .dev_id = "tegra20-i2s.1", .dt_id = TEGRA20_CLK_I2S2 },
+       { .con_id = "spdif_out", .dev_id = "tegra20-spdif", .dt_id = TEGRA20_CLK_SPDIF_OUT },
+       { .con_id = "spdif_in", .dev_id = "tegra20-spdif", .dt_id = TEGRA20_CLK_SPDIF_IN },
+       { .dev_id = "spi_tegra.0", .dt_id = TEGRA20_CLK_SBC1 },
+       { .dev_id = "spi_tegra.1", .dt_id = TEGRA20_CLK_SBC2 },
+       { .dev_id = "spi_tegra.2", .dt_id = TEGRA20_CLK_SBC3 },
+       { .dev_id = "spi_tegra.3", .dt_id = TEGRA20_CLK_SBC4 },
+       { .dev_id = "spi", .dt_id = TEGRA20_CLK_SPI },
+       { .dev_id = "xio", .dt_id = TEGRA20_CLK_XIO },
+       { .dev_id = "twc", .dt_id = TEGRA20_CLK_TWC },
+       { .dev_id = "ide", .dt_id = TEGRA20_CLK_IDE },
+       { .dev_id = "tegra_nand", .dt_id = TEGRA20_CLK_NDFLASH },
+       { .dev_id = "vfir", .dt_id = TEGRA20_CLK_VFIR },
+       { .dev_id = "csite", .dt_id = TEGRA20_CLK_CSITE },
+       { .dev_id = "la", .dt_id = TEGRA20_CLK_LA },
+       { .dev_id = "tegra_w1", .dt_id = TEGRA20_CLK_OWR },
+       { .dev_id = "mipi", .dt_id = TEGRA20_CLK_MIPI },
+       { .dev_id = "vde", .dt_id = TEGRA20_CLK_VDE },
+       { .con_id = "vi", .dev_id =  "tegra_camera", .dt_id = TEGRA20_CLK_VI },
+       { .dev_id = "epp", .dt_id = TEGRA20_CLK_EPP },
+       { .dev_id = "mpe", .dt_id = TEGRA20_CLK_MPE },
+       { .dev_id = "host1x", .dt_id = TEGRA20_CLK_HOST1X },
+       { .dev_id = "3d", .dt_id = TEGRA20_CLK_GR3D },
+       { .dev_id = "2d", .dt_id = TEGRA20_CLK_GR2D },
+       { .dev_id = "tegra-nor", .dt_id = TEGRA20_CLK_NOR },
+       { .dev_id = "sdhci-tegra.0", .dt_id = TEGRA20_CLK_SDMMC1 },
+       { .dev_id = "sdhci-tegra.1", .dt_id = TEGRA20_CLK_SDMMC2 },
+       { .dev_id = "sdhci-tegra.2", .dt_id = TEGRA20_CLK_SDMMC3 },
+       { .dev_id = "sdhci-tegra.3", .dt_id = TEGRA20_CLK_SDMMC4 },
+       { .dev_id = "cve", .dt_id = TEGRA20_CLK_CVE },
+       { .dev_id = "tvo", .dt_id = TEGRA20_CLK_TVO },
+       { .dev_id = "tvdac", .dt_id = TEGRA20_CLK_TVDAC },
+       { .con_id = "vi_sensor", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_VI_SENSOR },
+       { .dev_id = "hdmi", .dt_id = TEGRA20_CLK_HDMI },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.0", .dt_id = TEGRA20_CLK_I2C1 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.1", .dt_id = TEGRA20_CLK_I2C2 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.2", .dt_id = TEGRA20_CLK_I2C3 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.3", .dt_id = TEGRA20_CLK_DVC },
+       { .dev_id = "tegra-pwm", .dt_id = TEGRA20_CLK_PWM },
+       { .dev_id = "tegra_uart.0", .dt_id = TEGRA20_CLK_UARTA },
+       { .dev_id = "tegra_uart.1", .dt_id = TEGRA20_CLK_UARTB },
+       { .dev_id = "tegra_uart.2", .dt_id = TEGRA20_CLK_UARTC },
+       { .dev_id = "tegra_uart.3", .dt_id = TEGRA20_CLK_UARTD },
+       { .dev_id = "tegra_uart.4", .dt_id = TEGRA20_CLK_UARTE },
+       { .dev_id = "tegradc.0", .dt_id = TEGRA20_CLK_DISP1 },
+       { .dev_id = "tegradc.1", .dt_id = TEGRA20_CLK_DISP2 },
 };
 
-static struct tegra_clk_periph_regs periph_u_regs = {
-       .enb_reg = CLK_OUT_ENB_U,
-       .enb_set_reg = CLK_OUT_ENB_SET_U,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_U,
-       .rst_reg = RST_DEVICES_U,
-       .rst_set_reg = RST_DEVICES_SET_U,
-       .rst_clr_reg = RST_DEVICES_CLR_U,
+static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
+       [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true },
+       [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true },
+       [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc2] = { .dt_id = TEGRA20_CLK_SDMMC2, .present = true },
+       [tegra_clk_sdmmc3] = { .dt_id = TEGRA20_CLK_SDMMC3, .present = true },
+       [tegra_clk_sdmmc4] = { .dt_id = TEGRA20_CLK_SDMMC4, .present = true },
+       [tegra_clk_la] = { .dt_id = TEGRA20_CLK_LA, .present = true },
+       [tegra_clk_csite] = { .dt_id = TEGRA20_CLK_CSITE, .present = true },
+       [tegra_clk_vfir] = { .dt_id = TEGRA20_CLK_VFIR, .present = true },
+       [tegra_clk_mipi] = { .dt_id = TEGRA20_CLK_MIPI, .present = true },
+       [tegra_clk_nor] = { .dt_id = TEGRA20_CLK_NOR, .present = true },
+       [tegra_clk_rtc] = { .dt_id = TEGRA20_CLK_RTC, .present = true },
+       [tegra_clk_timer] = { .dt_id = TEGRA20_CLK_TIMER, .present = true },
+       [tegra_clk_kbc] = { .dt_id = TEGRA20_CLK_KBC, .present = true },
+       [tegra_clk_csus] = { .dt_id = TEGRA20_CLK_CSUS, .present = true },
+       [tegra_clk_vcp] = { .dt_id = TEGRA20_CLK_VCP, .present = true },
+       [tegra_clk_bsea] = { .dt_id = TEGRA20_CLK_BSEA, .present = true },
+       [tegra_clk_bsev] = { .dt_id = TEGRA20_CLK_BSEV, .present = true },
+       [tegra_clk_usbd] = { .dt_id = TEGRA20_CLK_USBD, .present = true },
+       [tegra_clk_usb2] = { .dt_id = TEGRA20_CLK_USB2, .present = true },
+       [tegra_clk_usb3] = { .dt_id = TEGRA20_CLK_USB3, .present = true },
+       [tegra_clk_csi] = { .dt_id = TEGRA20_CLK_CSI, .present = true },
+       [tegra_clk_isp] = { .dt_id = TEGRA20_CLK_ISP, .present = true },
+       [tegra_clk_clk_32k] = { .dt_id = TEGRA20_CLK_CLK_32K, .present = true },
+       [tegra_clk_blink] = { .dt_id = TEGRA20_CLK_BLINK, .present = true },
+       [tegra_clk_hclk] = { .dt_id = TEGRA20_CLK_HCLK, .present = true },
+       [tegra_clk_pclk] = { .dt_id = TEGRA20_CLK_PCLK, .present = true },
+       [tegra_clk_pll_p_out1] = { .dt_id = TEGRA20_CLK_PLL_P_OUT1, .present = true },
+       [tegra_clk_pll_p_out2] = { .dt_id = TEGRA20_CLK_PLL_P_OUT2, .present = true },
+       [tegra_clk_pll_p_out3] = { .dt_id = TEGRA20_CLK_PLL_P_OUT3, .present = true },
+       [tegra_clk_pll_p_out4] = { .dt_id = TEGRA20_CLK_PLL_P_OUT4, .present = true },
+       [tegra_clk_pll_p] = { .dt_id = TEGRA20_CLK_PLL_P, .present = true },
+       [tegra_clk_owr] = { .dt_id = TEGRA20_CLK_OWR, .present = true },
+       [tegra_clk_sbc1] = { .dt_id = TEGRA20_CLK_SBC1, .present = true },
+       [tegra_clk_sbc2] = { .dt_id = TEGRA20_CLK_SBC2, .present = true },
+       [tegra_clk_sbc3] = { .dt_id = TEGRA20_CLK_SBC3, .present = true },
+       [tegra_clk_sbc4] = { .dt_id = TEGRA20_CLK_SBC4, .present = true },
+       [tegra_clk_vde] = { .dt_id = TEGRA20_CLK_VDE, .present = true },
+       [tegra_clk_vi] = { .dt_id = TEGRA20_CLK_VI, .present = true },
+       [tegra_clk_epp] = { .dt_id = TEGRA20_CLK_EPP, .present = true },
+       [tegra_clk_mpe] = { .dt_id = TEGRA20_CLK_MPE, .present = true },
+       [tegra_clk_host1x] = { .dt_id = TEGRA20_CLK_HOST1X, .present = true },
+       [tegra_clk_gr2d] = { .dt_id = TEGRA20_CLK_GR2D, .present = true },
+       [tegra_clk_gr3d] = { .dt_id = TEGRA20_CLK_GR3D, .present = true },
+       [tegra_clk_ndflash] = { .dt_id = TEGRA20_CLK_NDFLASH, .present = true },
+       [tegra_clk_cve] = { .dt_id = TEGRA20_CLK_CVE, .present = true },
+       [tegra_clk_tvo] = { .dt_id = TEGRA20_CLK_TVO, .present = true },
+       [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true },
+       [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true },
+       [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
@@ -577,10 +635,8 @@ static void tegra20_pll_init(void)
 
        /* PLLC */
        clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0,
-                           0, &pll_c_params, TEGRA_PLL_HAS_CPCON,
-                           pll_c_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_c", NULL);
-       clks[pll_c] = clk;
+                           &pll_c_params, NULL);
+       clks[TEGRA20_CLK_PLL_C] = clk;
 
        /* PLLC_OUT1 */
        clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
@@ -589,71 +645,13 @@ static void tegra20_pll_init(void)
        clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
                                clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT,
                                0, NULL);
-       clk_register_clkdev(clk, "pll_c_out1", NULL);
-       clks[pll_c_out1] = clk;
-
-       /* PLLP */
-       clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0,
-                           216000000, &pll_p_params, TEGRA_PLL_FIXED |
-                           TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_p", NULL);
-       clks[pll_p] = clk;
-
-       /* PLLP_OUT1 */
-       clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0,
-                               TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
-                               clk_base + PLLP_OUTA, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out1", NULL);
-       clks[pll_p_out1] = clk;
-
-       /* PLLP_OUT2 */
-       clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0,
-                               TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
-                               24, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
-                               clk_base + PLLP_OUTA, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out2", NULL);
-       clks[pll_p_out2] = clk;
-
-       /* PLLP_OUT3 */
-       clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0,
-                               TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
-                               clk_base + PLLP_OUTB, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out3", NULL);
-       clks[pll_p_out3] = clk;
-
-       /* PLLP_OUT4 */
-       clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0,
-                               TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
-                               24, 8, 1, &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
-                               clk_base + PLLP_OUTB, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out4", NULL);
-       clks[pll_p_out4] = clk;
+       clks[TEGRA20_CLK_PLL_C_OUT1] = clk;
 
        /* PLLM */
        clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL,
-                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
-                           &pll_m_params, TEGRA_PLL_HAS_CPCON,
-                           pll_m_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_m", NULL);
-       clks[pll_m] = clk;
+                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+                           &pll_m_params, NULL);
+       clks[TEGRA20_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
        clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
@@ -662,42 +660,32 @@ static void tegra20_pll_init(void)
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
                                clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
                                CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_m_out1", NULL);
-       clks[pll_m_out1] = clk;
+       clks[TEGRA20_CLK_PLL_M_OUT1] = clk;
 
        /* PLLX */
        clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0,
-                           0, &pll_x_params, TEGRA_PLL_HAS_CPCON,
-                           pll_x_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_x", NULL);
-       clks[pll_x] = clk;
+                           &pll_x_params, NULL);
+       clks[TEGRA20_CLK_PLL_X] = clk;
 
        /* PLLU */
        clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0,
-                           0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON,
-                           pll_u_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_u", NULL);
-       clks[pll_u] = clk;
+                           &pll_u_params, NULL);
+       clks[TEGRA20_CLK_PLL_U] = clk;
 
        /* PLLD */
        clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0,
-                           0, &pll_d_params, TEGRA_PLL_HAS_CPCON,
-                           pll_d_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_d", NULL);
-       clks[pll_d] = clk;
+                           &pll_d_params, NULL);
+       clks[TEGRA20_CLK_PLL_D] = clk;
 
        /* PLLD_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_d_out0", NULL);
-       clks[pll_d_out0] = clk;
+       clks[TEGRA20_CLK_PLL_D_OUT0] = clk;
 
        /* PLLA */
        clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0,
-                           0, &pll_a_params, TEGRA_PLL_HAS_CPCON,
-                           pll_a_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_a", NULL);
-       clks[pll_a] = clk;
+                           &pll_a_params, NULL);
+       clks[TEGRA20_CLK_PLL_A] = clk;
 
        /* PLLA_OUT0 */
        clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
@@ -706,15 +694,12 @@ static void tegra20_pll_init(void)
        clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
                                clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
                                CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_a_out0", NULL);
-       clks[pll_a_out0] = clk;
+       clks[TEGRA20_CLK_PLL_A_OUT0] = clk;
 
        /* PLLE */
        clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base,
-                            0, 100000000, &pll_e_params,
-                            0, pll_e_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_e", NULL);
-       clks[pll_e] = clk;
+                            0, &pll_e_params, NULL);
+       clks[TEGRA20_CLK_PLL_E] = clk;
 }
 
 static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
@@ -732,40 +717,17 @@ static void tegra20_super_clk_init(void)
        clk = tegra_clk_register_super_mux("cclk", cclk_parents,
                              ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
                              clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "cclk", NULL);
-       clks[cclk] = clk;
+       clks[TEGRA20_CLK_CCLK] = clk;
 
        /* SCLK */
        clk = tegra_clk_register_super_mux("sclk", sclk_parents,
                              ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT,
                              clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "sclk", NULL);
-       clks[sclk] = clk;
-
-       /* HCLK */
-       clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
-                                  clk_base + CLK_SYSTEM_RATE, 4, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT,
-                               clk_base + CLK_SYSTEM_RATE, 7,
-                               CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "hclk", NULL);
-       clks[hclk] = clk;
-
-       /* PCLK */
-       clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
-                                  clk_base + CLK_SYSTEM_RATE, 0, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT,
-                               clk_base + CLK_SYSTEM_RATE, 3,
-                               CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "pclk", NULL);
-       clks[pclk] = clk;
+       clks[TEGRA20_CLK_SCLK] = clk;
 
        /* twd */
        clk = clk_register_fixed_factor(NULL, "twd", "cclk", 0, 1, 4);
-       clk_register_clkdev(clk, "twd", NULL);
-       clks[twd] = clk;
+       clks[TEGRA20_CLK_TWD] = clk;
 }
 
 static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused",
@@ -784,18 +746,16 @@ static void __init tegra20_audio_clk_init(void)
        clk = clk_register_gate(NULL, "audio", "audio_mux", 0,
                                clk_base + AUDIO_SYNC_CLK, 4,
                                CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio", NULL);
-       clks[audio] = clk;
+       clks[TEGRA20_CLK_AUDIO] = clk;
 
        /* audio_2x */
        clk = clk_register_fixed_factor(NULL, "audio_doubler", "audio",
                                        CLK_SET_RATE_PARENT, 2, 1);
        clk = tegra_clk_register_periph_gate("audio_2x", "audio_doubler",
                                    TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 89, &periph_u_regs,
+                                   CLK_SET_RATE_PARENT, 89,
                                    periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio_2x", NULL);
-       clks[audio_2x] = clk;
+       clks[TEGRA20_CLK_AUDIO_2X] = clk;
 
 }
 
@@ -803,68 +763,36 @@ static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
                                     "clk_m"};
 static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
                                     "clk_m"};
-static const char *spdif_out_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
-                                         "clk_m"};
-static const char *spdif_in_parents[] = {"pll_p", "pll_c", "pll_m"};
 static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m",
                                    "clk_32k"};
 static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"};
-static const char *mux_pllmcpa[] = {"pll_m", "pll_c", "pll_c", "pll_a"};
 static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c",
                                        "clk_m"};
 static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"};
 
 static struct tegra_periph_init_data tegra_periph_clk_list[] = {
-       TEGRA_INIT_DATA_MUX("i2s1",     NULL,           "tegra20-i2s.0", i2s1_parents,      CLK_SOURCE_I2S1,      11,   &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
-       TEGRA_INIT_DATA_MUX("i2s2",     NULL,           "tegra20-i2s.1", i2s2_parents,      CLK_SOURCE_I2S2,      18,   &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
-       TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out",   "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10,   &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
-       TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in",     "tegra20-spdif", spdif_in_parents,  CLK_SOURCE_SPDIF_IN,  10,   &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
-       TEGRA_INIT_DATA_MUX("sbc1",     NULL,           "spi_tegra.0",   mux_pllpcm_clkm,   CLK_SOURCE_SBC1,      41,   &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
-       TEGRA_INIT_DATA_MUX("sbc2",     NULL,           "spi_tegra.1",   mux_pllpcm_clkm,   CLK_SOURCE_SBC2,      44,   &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
-       TEGRA_INIT_DATA_MUX("sbc3",     NULL,           "spi_tegra.2",   mux_pllpcm_clkm,   CLK_SOURCE_SBC3,      46,   &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
-       TEGRA_INIT_DATA_MUX("sbc4",     NULL,           "spi_tegra.3",   mux_pllpcm_clkm,   CLK_SOURCE_SBC4,      68,   &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
-       TEGRA_INIT_DATA_MUX("spi",      NULL,           "spi",           mux_pllpcm_clkm,   CLK_SOURCE_SPI,       43,   &periph_h_regs, TEGRA_PERIPH_ON_APB, spi),
-       TEGRA_INIT_DATA_MUX("xio",      NULL,           "xio",           mux_pllpcm_clkm,   CLK_SOURCE_XIO,       45,   &periph_h_regs, 0, xio),
-       TEGRA_INIT_DATA_MUX("twc",      NULL,           "twc",           mux_pllpcm_clkm,   CLK_SOURCE_TWC,       16,   &periph_l_regs, TEGRA_PERIPH_ON_APB, twc),
-       TEGRA_INIT_DATA_MUX("ide",      NULL,           "ide",           mux_pllpcm_clkm,   CLK_SOURCE_XIO,       25,   &periph_l_regs, 0, ide),
-       TEGRA_INIT_DATA_MUX("ndflash",  NULL,           "tegra_nand",    mux_pllpcm_clkm,   CLK_SOURCE_NDFLASH,   13,   &periph_l_regs, 0, ndflash),
-       TEGRA_INIT_DATA_MUX("vfir",     NULL,           "vfir",          mux_pllpcm_clkm,   CLK_SOURCE_VFIR,      7,    &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
-       TEGRA_INIT_DATA_MUX("csite",    NULL,           "csite",         mux_pllpcm_clkm,   CLK_SOURCE_CSITE,     73,   &periph_u_regs, 0, csite),
-       TEGRA_INIT_DATA_MUX("la",       NULL,           "la",            mux_pllpcm_clkm,   CLK_SOURCE_LA,        76,   &periph_u_regs, 0, la),
-       TEGRA_INIT_DATA_MUX("owr",      NULL,           "tegra_w1",      mux_pllpcm_clkm,   CLK_SOURCE_OWR,       71,   &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
-       TEGRA_INIT_DATA_MUX("mipi",     NULL,           "mipi",          mux_pllpcm_clkm,   CLK_SOURCE_MIPI,      50,   &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
-       TEGRA_INIT_DATA_MUX("vde",      NULL,           "vde",           mux_pllpcm_clkm,   CLK_SOURCE_VDE,       61,   &periph_h_regs, 0, vde),
-       TEGRA_INIT_DATA_MUX("vi",       "vi",           "tegra_camera",  mux_pllmcpa,       CLK_SOURCE_VI,        20,   &periph_l_regs, 0, vi),
-       TEGRA_INIT_DATA_MUX("epp",      NULL,           "epp",           mux_pllmcpa,       CLK_SOURCE_EPP,       19,   &periph_l_regs, 0, epp),
-       TEGRA_INIT_DATA_MUX("mpe",      NULL,           "mpe",           mux_pllmcpa,       CLK_SOURCE_MPE,       60,   &periph_h_regs, 0, mpe),
-       TEGRA_INIT_DATA_MUX("host1x",   NULL,           "host1x",        mux_pllmcpa,       CLK_SOURCE_HOST1X,    28,   &periph_l_regs, 0, host1x),
-       TEGRA_INIT_DATA_MUX("3d",       NULL,           "3d",            mux_pllmcpa,       CLK_SOURCE_3D,        24,   &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d),
-       TEGRA_INIT_DATA_MUX("2d",       NULL,           "2d",            mux_pllmcpa,       CLK_SOURCE_2D,        21,   &periph_l_regs, 0, gr2d),
-       TEGRA_INIT_DATA_MUX("nor",      NULL,           "tegra-nor",     mux_pllpcm_clkm,   CLK_SOURCE_NOR,       42,   &periph_h_regs, 0, nor),
-       TEGRA_INIT_DATA_MUX("sdmmc1",   NULL,           "sdhci-tegra.0", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC1,    14,   &periph_l_regs, 0, sdmmc1),
-       TEGRA_INIT_DATA_MUX("sdmmc2",   NULL,           "sdhci-tegra.1", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC2,    9,    &periph_l_regs, 0, sdmmc2),
-       TEGRA_INIT_DATA_MUX("sdmmc3",   NULL,           "sdhci-tegra.2", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC3,    69,   &periph_u_regs, 0, sdmmc3),
-       TEGRA_INIT_DATA_MUX("sdmmc4",   NULL,           "sdhci-tegra.3", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC4,    15,   &periph_l_regs, 0, sdmmc4),
-       TEGRA_INIT_DATA_MUX("cve",      NULL,           "cve",           mux_pllpdc_clkm,   CLK_SOURCE_CVE,       49,   &periph_h_regs, 0, cve),
-       TEGRA_INIT_DATA_MUX("tvo",      NULL,           "tvo",           mux_pllpdc_clkm,   CLK_SOURCE_TVO,       49,   &periph_h_regs, 0, tvo),
-       TEGRA_INIT_DATA_MUX("tvdac",    NULL,           "tvdac",         mux_pllpdc_clkm,   CLK_SOURCE_TVDAC,     53,   &periph_h_regs, 0, tvdac),
-       TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor",   "tegra_camera",  mux_pllmcpa,       CLK_SOURCE_VI_SENSOR, 20,   &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
-       TEGRA_INIT_DATA_DIV16("i2c1",   "div-clk",      "tegra-i2c.0",   mux_pllpcm_clkm,   CLK_SOURCE_I2C1,      12,   &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1),
-       TEGRA_INIT_DATA_DIV16("i2c2",   "div-clk",      "tegra-i2c.1",   mux_pllpcm_clkm,   CLK_SOURCE_I2C2,      54,   &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2),
-       TEGRA_INIT_DATA_DIV16("i2c3",   "div-clk",      "tegra-i2c.2",   mux_pllpcm_clkm,   CLK_SOURCE_I2C3,      67,   &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3),
-       TEGRA_INIT_DATA_DIV16("dvc",    "div-clk",      "tegra-i2c.3",   mux_pllpcm_clkm,   CLK_SOURCE_DVC,       47,   &periph_h_regs, TEGRA_PERIPH_ON_APB, dvc),
-       TEGRA_INIT_DATA_MUX("hdmi",     NULL,           "hdmi",          mux_pllpdc_clkm,   CLK_SOURCE_HDMI,      51,   &periph_h_regs, 0, hdmi),
-       TEGRA_INIT_DATA("pwm",          NULL,           "tegra-pwm",     pwm_parents,       CLK_SOURCE_PWM,       28, 3, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm),
+       TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents,     CLK_SOURCE_I2S1,   11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1),
+       TEGRA_INIT_DATA_MUX("i2s2", i2s2_parents,     CLK_SOURCE_I2S2,   18, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S2),
+       TEGRA_INIT_DATA_MUX("spi",   mux_pllpcm_clkm,   CLK_SOURCE_SPI,   43, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_SPI),
+       TEGRA_INIT_DATA_MUX("xio",   mux_pllpcm_clkm,   CLK_SOURCE_XIO,   45, 0, TEGRA20_CLK_XIO),
+       TEGRA_INIT_DATA_MUX("twc",   mux_pllpcm_clkm,   CLK_SOURCE_TWC,   16, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_TWC),
+       TEGRA_INIT_DATA_MUX("ide",   mux_pllpcm_clkm,   CLK_SOURCE_XIO,   25, 0, TEGRA20_CLK_IDE),
+       TEGRA_INIT_DATA_DIV16("dvc", mux_pllpcm_clkm,   CLK_SOURCE_DVC,   47, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_DVC),
+       TEGRA_INIT_DATA_DIV16("i2c1", mux_pllpcm_clkm,   CLK_SOURCE_I2C1,   12, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C1),
+       TEGRA_INIT_DATA_DIV16("i2c2", mux_pllpcm_clkm,   CLK_SOURCE_I2C2,   54, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C2),
+       TEGRA_INIT_DATA_DIV16("i2c3", mux_pllpcm_clkm,   CLK_SOURCE_I2C3,   67, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C3),
+       TEGRA_INIT_DATA_MUX("hdmi", mux_pllpdc_clkm,   CLK_SOURCE_HDMI,   51, 0, TEGRA20_CLK_HDMI),
+       TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents,     CLK_SOURCE_PWM,   28, 3, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_PWM),
 };
 
 static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
-       TEGRA_INIT_DATA_NODIV("uarta",  NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6,  &periph_l_regs, TEGRA_PERIPH_ON_APB, uarta),
-       TEGRA_INIT_DATA_NODIV("uartb",  NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7,  &periph_l_regs, TEGRA_PERIPH_ON_APB, uartb),
-       TEGRA_INIT_DATA_NODIV("uartc",  NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, &periph_h_regs, TEGRA_PERIPH_ON_APB, uartc),
-       TEGRA_INIT_DATA_NODIV("uartd",  NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, &periph_u_regs, TEGRA_PERIPH_ON_APB, uartd),
-       TEGRA_INIT_DATA_NODIV("uarte",  NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, &periph_u_regs, TEGRA_PERIPH_ON_APB, uarte),
-       TEGRA_INIT_DATA_NODIV("disp1",  NULL, "tegradc.0",    mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, &periph_l_regs, 0, disp1),
-       TEGRA_INIT_DATA_NODIV("disp2",  NULL, "tegradc.1",    mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, &periph_l_regs, 0, disp2),
+       TEGRA_INIT_DATA_NODIV("uarta",  mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6,   TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTA),
+       TEGRA_INIT_DATA_NODIV("uartb",  mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7,   TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTB),
+       TEGRA_INIT_DATA_NODIV("uartc",  mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55,  TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTC),
+       TEGRA_INIT_DATA_NODIV("uartd",  mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65,  TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTD),
+       TEGRA_INIT_DATA_NODIV("uarte",  mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66,  TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTE),
+       TEGRA_INIT_DATA_NODIV("disp1",  mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27,  0, TEGRA20_CLK_DISP1),
+       TEGRA_INIT_DATA_NODIV("disp2",  mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26,  0, TEGRA20_CLK_DISP2),
 };
 
 static void __init tegra20_periph_clk_init(void)
@@ -876,69 +804,13 @@ static void __init tegra20_periph_clk_init(void)
        /* ac97 */
        clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0",
                                    TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 3, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra20-ac97");
-       clks[ac97] = clk;
+                                   clk_base, 0, 3, periph_clk_enb_refcnt);
+       clks[TEGRA20_CLK_AC97] = clk;
 
        /* apbdma */
        clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base,
-                                   0, 34, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-apbdma");
-       clks[apbdma] = clk;
-
-       /* rtc */
-       clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
-                                   TEGRA_PERIPH_NO_RESET,
-                                   clk_base, 0, 4, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "rtc-tegra");
-       clks[rtc] = clk;
-
-       /* timer */
-       clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
-                                   0, 5, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "timer");
-       clks[timer] = clk;
-
-       /* kbc */
-       clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
-                                   TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 36, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-kbc");
-       clks[kbc] = clk;
-
-       /* csus */
-       clk = tegra_clk_register_periph_gate("csus", "clk_m",
-                                   TEGRA_PERIPH_NO_RESET,
-                                   clk_base, 0, 92, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "csus", "tengra_camera");
-       clks[csus] = clk;
-
-       /* vcp */
-       clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0,
-                                   clk_base, 0, 29, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "vcp", "tegra-avp");
-       clks[vcp] = clk;
-
-       /* bsea */
-       clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0,
-                                   clk_base, 0, 62, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "bsea", "tegra-avp");
-       clks[bsea] = clk;
-
-       /* bsev */
-       clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0,
-                                   clk_base, 0, 63, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "bsev", "tegra-aes");
-       clks[bsev] = clk;
+                                   0, 34, periph_clk_enb_refcnt);
+       clks[TEGRA20_CLK_APBDMA] = clk;
 
        /* emc */
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
@@ -947,130 +819,52 @@ static void __init tegra20_periph_clk_init(void)
                               clk_base + CLK_SOURCE_EMC,
                               30, 2, 0, NULL);
        clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
-                                   57, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "emc", NULL);
-       clks[emc] = clk;
-
-       /* usbd */
-       clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0,
-                                   22, &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "fsl-tegra-udc");
-       clks[usbd] = clk;
-
-       /* usb2 */
-       clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0,
-                                   58, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-ehci.1");
-       clks[usb2] = clk;
-
-       /* usb3 */
-       clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0,
-                                   59, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-ehci.2");
-       clks[usb3] = clk;
+                                   57, periph_clk_enb_refcnt);
+       clks[TEGRA20_CLK_EMC] = clk;
 
        /* dsi */
        clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
-                                   48, &periph_h_regs, periph_clk_enb_refcnt);
+                                   48, periph_clk_enb_refcnt);
        clk_register_clkdev(clk, NULL, "dsi");
-       clks[dsi] = clk;
-
-       /* csi */
-       clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
-                                   0, 52, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "csi", "tegra_camera");
-       clks[csi] = clk;
-
-       /* isp */
-       clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23,
-                                   &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "isp", "tegra_camera");
-       clks[isp] = clk;
+       clks[TEGRA20_CLK_DSI] = clk;
 
        /* pex */
        clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70,
-                                   &periph_u_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "pex", NULL);
-       clks[pex] = clk;
-
-       /* afi */
-       clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72,
-                                   &periph_u_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "afi", NULL);
-       clks[afi] = clk;
-
-       /* pcie_xclk */
-       clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base,
-                                   0, 74, &periph_u_regs,
                                    periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "pcie_xclk", NULL);
-       clks[pcie_xclk] = clk;
+       clks[TEGRA20_CLK_PEX] = clk;
 
        /* cdev1 */
        clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT,
                                      26000000);
        clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0,
-                                   clk_base, 0, 94, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "cdev1", NULL);
-       clks[cdev1] = clk;
+                                   clk_base, 0, 94, periph_clk_enb_refcnt);
+       clks[TEGRA20_CLK_CDEV1] = clk;
 
        /* cdev2 */
        clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT,
                                      26000000);
        clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0,
-                                   clk_base, 0, 93, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "cdev2", NULL);
-       clks[cdev2] = clk;
+                                   clk_base, 0, 93, periph_clk_enb_refcnt);
+       clks[TEGRA20_CLK_CDEV2] = clk;
 
        for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
                data = &tegra_periph_clk_list[i];
-               clk = tegra_clk_register_periph(data->name, data->parent_names,
+               clk = tegra_clk_register_periph(data->name, data->p.parent_names,
                                data->num_parents, &data->periph,
                                clk_base, data->offset, data->flags);
-               clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
 
        for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
                data = &tegra_periph_nodiv_clk_list[i];
                clk = tegra_clk_register_periph_nodiv(data->name,
-                                       data->parent_names,
+                                       data->p.parent_names,
                                        data->num_parents, &data->periph,
                                        clk_base, data->offset);
-               clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
-}
-
-
-static void __init tegra20_fixed_clk_init(void)
-{
-       struct clk *clk;
-
-       /* clk_32k */
-       clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
-                                     32768);
-       clk_register_clkdev(clk, "clk_32k", NULL);
-       clks[clk_32k] = clk;
-}
-
-static void __init tegra20_pmc_clk_init(void)
-{
-       struct clk *clk;
 
-       /* blink */
-       writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
-       clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
-                               pmc_base + PMC_DPD_PADS_ORIDE,
-                               PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
-       clk = clk_register_gate(NULL, "blink", "blink_override", 0,
-                               pmc_base + PMC_CTRL,
-                               PMC_CTRL_BLINK_ENB, 0, NULL);
-       clk_register_clkdev(clk, "blink", NULL);
-       clks[blink] = clk;
+       tegra_periph_clk_init(clk_base, pmc_base, tegra20_clks, &pll_p_params);
 }
 
 static void __init tegra20_osc_clk_init(void)
@@ -1084,15 +878,13 @@ static void __init tegra20_osc_clk_init(void)
        /* clk_m */
        clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT |
                                      CLK_IGNORE_UNUSED, input_freq);
-       clk_register_clkdev(clk, "clk_m", NULL);
-       clks[clk_m] = clk;
+       clks[TEGRA20_CLK_CLK_M] = clk;
 
        /* pll_ref */
        pll_ref_div = tegra20_get_pll_ref_div();
        clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
                                        CLK_SET_RATE_PARENT, 1, pll_ref_div);
-       clk_register_clkdev(clk, "pll_ref", NULL);
-       clks[pll_ref] = clk;
+       clks[TEGRA20_CLK_PLL_REF] = clk;
 }
 
 /* Tegra20 CPU clock and reset control functions */
@@ -1226,49 +1018,49 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
 };
 
 static struct tegra_clk_init_table init_table[] __initdata = {
-       {pll_p, clk_max, 216000000, 1},
-       {pll_p_out1, clk_max, 28800000, 1},
-       {pll_p_out2, clk_max, 48000000, 1},
-       {pll_p_out3, clk_max, 72000000, 1},
-       {pll_p_out4, clk_max, 24000000, 1},
-       {pll_c, clk_max, 600000000, 1},
-       {pll_c_out1, clk_max, 120000000, 1},
-       {sclk, pll_c_out1, 0, 1},
-       {hclk, clk_max, 0, 1},
-       {pclk, clk_max, 60000000, 1},
-       {csite, clk_max, 0, 1},
-       {emc, clk_max, 0, 1},
-       {cclk, clk_max, 0, 1},
-       {uarta, pll_p, 0, 0},
-       {uartb, pll_p, 0, 0},
-       {uartc, pll_p, 0, 0},
-       {uartd, pll_p, 0, 0},
-       {uarte, pll_p, 0, 0},
-       {pll_a, clk_max, 56448000, 1},
-       {pll_a_out0, clk_max, 11289600, 1},
-       {cdev1, clk_max, 0, 1},
-       {blink, clk_max, 32768, 1},
-       {i2s1, pll_a_out0, 11289600, 0},
-       {i2s2, pll_a_out0, 11289600, 0},
-       {sdmmc1, pll_p, 48000000, 0},
-       {sdmmc3, pll_p, 48000000, 0},
-       {sdmmc4, pll_p, 48000000, 0},
-       {spi, pll_p, 20000000, 0},
-       {sbc1, pll_p, 100000000, 0},
-       {sbc2, pll_p, 100000000, 0},
-       {sbc3, pll_p, 100000000, 0},
-       {sbc4, pll_p, 100000000, 0},
-       {host1x, pll_c, 150000000, 0},
-       {disp1, pll_p, 600000000, 0},
-       {disp2, pll_p, 600000000, 0},
-       {gr2d, pll_c, 300000000, 0},
-       {gr3d, pll_c, 300000000, 0},
-       {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */
+       {TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1},
+       {TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1},
+       {TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1},
+       {TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1},
+       {TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1},
+       {TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1},
+       {TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1},
+       {TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1},
+       {TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1},
+       {TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1},
+       {TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1},
+       {TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1},
+       {TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1},
+       {TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0},
+       {TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0},
+       {TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0},
+       {TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0},
+       {TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0},
+       {TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1},
+       {TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1},
+       {TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1},
+       {TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1},
+       {TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0},
+       {TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0},
+       {TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0},
+       {TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0},
+       {TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0},
+       {TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0},
+       {TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0},
+       {TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0},
+       {TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0},
+       {TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0},
+       {TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0},
+       {TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0},
+       {TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0},
+       {TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry */
 };
 
 static void __init tegra20_clock_apply_init_table(void)
 {
-       tegra_init_from_table(init_table, clks, clk_max);
+       tegra_init_from_table(init_table, clks, TEGRA20_CLK_CLK_MAX);
 }
 
 /*
@@ -1277,11 +1069,11 @@ static void __init tegra20_clock_apply_init_table(void)
  * table under two names.
  */
 static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
-       TEGRA_CLK_DUPLICATE(usbd,   "utmip-pad",    NULL),
-       TEGRA_CLK_DUPLICATE(usbd,   "tegra-ehci.0", NULL),
-       TEGRA_CLK_DUPLICATE(usbd,   "tegra-otg",    NULL),
-       TEGRA_CLK_DUPLICATE(cclk,   NULL,           "cpu"),
-       TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */
+       TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "utmip-pad",    NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "tegra-ehci.0", NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD,   "tegra-otg",    NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK,   NULL,           "cpu"),
+       TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), /* Must be the last entry */
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
@@ -1291,7 +1083,6 @@ static const struct of_device_id pmc_match[] __initconst = {
 
 static void __init tegra20_clock_init(struct device_node *np)
 {
-       int i;
        struct device_node *node;
 
        clk_base = of_iomap(np, 0);
@@ -1312,30 +1103,24 @@ static void __init tegra20_clock_init(struct device_node *np)
                BUG();
        }
 
+       clks = tegra_clk_init(clk_base, TEGRA20_CLK_CLK_MAX,
+                               TEGRA20_CLK_PERIPH_BANKS);
+       if (!clks)
+               return;
+
        tegra20_osc_clk_init();
-       tegra20_pmc_clk_init();
-       tegra20_fixed_clk_init();
+       tegra_fixed_clk_init(tegra20_clks);
        tegra20_pll_init();
        tegra20_super_clk_init();
+       tegra_super_clk_gen4_init(clk_base, pmc_base, tegra20_clks, NULL);
        tegra20_periph_clk_init();
        tegra20_audio_clk_init();
+       tegra_pmc_clk_init(pmc_base, tegra20_clks);
 
+       tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX);
 
-       for (i = 0; i < ARRAY_SIZE(clks); i++) {
-               if (IS_ERR(clks[i])) {
-                       pr_err("Tegra20 clk %d: register failed with %ld\n",
-                              i, PTR_ERR(clks[i]));
-                       BUG();
-               }
-               if (!clks[i])
-                       clks[i] = ERR_PTR(-EINVAL);
-       }
-
-       tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max);
-
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       tegra_add_of_provider(np);
+       tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
        tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
 
index dbe7c8003c5c4392244b7161e5b7771634e7e8c3..8b10c38b6e3c677a19be8253ca11629a3a145445 100644 (file)
 #include <linux/of_address.h>
 #include <linux/clk/tegra.h>
 #include <linux/tegra-powergate.h>
-
+#include <dt-bindings/clock/tegra30-car.h>
 #include "clk.h"
-
-#define RST_DEVICES_L 0x004
-#define RST_DEVICES_H 0x008
-#define RST_DEVICES_U 0x00c
-#define RST_DEVICES_V 0x358
-#define RST_DEVICES_W 0x35c
-#define RST_DEVICES_SET_L 0x300
-#define RST_DEVICES_CLR_L 0x304
-#define RST_DEVICES_SET_H 0x308
-#define RST_DEVICES_CLR_H 0x30c
-#define RST_DEVICES_SET_U 0x310
-#define RST_DEVICES_CLR_U 0x314
-#define RST_DEVICES_SET_V 0x430
-#define RST_DEVICES_CLR_V 0x434
-#define RST_DEVICES_SET_W 0x438
-#define RST_DEVICES_CLR_W 0x43c
-#define RST_DEVICES_NUM 5
-
-#define CLK_OUT_ENB_L 0x010
-#define CLK_OUT_ENB_H 0x014
-#define CLK_OUT_ENB_U 0x018
-#define CLK_OUT_ENB_V 0x360
-#define CLK_OUT_ENB_W 0x364
-#define CLK_OUT_ENB_SET_L 0x320
-#define CLK_OUT_ENB_CLR_L 0x324
-#define CLK_OUT_ENB_SET_H 0x328
-#define CLK_OUT_ENB_CLR_H 0x32c
-#define CLK_OUT_ENB_SET_U 0x330
-#define CLK_OUT_ENB_CLR_U 0x334
-#define CLK_OUT_ENB_SET_V 0x440
-#define CLK_OUT_ENB_CLR_V 0x444
-#define CLK_OUT_ENB_SET_W 0x448
-#define CLK_OUT_ENB_CLR_W 0x44c
-#define CLK_OUT_ENB_NUM 5
+#include "clk-id.h"
 
 #define OSC_CTRL                       0x50
 #define OSC_CTRL_OSC_FREQ_MASK         (0xF<<28)
@@ -92,6 +59,8 @@
 
 #define SYSTEM_CLK_RATE 0x030
 
+#define TEGRA30_CLK_PERIPH_BANKS       5
+
 #define PLLC_BASE 0x80
 #define PLLC_MISC 0x8c
 #define PLLM_BASE 0x90
 #define AUDIO_SYNC_CLK_I2S4 0x4b0
 #define AUDIO_SYNC_CLK_SPDIF 0x4b4
 
-#define PMC_CLK_OUT_CNTRL 0x1a8
-
-#define CLK_SOURCE_I2S0 0x1d8
-#define CLK_SOURCE_I2S1 0x100
-#define CLK_SOURCE_I2S2 0x104
-#define CLK_SOURCE_I2S3 0x3bc
-#define CLK_SOURCE_I2S4 0x3c0
 #define CLK_SOURCE_SPDIF_OUT 0x108
-#define CLK_SOURCE_SPDIF_IN 0x10c
 #define CLK_SOURCE_PWM 0x110
 #define CLK_SOURCE_D_AUDIO 0x3d0
 #define CLK_SOURCE_DAM0 0x3d8
 #define CLK_SOURCE_DAM1 0x3dc
 #define CLK_SOURCE_DAM2 0x3e0
-#define CLK_SOURCE_HDA 0x428
-#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
-#define CLK_SOURCE_SBC1 0x134
-#define CLK_SOURCE_SBC2 0x118
-#define CLK_SOURCE_SBC3 0x11c
-#define CLK_SOURCE_SBC4 0x1b4
-#define CLK_SOURCE_SBC5 0x3c8
-#define CLK_SOURCE_SBC6 0x3cc
-#define CLK_SOURCE_SATA_OOB 0x420
-#define CLK_SOURCE_SATA 0x424
-#define CLK_SOURCE_NDFLASH 0x160
-#define CLK_SOURCE_NDSPEED 0x3f8
-#define CLK_SOURCE_VFIR 0x168
-#define CLK_SOURCE_SDMMC1 0x150
-#define CLK_SOURCE_SDMMC2 0x154
-#define CLK_SOURCE_SDMMC3 0x1bc
-#define CLK_SOURCE_SDMMC4 0x164
-#define CLK_SOURCE_VDE 0x1c8
-#define CLK_SOURCE_CSITE 0x1d4
-#define CLK_SOURCE_LA 0x1f8
-#define CLK_SOURCE_OWR 0x1cc
-#define CLK_SOURCE_NOR 0x1d0
-#define CLK_SOURCE_MIPI 0x174
-#define CLK_SOURCE_I2C1 0x124
-#define CLK_SOURCE_I2C2 0x198
-#define CLK_SOURCE_I2C3 0x1b8
-#define CLK_SOURCE_I2C4 0x3c4
-#define CLK_SOURCE_I2C5 0x128
-#define CLK_SOURCE_UARTA 0x178
-#define CLK_SOURCE_UARTB 0x17c
-#define CLK_SOURCE_UARTC 0x1a0
-#define CLK_SOURCE_UARTD 0x1c0
-#define CLK_SOURCE_UARTE 0x1c4
-#define CLK_SOURCE_VI 0x148
-#define CLK_SOURCE_VI_SENSOR 0x1a8
-#define CLK_SOURCE_3D 0x158
 #define CLK_SOURCE_3D2 0x3b0
 #define CLK_SOURCE_2D 0x15c
-#define CLK_SOURCE_EPP 0x16c
-#define CLK_SOURCE_MPE 0x170
-#define CLK_SOURCE_HOST1X 0x180
-#define CLK_SOURCE_CVE 0x140
-#define CLK_SOURCE_TVO 0x188
-#define CLK_SOURCE_DTV 0x1dc
 #define CLK_SOURCE_HDMI 0x18c
-#define CLK_SOURCE_TVDAC 0x194
-#define CLK_SOURCE_DISP1 0x138
-#define CLK_SOURCE_DISP2 0x13c
 #define CLK_SOURCE_DSIB 0xd0
-#define CLK_SOURCE_TSENSOR 0x3b8
-#define CLK_SOURCE_ACTMON 0x3e8
-#define CLK_SOURCE_EXTERN1 0x3ec
-#define CLK_SOURCE_EXTERN2 0x3f0
-#define CLK_SOURCE_EXTERN3 0x3f4
-#define CLK_SOURCE_I2CSLOW 0x3fc
 #define CLK_SOURCE_SE 0x42c
-#define CLK_SOURCE_MSELECT 0x3b4
 #define CLK_SOURCE_EMC 0x19c
 
 #define AUDIO_SYNC_DOUBLER 0x49c
 
-#define PMC_CTRL 0
-#define PMC_CTRL_BLINK_ENB 7
-
-#define PMC_DPD_PADS_ORIDE 0x1c
-#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
-#define PMC_BLINK_TIMER 0x40
-
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
 #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
@@ -266,89 +168,41 @@ static struct cpu_clk_suspend_context {
 } tegra30_cpu_clk_sctx;
 #endif
 
-static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
-
 static void __iomem *clk_base;
 static void __iomem *pmc_base;
 static unsigned long input_freq;
 
-static DEFINE_SPINLOCK(clk_doubler_lock);
-static DEFINE_SPINLOCK(clk_out_lock);
-static DEFINE_SPINLOCK(pll_div_lock);
 static DEFINE_SPINLOCK(cml_lock);
 static DEFINE_SPINLOCK(pll_d_lock);
-static DEFINE_SPINLOCK(sysrate_lock);
-
-#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 8, 1, 0, _regs, _clk_num,          \
-                       periph_clk_enb_refcnt, _gate_flags, _clk_id)
-
-#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,     \
-                       _regs, _clk_num, periph_clk_enb_refcnt,         \
-                       _gate_flags, _clk_id)
-
-#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
-                            _clk_num, _regs, _gate_flags, _clk_id)     \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       29, 3, 0, 0, 8, 1, 0, _regs, _clk_num,          \
-                       periph_clk_enb_refcnt, _gate_flags, _clk_id)
-
-#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,        \
-                           _clk_num, _regs, _gate_flags, _clk_id)      \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,    \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
-                       _clk_id)
 
-#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
-                            _clk_num, _regs, _clk_id)                  \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,  \
-                       _clk_num, periph_clk_enb_refcnt, 0, _clk_id)
+#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset,  \
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \
+                       _clk_num, _gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_MUX8(_name, _parents, _offset, \
+                            _clk_num, _gate_flags, _clk_id)    \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \
+                       _clk_num, _gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_INT(_name, _parents, _offset,  \
+                           _clk_num, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT |          \
+                       TEGRA_DIVIDER_ROUND_UP, _clk_num,       \
+                       _gate_flags, _clk_id)
 
-#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
-                             _mux_shift, _mux_width, _clk_num, _regs,  \
+#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \
+                             _mux_shift, _mux_width, _clk_num, \
                              _gate_flags, _clk_id)                     \
-       TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,     \
-                       _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs,   \
-                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+       TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
+                       _mux_shift, _mux_width, 0, 0, 0, 0, 0,\
+                       _clk_num, _gate_flags,  \
                        _clk_id)
 
-/*
- * IDs assigned here must be in sync with DT bindings definition
- * for Tegra30 clocks.
- */
-enum tegra30_clk {
-       cpu, rtc = 4, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, ndflash,
-       sdmmc1, sdmmc4, pwm = 17, i2s2, epp, gr2d = 21, usbd, isp, gr3d,
-       disp2 = 26, disp1, host1x, vcp, i2s0, cop_cache, mc, ahbdma, apbdma,
-       kbc = 36, statmon, pmc, kfuse = 40, sbc1, nor, sbc2 = 44, sbc3 = 46,
-       i2c5, dsia, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
-       usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
-       pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2cslow,
-       dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92,
-       cdev2, cdev1, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4,
-       i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x,
-       atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x,
-       spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda,
-       se = 127, hda2hdmi, sata_cold, uartb = 160, vfir, spdif_in, spdif_out,
-       vi, vi_sensor, fuse, fuse_burn, cve, tvo, clk_32k, clk_m, clk_m_div2,
-       clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_m, pll_m_out1, pll_p,
-       pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_a, pll_a_out0,
-       pll_d, pll_d_out0, pll_d2, pll_d2_out0, pll_u, pll_x, pll_x_out0, pll_e,
-       spdif_in_sync, i2s0_sync, i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync,
-       vimclk_sync, audio0, audio1, audio2, audio3, audio4, spdif, clk_out_1,
-       clk_out_2, clk_out_3, sclk, blink, cclk_g, cclk_lp, twd, cml0, cml1,
-       hclk, pclk, clk_out_1_mux = 300, clk_max
-};
-
-static struct clk *clks[clk_max];
-static struct clk_onecell_data clk_data;
+static struct clk **clks;
 
 /*
  * Structure defining the fields for USB UTMI clocks Parameters.
@@ -564,6 +418,8 @@ static struct tegra_clk_pll_params pll_c_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_c_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
 };
 
 static struct div_nmp pllm_nmp = {
@@ -593,6 +449,9 @@ static struct tegra_clk_pll_params pll_m_params = {
        .div_nmp = &pllm_nmp,
        .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
        .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE,
+       .freq_table = pll_m_freq_table,
+       .flags = TEGRA_PLLM | TEGRA_PLL_HAS_CPCON |
+                TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_p_params = {
@@ -607,6 +466,9 @@ static struct tegra_clk_pll_params pll_p_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_p_freq_table,
+       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+       .fixed_rate = 408000000,
 };
 
 static struct tegra_clk_pll_params pll_a_params = {
@@ -621,6 +483,8 @@ static struct tegra_clk_pll_params pll_a_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_a_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_d_params = {
@@ -635,6 +499,10 @@ static struct tegra_clk_pll_params pll_d_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
+
 };
 
 static struct tegra_clk_pll_params pll_d2_params = {
@@ -649,6 +517,9 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
+       .freq_table = pll_d_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_u_params = {
@@ -664,6 +535,8 @@ static struct tegra_clk_pll_params pll_u_params = {
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .pdiv_tohw = pllu_p,
+       .freq_table = pll_u_freq_table,
+       .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -678,6 +551,9 @@ static struct tegra_clk_pll_params pll_x_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_x_freq_table,
+       .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON |
+                TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_params pll_e_params = {
@@ -692,116 +568,299 @@ static struct tegra_clk_pll_params pll_e_params = {
        .lock_mask = PLLE_MISC_LOCK,
        .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
        .lock_delay = 300,
+       .freq_table = pll_e_freq_table,
+       .flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED,
+       .fixed_rate = 100000000,
 };
 
-/* Peripheral clock registers */
-static struct tegra_clk_periph_regs periph_l_regs = {
-       .enb_reg = CLK_OUT_ENB_L,
-       .enb_set_reg = CLK_OUT_ENB_SET_L,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_L,
-       .rst_reg = RST_DEVICES_L,
-       .rst_set_reg = RST_DEVICES_SET_L,
-       .rst_clr_reg = RST_DEVICES_CLR_L,
+static unsigned long tegra30_input_freq[] = {
+       [0] = 13000000,
+       [1] = 16800000,
+       [4] = 19200000,
+       [5] = 38400000,
+       [8] = 12000000,
+       [9] = 48000000,
+       [12] = 260000000,
 };
 
-static struct tegra_clk_periph_regs periph_h_regs = {
-       .enb_reg = CLK_OUT_ENB_H,
-       .enb_set_reg = CLK_OUT_ENB_SET_H,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_H,
-       .rst_reg = RST_DEVICES_H,
-       .rst_set_reg = RST_DEVICES_SET_H,
-       .rst_clr_reg = RST_DEVICES_CLR_H,
+static struct tegra_devclk devclks[] __initdata = {
+       { .con_id = "pll_c", .dt_id = TEGRA30_CLK_PLL_C },
+       { .con_id = "pll_c_out1", .dt_id = TEGRA30_CLK_PLL_C_OUT1 },
+       { .con_id = "pll_p", .dt_id = TEGRA30_CLK_PLL_P },
+       { .con_id = "pll_p_out1", .dt_id = TEGRA30_CLK_PLL_P_OUT1 },
+       { .con_id = "pll_p_out2", .dt_id = TEGRA30_CLK_PLL_P_OUT2 },
+       { .con_id = "pll_p_out3", .dt_id = TEGRA30_CLK_PLL_P_OUT3 },
+       { .con_id = "pll_p_out4", .dt_id = TEGRA30_CLK_PLL_P_OUT4 },
+       { .con_id = "pll_m", .dt_id = TEGRA30_CLK_PLL_M },
+       { .con_id = "pll_m_out1", .dt_id = TEGRA30_CLK_PLL_M_OUT1 },
+       { .con_id = "pll_x", .dt_id = TEGRA30_CLK_PLL_X },
+       { .con_id = "pll_x_out0", .dt_id = TEGRA30_CLK_PLL_X_OUT0 },
+       { .con_id = "pll_u", .dt_id = TEGRA30_CLK_PLL_U },
+       { .con_id = "pll_d", .dt_id = TEGRA30_CLK_PLL_D },
+       { .con_id = "pll_d_out0", .dt_id = TEGRA30_CLK_PLL_D_OUT0 },
+       { .con_id = "pll_d2", .dt_id = TEGRA30_CLK_PLL_D2 },
+       { .con_id = "pll_d2_out0", .dt_id = TEGRA30_CLK_PLL_D2_OUT0 },
+       { .con_id = "pll_a", .dt_id = TEGRA30_CLK_PLL_A },
+       { .con_id = "pll_a_out0", .dt_id = TEGRA30_CLK_PLL_A_OUT0 },
+       { .con_id = "pll_e", .dt_id = TEGRA30_CLK_PLL_E },
+       { .con_id = "spdif_in_sync", .dt_id = TEGRA30_CLK_SPDIF_IN_SYNC },
+       { .con_id = "i2s0_sync", .dt_id = TEGRA30_CLK_I2S0_SYNC },
+       { .con_id = "i2s1_sync", .dt_id = TEGRA30_CLK_I2S1_SYNC },
+       { .con_id = "i2s2_sync", .dt_id = TEGRA30_CLK_I2S2_SYNC },
+       { .con_id = "i2s3_sync", .dt_id = TEGRA30_CLK_I2S3_SYNC },
+       { .con_id = "i2s4_sync", .dt_id = TEGRA30_CLK_I2S4_SYNC },
+       { .con_id = "vimclk_sync", .dt_id = TEGRA30_CLK_VIMCLK_SYNC },
+       { .con_id = "audio0", .dt_id = TEGRA30_CLK_AUDIO0 },
+       { .con_id = "audio1", .dt_id = TEGRA30_CLK_AUDIO1 },
+       { .con_id = "audio2", .dt_id = TEGRA30_CLK_AUDIO2 },
+       { .con_id = "audio3", .dt_id = TEGRA30_CLK_AUDIO3 },
+       { .con_id = "audio4", .dt_id = TEGRA30_CLK_AUDIO4 },
+       { .con_id = "spdif", .dt_id = TEGRA30_CLK_SPDIF },
+       { .con_id = "audio0_2x", .dt_id = TEGRA30_CLK_AUDIO0_2X },
+       { .con_id = "audio1_2x", .dt_id = TEGRA30_CLK_AUDIO1_2X },
+       { .con_id = "audio2_2x", .dt_id = TEGRA30_CLK_AUDIO2_2X },
+       { .con_id = "audio3_2x", .dt_id = TEGRA30_CLK_AUDIO3_2X },
+       { .con_id = "audio4_2x", .dt_id = TEGRA30_CLK_AUDIO4_2X },
+       { .con_id = "spdif_2x", .dt_id = TEGRA30_CLK_SPDIF_2X },
+       { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA30_CLK_EXTERN1 },
+       { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA30_CLK_EXTERN2 },
+       { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA30_CLK_EXTERN3 },
+       { .con_id = "blink", .dt_id = TEGRA30_CLK_BLINK },
+       { .con_id = "cclk_g", .dt_id = TEGRA30_CLK_CCLK_G },
+       { .con_id = "cclk_lp", .dt_id = TEGRA30_CLK_CCLK_LP },
+       { .con_id = "sclk", .dt_id = TEGRA30_CLK_SCLK },
+       { .con_id = "hclk", .dt_id = TEGRA30_CLK_HCLK },
+       { .con_id = "pclk", .dt_id = TEGRA30_CLK_PCLK },
+       { .con_id = "twd", .dt_id = TEGRA30_CLK_TWD },
+       { .con_id = "emc", .dt_id = TEGRA30_CLK_EMC },
+       { .con_id = "clk_32k", .dt_id = TEGRA30_CLK_CLK_32K },
+       { .con_id = "clk_m_div2", .dt_id = TEGRA30_CLK_CLK_M_DIV2 },
+       { .con_id = "clk_m_div4", .dt_id = TEGRA30_CLK_CLK_M_DIV4 },
+       { .con_id = "cml0", .dt_id = TEGRA30_CLK_CML0 },
+       { .con_id = "cml1", .dt_id = TEGRA30_CLK_CML1 },
+       { .con_id = "clk_m", .dt_id = TEGRA30_CLK_CLK_M },
+       { .con_id = "pll_ref", .dt_id = TEGRA30_CLK_PLL_REF },
+       { .con_id = "csus", .dev_id = "tengra_camera", .dt_id = TEGRA30_CLK_CSUS },
+       { .con_id = "vcp", .dev_id = "tegra-avp", .dt_id = TEGRA30_CLK_VCP },
+       { .con_id = "bsea", .dev_id = "tegra-avp", .dt_id = TEGRA30_CLK_BSEA },
+       { .con_id = "bsev", .dev_id = "tegra-aes", .dt_id = TEGRA30_CLK_BSEV },
+       { .con_id = "dsia", .dev_id = "tegradc.0", .dt_id = TEGRA30_CLK_DSIA },
+       { .con_id = "csi", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_CSI },
+       { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_ISP },
+       { .con_id = "pcie", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIE },
+       { .con_id = "afi", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_AFI },
+       { .con_id = "fuse", .dt_id = TEGRA30_CLK_FUSE },
+       { .con_id = "fuse_burn", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE_BURN },
+       { .con_id = "apbif", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_APBIF },
+       { .con_id = "hda2hdmi", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2HDMI },
+       { .dev_id =  "tegra-apbdma", .dt_id = TEGRA30_CLK_APBDMA },
+       { .dev_id =  "rtc-tegra", .dt_id = TEGRA30_CLK_RTC },
+       { .dev_id =  "timer", .dt_id = TEGRA30_CLK_TIMER },
+       { .dev_id =  "tegra-kbc", .dt_id = TEGRA30_CLK_KBC },
+       { .dev_id =  "fsl-tegra-udc", .dt_id = TEGRA30_CLK_USBD },
+       { .dev_id =  "tegra-ehci.1", .dt_id = TEGRA30_CLK_USB2 },
+       { .dev_id =  "tegra-ehci.2", .dt_id = TEGRA30_CLK_USB2 },
+       { .dev_id =  "kfuse-tegra", .dt_id = TEGRA30_CLK_KFUSE },
+       { .dev_id =  "tegra_sata_cold", .dt_id = TEGRA30_CLK_SATA_COLD },
+       { .dev_id =  "dtv", .dt_id = TEGRA30_CLK_DTV },
+       { .dev_id = "tegra30-i2s.0", .dt_id = TEGRA30_CLK_I2S0 },
+       { .dev_id = "tegra30-i2s.1", .dt_id = TEGRA30_CLK_I2S1 },
+       { .dev_id = "tegra30-i2s.2", .dt_id = TEGRA30_CLK_I2S2 },
+       { .dev_id = "tegra30-i2s.3", .dt_id = TEGRA30_CLK_I2S3 },
+       { .dev_id = "tegra30-i2s.4", .dt_id = TEGRA30_CLK_I2S4 },
+       { .con_id = "spdif_out", .dev_id = "tegra30-spdif", .dt_id = TEGRA30_CLK_SPDIF_OUT },
+       { .con_id = "spdif_in", .dev_id = "tegra30-spdif", .dt_id = TEGRA30_CLK_SPDIF_IN },
+       { .con_id = "d_audio", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_D_AUDIO },
+       { .dev_id = "tegra30-dam.0", .dt_id = TEGRA30_CLK_DAM0 },
+       { .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 },
+       { .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 },
+       { .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA },
+       { .con_id = "hda2codec", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X },
+       { .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 },
+       { .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 },
+       { .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 },
+       { .dev_id = "spi_tegra.3", .dt_id = TEGRA30_CLK_SBC4 },
+       { .dev_id = "spi_tegra.4", .dt_id = TEGRA30_CLK_SBC5 },
+       { .dev_id = "spi_tegra.5", .dt_id = TEGRA30_CLK_SBC6 },
+       { .dev_id = "tegra_sata_oob", .dt_id = TEGRA30_CLK_SATA_OOB },
+       { .dev_id = "tegra_sata", .dt_id = TEGRA30_CLK_SATA },
+       { .dev_id = "tegra_nand", .dt_id = TEGRA30_CLK_NDFLASH },
+       { .dev_id = "tegra_nand_speed", .dt_id = TEGRA30_CLK_NDSPEED },
+       { .dev_id = "vfir", .dt_id = TEGRA30_CLK_VFIR },
+       { .dev_id = "csite", .dt_id = TEGRA30_CLK_CSITE },
+       { .dev_id = "la", .dt_id = TEGRA30_CLK_LA },
+       { .dev_id = "tegra_w1", .dt_id = TEGRA30_CLK_OWR },
+       { .dev_id = "mipi", .dt_id = TEGRA30_CLK_MIPI },
+       { .dev_id = "tegra-tsensor", .dt_id = TEGRA30_CLK_TSENSOR },
+       { .dev_id = "i2cslow", .dt_id = TEGRA30_CLK_I2CSLOW },
+       { .dev_id = "vde", .dt_id = TEGRA30_CLK_VDE },
+       { .con_id = "vi", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_VI },
+       { .dev_id = "epp", .dt_id = TEGRA30_CLK_EPP },
+       { .dev_id = "mpe", .dt_id = TEGRA30_CLK_MPE },
+       { .dev_id = "host1x", .dt_id = TEGRA30_CLK_HOST1X },
+       { .dev_id = "3d", .dt_id = TEGRA30_CLK_GR3D },
+       { .dev_id = "3d2", .dt_id = TEGRA30_CLK_GR3D2 },
+       { .dev_id = "2d", .dt_id = TEGRA30_CLK_GR2D },
+       { .dev_id = "se", .dt_id = TEGRA30_CLK_SE },
+       { .dev_id = "mselect", .dt_id = TEGRA30_CLK_MSELECT },
+       { .dev_id = "tegra-nor", .dt_id = TEGRA30_CLK_NOR },
+       { .dev_id = "sdhci-tegra.0", .dt_id = TEGRA30_CLK_SDMMC1 },
+       { .dev_id = "sdhci-tegra.1", .dt_id = TEGRA30_CLK_SDMMC2 },
+       { .dev_id = "sdhci-tegra.2", .dt_id = TEGRA30_CLK_SDMMC3 },
+       { .dev_id = "sdhci-tegra.3", .dt_id = TEGRA30_CLK_SDMMC4 },
+       { .dev_id = "cve", .dt_id = TEGRA30_CLK_CVE },
+       { .dev_id = "tvo", .dt_id = TEGRA30_CLK_TVO },
+       { .dev_id = "tvdac", .dt_id = TEGRA30_CLK_TVDAC },
+       { .dev_id = "actmon", .dt_id = TEGRA30_CLK_ACTMON },
+       { .con_id = "vi_sensor", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_VI_SENSOR },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.0", .dt_id = TEGRA30_CLK_I2C1 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.1", .dt_id = TEGRA30_CLK_I2C2 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.2", .dt_id = TEGRA30_CLK_I2C3 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.3", .dt_id = TEGRA30_CLK_I2C4 },
+       { .con_id = "div-clk", .dev_id = "tegra-i2c.4", .dt_id = TEGRA30_CLK_I2C5 },
+       { .dev_id = "tegra_uart.0", .dt_id = TEGRA30_CLK_UARTA },
+       { .dev_id = "tegra_uart.1", .dt_id = TEGRA30_CLK_UARTB },
+       { .dev_id = "tegra_uart.2", .dt_id = TEGRA30_CLK_UARTC },
+       { .dev_id = "tegra_uart.3", .dt_id = TEGRA30_CLK_UARTD },
+       { .dev_id = "tegra_uart.4", .dt_id = TEGRA30_CLK_UARTE },
+       { .dev_id = "hdmi", .dt_id = TEGRA30_CLK_HDMI },
+       { .dev_id = "extern1", .dt_id = TEGRA30_CLK_EXTERN1 },
+       { .dev_id = "extern2", .dt_id = TEGRA30_CLK_EXTERN2 },
+       { .dev_id = "extern3", .dt_id = TEGRA30_CLK_EXTERN3 },
+       { .dev_id = "pwm", .dt_id = TEGRA30_CLK_PWM },
+       { .dev_id = "tegradc.0", .dt_id = TEGRA30_CLK_DISP1 },
+       { .dev_id = "tegradc.1", .dt_id = TEGRA30_CLK_DISP2 },
+       { .dev_id = "tegradc.1", .dt_id = TEGRA30_CLK_DSIB },
 };
 
-static struct tegra_clk_periph_regs periph_u_regs = {
-       .enb_reg = CLK_OUT_ENB_U,
-       .enb_set_reg = CLK_OUT_ENB_SET_U,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_U,
-       .rst_reg = RST_DEVICES_U,
-       .rst_set_reg = RST_DEVICES_SET_U,
-       .rst_clr_reg = RST_DEVICES_CLR_U,
-};
+static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
+       [tegra_clk_clk_32k] = { .dt_id = TEGRA30_CLK_CLK_32K, .present = true },
+       [tegra_clk_clk_m] = { .dt_id = TEGRA30_CLK_CLK_M, .present = true },
+       [tegra_clk_clk_m_div2] = { .dt_id = TEGRA30_CLK_CLK_M_DIV2, .present = true },
+       [tegra_clk_clk_m_div4] = { .dt_id = TEGRA30_CLK_CLK_M_DIV4, .present = true },
+       [tegra_clk_pll_ref] = { .dt_id = TEGRA30_CLK_PLL_REF, .present = true },
+       [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA30_CLK_SPDIF_IN_SYNC, .present = true },
+       [tegra_clk_i2s0_sync] = { .dt_id = TEGRA30_CLK_I2S0_SYNC, .present = true },
+       [tegra_clk_i2s1_sync] = { .dt_id = TEGRA30_CLK_I2S1_SYNC, .present = true },
+       [tegra_clk_i2s2_sync] = { .dt_id = TEGRA30_CLK_I2S2_SYNC, .present = true },
+       [tegra_clk_i2s3_sync] = { .dt_id = TEGRA30_CLK_I2S3_SYNC, .present = true },
+       [tegra_clk_i2s4_sync] = { .dt_id = TEGRA30_CLK_I2S4_SYNC, .present = true },
+       [tegra_clk_vimclk_sync] = { .dt_id = TEGRA30_CLK_VIMCLK_SYNC, .present = true },
+       [tegra_clk_audio0] = { .dt_id = TEGRA30_CLK_AUDIO0, .present = true },
+       [tegra_clk_audio1] = { .dt_id = TEGRA30_CLK_AUDIO1, .present = true },
+       [tegra_clk_audio2] = { .dt_id = TEGRA30_CLK_AUDIO2, .present = true },
+       [tegra_clk_audio3] = { .dt_id = TEGRA30_CLK_AUDIO3, .present = true },
+       [tegra_clk_audio4] = { .dt_id = TEGRA30_CLK_AUDIO4, .present = true },
+       [tegra_clk_spdif] = { .dt_id = TEGRA30_CLK_SPDIF, .present = true },
+       [tegra_clk_audio0_mux] = { .dt_id = TEGRA30_CLK_AUDIO0_MUX, .present = true },
+       [tegra_clk_audio1_mux] = { .dt_id = TEGRA30_CLK_AUDIO1_MUX, .present = true },
+       [tegra_clk_audio2_mux] = { .dt_id = TEGRA30_CLK_AUDIO2_MUX, .present = true },
+       [tegra_clk_audio3_mux] = { .dt_id = TEGRA30_CLK_AUDIO3_MUX, .present = true },
+       [tegra_clk_audio4_mux] = { .dt_id = TEGRA30_CLK_AUDIO4_MUX, .present = true },
+       [tegra_clk_spdif_mux] = { .dt_id = TEGRA30_CLK_SPDIF_MUX, .present = true },
+       [tegra_clk_audio0_2x] = { .dt_id = TEGRA30_CLK_AUDIO0_2X, .present = true },
+       [tegra_clk_audio1_2x] = { .dt_id = TEGRA30_CLK_AUDIO1_2X, .present = true },
+       [tegra_clk_audio2_2x] = { .dt_id = TEGRA30_CLK_AUDIO2_2X, .present = true },
+       [tegra_clk_audio3_2x] = { .dt_id = TEGRA30_CLK_AUDIO3_2X, .present = true },
+       [tegra_clk_audio4_2x] = { .dt_id = TEGRA30_CLK_AUDIO4_2X, .present = true },
+       [tegra_clk_spdif_2x] = { .dt_id = TEGRA30_CLK_SPDIF_2X, .present = true },
+       [tegra_clk_clk_out_1] = { .dt_id = TEGRA30_CLK_CLK_OUT_1, .present = true },
+       [tegra_clk_clk_out_2] = { .dt_id = TEGRA30_CLK_CLK_OUT_2, .present = true },
+       [tegra_clk_clk_out_3] = { .dt_id = TEGRA30_CLK_CLK_OUT_3, .present = true },
+       [tegra_clk_blink] = { .dt_id = TEGRA30_CLK_BLINK, .present = true },
+       [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_1_MUX, .present = true },
+       [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_2_MUX, .present = true },
+       [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_3_MUX, .present = true },
+       [tegra_clk_hclk] = { .dt_id = TEGRA30_CLK_HCLK, .present = true },
+       [tegra_clk_pclk] = { .dt_id = TEGRA30_CLK_PCLK, .present = true },
+       [tegra_clk_i2s0] = { .dt_id = TEGRA30_CLK_I2S0, .present = true },
+       [tegra_clk_i2s1] = { .dt_id = TEGRA30_CLK_I2S1, .present = true },
+       [tegra_clk_i2s2] = { .dt_id = TEGRA30_CLK_I2S2, .present = true },
+       [tegra_clk_i2s3] = { .dt_id = TEGRA30_CLK_I2S3, .present = true },
+       [tegra_clk_i2s4] = { .dt_id = TEGRA30_CLK_I2S4, .present = true },
+       [tegra_clk_spdif_in] = { .dt_id = TEGRA30_CLK_SPDIF_IN, .present = true },
+       [tegra_clk_hda] = { .dt_id = TEGRA30_CLK_HDA, .present = true },
+       [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA30_CLK_HDA2CODEC_2X, .present = true },
+       [tegra_clk_sbc1] = { .dt_id = TEGRA30_CLK_SBC1, .present = true },
+       [tegra_clk_sbc2] = { .dt_id = TEGRA30_CLK_SBC2, .present = true },
+       [tegra_clk_sbc3] = { .dt_id = TEGRA30_CLK_SBC3, .present = true },
+       [tegra_clk_sbc4] = { .dt_id = TEGRA30_CLK_SBC4, .present = true },
+       [tegra_clk_sbc5] = { .dt_id = TEGRA30_CLK_SBC5, .present = true },
+       [tegra_clk_sbc6] = { .dt_id = TEGRA30_CLK_SBC6, .present = true },
+       [tegra_clk_ndflash] = { .dt_id = TEGRA30_CLK_NDFLASH, .present = true },
+       [tegra_clk_ndspeed] = { .dt_id = TEGRA30_CLK_NDSPEED, .present = true },
+       [tegra_clk_vfir] = { .dt_id = TEGRA30_CLK_VFIR, .present = true },
+       [tegra_clk_la] = { .dt_id = TEGRA30_CLK_LA, .present = true },
+       [tegra_clk_csite] = { .dt_id = TEGRA30_CLK_CSITE, .present = true },
+       [tegra_clk_owr] = { .dt_id = TEGRA30_CLK_OWR, .present = true },
+       [tegra_clk_mipi] = { .dt_id = TEGRA30_CLK_MIPI, .present = true },
+       [tegra_clk_tsensor] = { .dt_id = TEGRA30_CLK_TSENSOR, .present = true },
+       [tegra_clk_i2cslow] = { .dt_id = TEGRA30_CLK_I2CSLOW, .present = true },
+       [tegra_clk_vde] = { .dt_id = TEGRA30_CLK_VDE, .present = true },
+       [tegra_clk_vi] = { .dt_id = TEGRA30_CLK_VI, .present = true },
+       [tegra_clk_epp] = { .dt_id = TEGRA30_CLK_EPP, .present = true },
+       [tegra_clk_mpe] = { .dt_id = TEGRA30_CLK_MPE, .present = true },
+       [tegra_clk_host1x] = { .dt_id = TEGRA30_CLK_HOST1X, .present = true },
+       [tegra_clk_gr2d] = { .dt_id = TEGRA30_CLK_GR2D, .present = true },
+       [tegra_clk_gr3d] = { .dt_id = TEGRA30_CLK_GR3D, .present = true },
+       [tegra_clk_mselect] = { .dt_id = TEGRA30_CLK_MSELECT, .present = true },
+       [tegra_clk_nor] = { .dt_id = TEGRA30_CLK_NOR, .present = true },
+       [tegra_clk_sdmmc1] = { .dt_id = TEGRA30_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc2] = { .dt_id = TEGRA30_CLK_SDMMC2, .present = true },
+       [tegra_clk_sdmmc3] = { .dt_id = TEGRA30_CLK_SDMMC3, .present = true },
+       [tegra_clk_sdmmc4] = { .dt_id = TEGRA30_CLK_SDMMC4, .present = true },
+       [tegra_clk_cve] = { .dt_id = TEGRA30_CLK_CVE, .present = true },
+       [tegra_clk_tvo] = { .dt_id = TEGRA30_CLK_TVO, .present = true },
+       [tegra_clk_tvdac] = { .dt_id = TEGRA30_CLK_TVDAC, .present = true },
+       [tegra_clk_actmon] = { .dt_id = TEGRA30_CLK_ACTMON, .present = true },
+       [tegra_clk_vi_sensor] = { .dt_id = TEGRA30_CLK_VI_SENSOR, .present = true },
+       [tegra_clk_i2c1] = { .dt_id = TEGRA30_CLK_I2C1, .present = true },
+       [tegra_clk_i2c2] = { .dt_id = TEGRA30_CLK_I2C2, .present = true },
+       [tegra_clk_i2c3] = { .dt_id = TEGRA30_CLK_I2C3, .present = true },
+       [tegra_clk_i2c4] = { .dt_id = TEGRA30_CLK_I2C4, .present = true },
+       [tegra_clk_i2c5] = { .dt_id = TEGRA30_CLK_I2C5, .present = true },
+       [tegra_clk_uarta] = { .dt_id = TEGRA30_CLK_UARTA, .present = true },
+       [tegra_clk_uartb] = { .dt_id = TEGRA30_CLK_UARTB, .present = true },
+       [tegra_clk_uartc] = { .dt_id = TEGRA30_CLK_UARTC, .present = true },
+       [tegra_clk_uartd] = { .dt_id = TEGRA30_CLK_UARTD, .present = true },
+       [tegra_clk_uarte] = { .dt_id = TEGRA30_CLK_UARTE, .present = true },
+       [tegra_clk_extern1] = { .dt_id = TEGRA30_CLK_EXTERN1, .present = true },
+       [tegra_clk_extern2] = { .dt_id = TEGRA30_CLK_EXTERN2, .present = true },
+       [tegra_clk_extern3] = { .dt_id = TEGRA30_CLK_EXTERN3, .present = true },
+       [tegra_clk_disp1] = { .dt_id = TEGRA30_CLK_DISP1, .present = true },
+       [tegra_clk_disp2] = { .dt_id = TEGRA30_CLK_DISP2, .present = true },
+       [tegra_clk_apbdma] = { .dt_id = TEGRA30_CLK_APBDMA, .present = true },
+       [tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true },
+       [tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true },
+       [tegra_clk_kbc] = { .dt_id = TEGRA30_CLK_KBC, .present = true },
+       [tegra_clk_csus] = { .dt_id = TEGRA30_CLK_CSUS, .present = true },
+       [tegra_clk_vcp] = { .dt_id = TEGRA30_CLK_VCP, .present = true },
+       [tegra_clk_bsea] = { .dt_id = TEGRA30_CLK_BSEA, .present = true },
+       [tegra_clk_bsev] = { .dt_id = TEGRA30_CLK_BSEV, .present = true },
+       [tegra_clk_usbd] = { .dt_id = TEGRA30_CLK_USBD, .present = true },
+       [tegra_clk_usb2] = { .dt_id = TEGRA30_CLK_USB2, .present = true },
+       [tegra_clk_usb3] = { .dt_id = TEGRA30_CLK_USB3, .present = true },
+       [tegra_clk_csi] = { .dt_id = TEGRA30_CLK_CSI, .present = true },
+       [tegra_clk_isp] = { .dt_id = TEGRA30_CLK_ISP, .present = true },
+       [tegra_clk_kfuse] = { .dt_id = TEGRA30_CLK_KFUSE, .present = true },
+       [tegra_clk_fuse] = { .dt_id = TEGRA30_CLK_FUSE, .present = true },
+       [tegra_clk_fuse_burn] = { .dt_id = TEGRA30_CLK_FUSE_BURN, .present = true },
+       [tegra_clk_apbif] = { .dt_id = TEGRA30_CLK_APBIF, .present = true },
+       [tegra_clk_hda2hdmi] = { .dt_id = TEGRA30_CLK_HDA2HDMI, .present = true },
+       [tegra_clk_sata_cold] = { .dt_id = TEGRA30_CLK_SATA_COLD, .present = true },
+       [tegra_clk_sata_oob] = { .dt_id = TEGRA30_CLK_SATA_OOB, .present = true },
+       [tegra_clk_sata] = { .dt_id = TEGRA30_CLK_SATA, .present = true },
+       [tegra_clk_dtv] = { .dt_id = TEGRA30_CLK_DTV, .present = true },
+       [tegra_clk_pll_p] = { .dt_id = TEGRA30_CLK_PLL_P, .present = true },
+       [tegra_clk_pll_p_out1] = { .dt_id = TEGRA30_CLK_PLL_P_OUT1, .present = true },
+       [tegra_clk_pll_p_out2] = { .dt_id = TEGRA30_CLK_PLL_P_OUT2, .present = true },
+       [tegra_clk_pll_p_out3] = { .dt_id = TEGRA30_CLK_PLL_P_OUT3, .present = true },
+       [tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true },
+       [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
+       [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
 
-static struct tegra_clk_periph_regs periph_v_regs = {
-       .enb_reg = CLK_OUT_ENB_V,
-       .enb_set_reg = CLK_OUT_ENB_SET_V,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_V,
-       .rst_reg = RST_DEVICES_V,
-       .rst_set_reg = RST_DEVICES_SET_V,
-       .rst_clr_reg = RST_DEVICES_CLR_V,
 };
 
-static struct tegra_clk_periph_regs periph_w_regs = {
-       .enb_reg = CLK_OUT_ENB_W,
-       .enb_set_reg = CLK_OUT_ENB_SET_W,
-       .enb_clr_reg = CLK_OUT_ENB_CLR_W,
-       .rst_reg = RST_DEVICES_W,
-       .rst_set_reg = RST_DEVICES_SET_W,
-       .rst_clr_reg = RST_DEVICES_CLR_W,
-};
-
-static void tegra30_clk_measure_input_freq(void)
-{
-       u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL);
-       u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK;
-       u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
-
-       switch (auto_clk_control) {
-       case OSC_CTRL_OSC_FREQ_12MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-               input_freq = 12000000;
-               break;
-       case OSC_CTRL_OSC_FREQ_13MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-               input_freq = 13000000;
-               break;
-       case OSC_CTRL_OSC_FREQ_19_2MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-               input_freq = 19200000;
-               break;
-       case OSC_CTRL_OSC_FREQ_26MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-               input_freq = 26000000;
-               break;
-       case OSC_CTRL_OSC_FREQ_16_8MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-               input_freq = 16800000;
-               break;
-       case OSC_CTRL_OSC_FREQ_38_4MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2);
-               input_freq = 38400000;
-               break;
-       case OSC_CTRL_OSC_FREQ_48MHZ:
-               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
-               input_freq = 48000000;
-               break;
-       default:
-               pr_err("Unexpected auto clock control value %d",
-                       auto_clk_control);
-               BUG();
-               return;
-       }
-}
-
-static unsigned int tegra30_get_pll_ref_div(void)
-{
-       u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) &
-                                       OSC_CTRL_PLL_REF_DIV_MASK;
-
-       switch (pll_ref_div) {
-       case OSC_CTRL_PLL_REF_DIV_1:
-               return 1;
-       case OSC_CTRL_PLL_REF_DIV_2:
-               return 2;
-       case OSC_CTRL_PLL_REF_DIV_4:
-               return 4;
-       default:
-               pr_err("Invalid pll ref divider %d", pll_ref_div);
-               BUG();
-       }
-       return 0;
-}
-
 static void tegra30_utmi_param_configure(void)
 {
        u32 reg;
@@ -863,11 +922,8 @@ static void __init tegra30_pll_init(void)
 
        /* PLLC */
        clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0,
-                           0, &pll_c_params,
-                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
-                           pll_c_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_c", NULL);
-       clks[pll_c] = clk;
+                               &pll_c_params, NULL);
+       clks[TEGRA30_CLK_PLL_C] = clk;
 
        /* PLLC_OUT1 */
        clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
@@ -876,73 +932,13 @@ static void __init tegra30_pll_init(void)
        clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
                                clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT,
                                0, NULL);
-       clk_register_clkdev(clk, "pll_c_out1", NULL);
-       clks[pll_c_out1] = clk;
-
-       /* PLLP */
-       clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc_base, 0,
-                           408000000, &pll_p_params,
-                           TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_USE_LOCK, pll_p_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_p", NULL);
-       clks[pll_p] = clk;
-
-       /* PLLP_OUT1 */
-       clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1,
-                               &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
-                               clk_base + PLLP_OUTA, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out1", NULL);
-       clks[pll_p_out1] = clk;
-
-       /* PLLP_OUT2 */
-       clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
-                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
-                               &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
-                               clk_base + PLLP_OUTA, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out2", NULL);
-       clks[pll_p_out2] = clk;
-
-       /* PLLP_OUT3 */
-       clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1,
-                               &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
-                               clk_base + PLLP_OUTB, 1, 0,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out3", NULL);
-       clks[pll_p_out3] = clk;
-
-       /* PLLP_OUT4 */
-       clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
-                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
-                               TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
-                               &pll_div_lock);
-       clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
-                               clk_base + PLLP_OUTB, 17, 16,
-                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
-                               &pll_div_lock);
-       clk_register_clkdev(clk, "pll_p_out4", NULL);
-       clks[pll_p_out4] = clk;
+       clks[TEGRA30_CLK_PLL_C_OUT1] = clk;
 
        /* PLLM */
        clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base,
-                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
-                           &pll_m_params, TEGRA_PLLM | TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
-                           pll_m_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_m", NULL);
-       clks[pll_m] = clk;
+                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+                           &pll_m_params, NULL);
+       clks[TEGRA30_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
        clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
@@ -951,78 +947,44 @@ static void __init tegra30_pll_init(void)
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
                                clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
                                CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_m_out1", NULL);
-       clks[pll_m_out1] = clk;
+       clks[TEGRA30_CLK_PLL_M_OUT1] = clk;
 
        /* PLLX */
        clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, pmc_base, 0,
-                           0, &pll_x_params, TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
-                           pll_x_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_x", NULL);
-       clks[pll_x] = clk;
+                           &pll_x_params, NULL);
+       clks[TEGRA30_CLK_PLL_X] = clk;
 
        /* PLLX_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_x_out0", NULL);
-       clks[pll_x_out0] = clk;
+       clks[TEGRA30_CLK_PLL_X_OUT0] = clk;
 
        /* PLLU */
        clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0,
-                           0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_SET_LFCON,
-                           pll_u_freq_table,
-                           NULL);
-       clk_register_clkdev(clk, "pll_u", NULL);
-       clks[pll_u] = clk;
+                           &pll_u_params, NULL);
+       clks[TEGRA30_CLK_PLL_U] = clk;
 
        tegra30_utmi_param_configure();
 
        /* PLLD */
        clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0,
-                           0, &pll_d_params, TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
-                           pll_d_freq_table, &pll_d_lock);
-       clk_register_clkdev(clk, "pll_d", NULL);
-       clks[pll_d] = clk;
+                           &pll_d_params, &pll_d_lock);
+       clks[TEGRA30_CLK_PLL_D] = clk;
 
        /* PLLD_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_d_out0", NULL);
-       clks[pll_d_out0] = clk;
+       clks[TEGRA30_CLK_PLL_D_OUT0] = clk;
 
        /* PLLD2 */
        clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0,
-                           0, &pll_d2_params, TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
-                           pll_d_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_d2", NULL);
-       clks[pll_d2] = clk;
+                           &pll_d2_params, NULL);
+       clks[TEGRA30_CLK_PLL_D2] = clk;
 
        /* PLLD2_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "pll_d2_out0", NULL);
-       clks[pll_d2_out0] = clk;
-
-       /* PLLA */
-       clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc_base,
-                           0, 0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
-                           TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_a", NULL);
-       clks[pll_a] = clk;
-
-       /* PLLA_OUT0 */
-       clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
-                               clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, NULL);
-       clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
-                               clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
-                               CLK_SET_RATE_PARENT, 0, NULL);
-       clk_register_clkdev(clk, "pll_a_out0", NULL);
-       clks[pll_a_out0] = clk;
+       clks[TEGRA30_CLK_PLL_D2_OUT0] = clk;
 
        /* PLLE */
        clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents,
@@ -1030,258 +992,8 @@ static void __init tegra30_pll_init(void)
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + PLLE_AUX, 2, 1, 0, NULL);
        clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base,
-                            CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params,
-                            TEGRA_PLLE_CONFIGURE, pll_e_freq_table, NULL);
-       clk_register_clkdev(clk, "pll_e", NULL);
-       clks[pll_e] = clk;
-}
-
-static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
-       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",};
-static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
-                                         "clk_m_div4", "extern1", };
-static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
-                                         "clk_m_div4", "extern2", };
-static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
-                                         "clk_m_div4", "extern3", };
-
-static void __init tegra30_audio_clk_init(void)
-{
-       struct clk *clk;
-
-       /* spdif_in_sync */
-       clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
-                                            24000000);
-       clk_register_clkdev(clk, "spdif_in_sync", NULL);
-       clks[spdif_in_sync] = clk;
-
-       /* i2s0_sync */
-       clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s0_sync", NULL);
-       clks[i2s0_sync] = clk;
-
-       /* i2s1_sync */
-       clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s1_sync", NULL);
-       clks[i2s1_sync] = clk;
-
-       /* i2s2_sync */
-       clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s2_sync", NULL);
-       clks[i2s2_sync] = clk;
-
-       /* i2s3_sync */
-       clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s3_sync", NULL);
-       clks[i2s3_sync] = clk;
-
-       /* i2s4_sync */
-       clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "i2s4_sync", NULL);
-       clks[i2s4_sync] = clk;
-
-       /* vimclk_sync */
-       clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
-       clk_register_clkdev(clk, "vimclk_sync", NULL);
-       clks[vimclk_sync] = clk;
-
-       /* audio0 */
-       clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S0, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio0", NULL);
-       clks[audio0] = clk;
-
-       /* audio1 */
-       clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S1, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio1", NULL);
-       clks[audio1] = clk;
-
-       /* audio2 */
-       clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S2, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio2", NULL);
-       clks[audio2] = clk;
-
-       /* audio3 */
-       clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S3, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio3", NULL);
-       clks[audio3] = clk;
-
-       /* audio4 */
-       clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_I2S4, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "audio4", NULL);
-       clks[audio4] = clk;
-
-       /* spdif */
-       clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
-                               ARRAY_SIZE(mux_audio_sync_clk),
-                               CLK_SET_RATE_NO_REPARENT,
-                               clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL);
-       clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
-                               clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
-                               CLK_GATE_SET_TO_DISABLE, NULL);
-       clk_register_clkdev(clk, "spdif", NULL);
-       clks[spdif] = clk;
-
-       /* audio0_2x */
-       clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 113, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio0_2x", NULL);
-       clks[audio0_2x] = clk;
-
-       /* audio1_2x */
-       clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 114, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio1_2x", NULL);
-       clks[audio1_2x] = clk;
-
-       /* audio2_2x */
-       clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 115, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio2_2x", NULL);
-       clks[audio2_2x] = clk;
-
-       /* audio3_2x */
-       clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 116, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio3_2x", NULL);
-       clks[audio3_2x] = clk;
-
-       /* audio4_2x */
-       clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 117, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "audio4_2x", NULL);
-       clks[audio4_2x] = clk;
-
-       /* spdif_2x */
-       clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
-                                       CLK_SET_RATE_PARENT, 2, 1);
-       clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
-                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, 0,
-                               &clk_doubler_lock);
-       clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
-                                   TEGRA_PERIPH_NO_RESET, clk_base,
-                                   CLK_SET_RATE_PARENT, 118, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "spdif_2x", NULL);
-       clks[spdif_2x] = clk;
-}
-
-static void __init tegra30_pmc_clk_init(void)
-{
-       struct clk *clk;
-
-       /* clk_out_1 */
-       clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
-                              ARRAY_SIZE(clk_out1_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
-                              &clk_out_lock);
-       clks[clk_out_1_mux] = clk;
-       clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern1", "clk_out_1");
-       clks[clk_out_1] = clk;
-
-       /* clk_out_2 */
-       clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
-                              ARRAY_SIZE(clk_out2_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
-                              &clk_out_lock);
-       clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern2", "clk_out_2");
-       clks[clk_out_2] = clk;
-
-       /* clk_out_3 */
-       clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
-                              ARRAY_SIZE(clk_out3_parents),
-                              CLK_SET_RATE_NO_REPARENT,
-                              pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
-                              &clk_out_lock);
-       clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
-                               pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
-                               &clk_out_lock);
-       clk_register_clkdev(clk, "extern3", "clk_out_3");
-       clks[clk_out_3] = clk;
-
-       /* blink */
-       writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
-       clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
-                               pmc_base + PMC_DPD_PADS_ORIDE,
-                               PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
-       clk = clk_register_gate(NULL, "blink", "blink_override", 0,
-                               pmc_base + PMC_CTRL,
-                               PMC_CTRL_BLINK_ENB, 0, NULL);
-       clk_register_clkdev(clk, "blink", NULL);
-       clks[blink] = clk;
-
+                            CLK_GET_RATE_NOCACHE, &pll_e_params, NULL);
+       clks[TEGRA30_CLK_PLL_E] = clk;
 }
 
 static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
@@ -1332,8 +1044,7 @@ static void __init tegra30_super_clk_init(void)
                                  CLK_SET_RATE_PARENT,
                                  clk_base + CCLKG_BURST_POLICY,
                                  0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "cclk_g", NULL);
-       clks[cclk_g] = clk;
+       clks[TEGRA30_CLK_CCLK_G] = clk;
 
        /*
         * Clock input to cclk_lp divided from pll_p using
@@ -1369,8 +1080,7 @@ static void __init tegra30_super_clk_init(void)
                                  clk_base + CCLKLP_BURST_POLICY,
                                  TEGRA_DIVIDER_2, 4, 8, 9,
                              NULL);
-       clk_register_clkdev(clk, "cclk_lp", NULL);
-       clks[cclk_lp] = clk;
+       clks[TEGRA30_CLK_CCLK_LP] = clk;
 
        /* SCLK */
        clk = tegra_clk_register_super_mux("sclk", sclk_parents,
@@ -1378,142 +1088,44 @@ static void __init tegra30_super_clk_init(void)
                                  CLK_SET_RATE_PARENT,
                                  clk_base + SCLK_BURST_POLICY,
                                  0, 4, 0, 0, NULL);
-       clk_register_clkdev(clk, "sclk", NULL);
-       clks[sclk] = clk;
-
-       /* HCLK */
-       clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
-                                  clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT,
-                               clk_base + SYSTEM_CLK_RATE, 7,
-                               CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "hclk", NULL);
-       clks[hclk] = clk;
-
-       /* PCLK */
-       clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
-                                  clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
-                                  &sysrate_lock);
-       clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT,
-                               clk_base + SYSTEM_CLK_RATE, 3,
-                               CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
-       clk_register_clkdev(clk, "pclk", NULL);
-       clks[pclk] = clk;
+       clks[TEGRA30_CLK_SCLK] = clk;
 
        /* twd */
        clk = clk_register_fixed_factor(NULL, "twd", "cclk_g",
                                        CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "twd", NULL);
-       clks[twd] = clk;
+       clks[TEGRA30_CLK_TWD] = clk;
+
+       tegra_super_clk_gen4_init(clk_base, pmc_base, tegra30_clks, NULL);
 }
 
 static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p",
                                         "clk_m" };
 static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
 static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
-static const char *i2s0_parents[] = { "pll_a_out0", "audio0_2x", "pll_p",
-                                     "clk_m" };
-static const char *i2s1_parents[] = { "pll_a_out0", "audio1_2x", "pll_p",
-                                     "clk_m" };
-static const char *i2s2_parents[] = { "pll_a_out0", "audio2_2x", "pll_p",
-                                     "clk_m" };
-static const char *i2s3_parents[] = { "pll_a_out0", "audio3_2x", "pll_p",
-                                     "clk_m" };
-static const char *i2s4_parents[] = { "pll_a_out0", "audio4_2x", "pll_p",
-                                     "clk_m" };
 static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p",
                                           "clk_m" };
-static const char *spdif_in_parents[] = { "pll_p", "pll_c", "pll_m" };
-static const char *mux_pllpc_clk32k_clkm[] = { "pll_p", "pll_c", "clk_32k",
-                                              "clk_m" };
-static const char *mux_pllpc_clkm_clk32k[] = { "pll_p", "pll_c", "clk_m",
-                                              "clk_32k" };
 static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" };
-static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c",
-                                        "clk_m" };
-static const char *mux_pllp_clkm[] = { "pll_p", "unused", "unused", "clk_m" };
 static const char *mux_pllpmdacd2_clkm[] = { "pll_p", "pll_m", "pll_d_out0",
                                             "pll_a_out0", "pll_c",
                                             "pll_d2_out0", "clk_m" };
-static const char *mux_plla_clk32k_pllp_clkm_plle[] = { "pll_a_out0",
-                                                       "clk_32k", "pll_p",
-                                                       "clk_m", "pll_e" };
 static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0",
                                                  "pll_d2_out0" };
+static const char *pwm_parents[] = { "pll_p", "pll_c", "clk_32k", "clk_m" };
 
 static struct tegra_periph_init_data tegra_periph_clk_list[] = {
-       TEGRA_INIT_DATA_MUX("i2s0",     NULL,           "tegra30-i2s.0",        i2s0_parents,           CLK_SOURCE_I2S0,        30,     &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
-       TEGRA_INIT_DATA_MUX("i2s1",     NULL,           "tegra30-i2s.1",        i2s1_parents,           CLK_SOURCE_I2S1,        11,     &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
-       TEGRA_INIT_DATA_MUX("i2s2",     NULL,           "tegra30-i2s.2",        i2s2_parents,           CLK_SOURCE_I2S2,        18,     &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
-       TEGRA_INIT_DATA_MUX("i2s3",     NULL,           "tegra30-i2s.3",        i2s3_parents,           CLK_SOURCE_I2S3,        101,    &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
-       TEGRA_INIT_DATA_MUX("i2s4",     NULL,           "tegra30-i2s.4",        i2s4_parents,           CLK_SOURCE_I2S4,        102,    &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
-       TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out",   "tegra30-spdif",        spdif_out_parents,      CLK_SOURCE_SPDIF_OUT,   10,     &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
-       TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in",     "tegra30-spdif",        spdif_in_parents,       CLK_SOURCE_SPDIF_IN,    10,     &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
-       TEGRA_INIT_DATA_MUX("d_audio",  "d_audio",      "tegra30-ahub",         mux_pllacp_clkm,        CLK_SOURCE_D_AUDIO,     106,    &periph_v_regs, 0, d_audio),
-       TEGRA_INIT_DATA_MUX("dam0",     NULL,           "tegra30-dam.0",        mux_pllacp_clkm,        CLK_SOURCE_DAM0,        108,    &periph_v_regs, 0, dam0),
-       TEGRA_INIT_DATA_MUX("dam1",     NULL,           "tegra30-dam.1",        mux_pllacp_clkm,        CLK_SOURCE_DAM1,        109,    &periph_v_regs, 0, dam1),
-       TEGRA_INIT_DATA_MUX("dam2",     NULL,           "tegra30-dam.2",        mux_pllacp_clkm,        CLK_SOURCE_DAM2,        110,    &periph_v_regs, 0, dam2),
-       TEGRA_INIT_DATA_MUX("hda",      "hda",          "tegra30-hda",          mux_pllpcm_clkm,        CLK_SOURCE_HDA,         125,    &periph_v_regs, 0, hda),
-       TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda",         mux_pllpcm_clkm,        CLK_SOURCE_HDA2CODEC_2X, 111,   &periph_v_regs, 0, hda2codec_2x),
-       TEGRA_INIT_DATA_MUX("sbc1",     NULL,           "spi_tegra.0",          mux_pllpcm_clkm,        CLK_SOURCE_SBC1,        41,     &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
-       TEGRA_INIT_DATA_MUX("sbc2",     NULL,           "spi_tegra.1",          mux_pllpcm_clkm,        CLK_SOURCE_SBC2,        44,     &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
-       TEGRA_INIT_DATA_MUX("sbc3",     NULL,           "spi_tegra.2",          mux_pllpcm_clkm,        CLK_SOURCE_SBC3,        46,     &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
-       TEGRA_INIT_DATA_MUX("sbc4",     NULL,           "spi_tegra.3",          mux_pllpcm_clkm,        CLK_SOURCE_SBC4,        68,     &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
-       TEGRA_INIT_DATA_MUX("sbc5",     NULL,           "spi_tegra.4",          mux_pllpcm_clkm,        CLK_SOURCE_SBC5,        104,    &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
-       TEGRA_INIT_DATA_MUX("sbc6",     NULL,           "spi_tegra.5",          mux_pllpcm_clkm,        CLK_SOURCE_SBC6,        105,    &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
-       TEGRA_INIT_DATA_MUX("sata_oob", NULL,           "tegra_sata_oob",       mux_pllpcm_clkm,        CLK_SOURCE_SATA_OOB,    123,    &periph_v_regs, TEGRA_PERIPH_ON_APB, sata_oob),
-       TEGRA_INIT_DATA_MUX("sata",     NULL,           "tegra_sata",           mux_pllpcm_clkm,        CLK_SOURCE_SATA,        124,    &periph_v_regs, TEGRA_PERIPH_ON_APB, sata),
-       TEGRA_INIT_DATA_MUX("ndflash",  NULL,           "tegra_nand",           mux_pllpcm_clkm,        CLK_SOURCE_NDFLASH,     13,     &periph_l_regs, TEGRA_PERIPH_ON_APB, ndflash),
-       TEGRA_INIT_DATA_MUX("ndspeed",  NULL,           "tegra_nand_speed",     mux_pllpcm_clkm,        CLK_SOURCE_NDSPEED,     80,     &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
-       TEGRA_INIT_DATA_MUX("vfir",     NULL,           "vfir",                 mux_pllpcm_clkm,        CLK_SOURCE_VFIR,        7,      &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
-       TEGRA_INIT_DATA_MUX("csite",    NULL,           "csite",                mux_pllpcm_clkm,        CLK_SOURCE_CSITE,       73,     &periph_u_regs, TEGRA_PERIPH_ON_APB, csite),
-       TEGRA_INIT_DATA_MUX("la",       NULL,           "la",                   mux_pllpcm_clkm,        CLK_SOURCE_LA,          76,     &periph_u_regs, TEGRA_PERIPH_ON_APB, la),
-       TEGRA_INIT_DATA_MUX("owr",      NULL,           "tegra_w1",             mux_pllpcm_clkm,        CLK_SOURCE_OWR,         71,     &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
-       TEGRA_INIT_DATA_MUX("mipi",     NULL,           "mipi",                 mux_pllpcm_clkm,        CLK_SOURCE_MIPI,        50,     &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
-       TEGRA_INIT_DATA_MUX("tsensor",  NULL,           "tegra-tsensor",        mux_pllpc_clkm_clk32k,  CLK_SOURCE_TSENSOR,     100,    &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
-       TEGRA_INIT_DATA_MUX("i2cslow",  NULL,           "i2cslow",              mux_pllpc_clk32k_clkm,  CLK_SOURCE_I2CSLOW,     81,     &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
-       TEGRA_INIT_DATA_INT("vde",      NULL,           "vde",                  mux_pllpcm_clkm,        CLK_SOURCE_VDE,         61,     &periph_h_regs, 0, vde),
-       TEGRA_INIT_DATA_INT("vi",       "vi",           "tegra_camera",         mux_pllmcpa,            CLK_SOURCE_VI,          20,     &periph_l_regs, 0, vi),
-       TEGRA_INIT_DATA_INT("epp",      NULL,           "epp",                  mux_pllmcpa,            CLK_SOURCE_EPP,         19,     &periph_l_regs, 0, epp),
-       TEGRA_INIT_DATA_INT("mpe",      NULL,           "mpe",                  mux_pllmcpa,            CLK_SOURCE_MPE,         60,     &periph_h_regs, 0, mpe),
-       TEGRA_INIT_DATA_INT("host1x",   NULL,           "host1x",               mux_pllmcpa,            CLK_SOURCE_HOST1X,      28,     &periph_l_regs, 0, host1x),
-       TEGRA_INIT_DATA_INT("3d",       NULL,           "3d",                   mux_pllmcpa,            CLK_SOURCE_3D,          24,     &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d),
-       TEGRA_INIT_DATA_INT("3d2",      NULL,           "3d2",                  mux_pllmcpa,            CLK_SOURCE_3D2,         98,     &periph_v_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d2),
-       TEGRA_INIT_DATA_INT("2d",       NULL,           "2d",                   mux_pllmcpa,            CLK_SOURCE_2D,          21,     &periph_l_regs, 0, gr2d),
-       TEGRA_INIT_DATA_INT("se",       NULL,           "se",                   mux_pllpcm_clkm,        CLK_SOURCE_SE,          127,    &periph_v_regs, 0, se),
-       TEGRA_INIT_DATA_MUX("mselect",  NULL,           "mselect",              mux_pllp_clkm,          CLK_SOURCE_MSELECT,     99,     &periph_v_regs, 0, mselect),
-       TEGRA_INIT_DATA_MUX("nor",      NULL,           "tegra-nor",            mux_pllpcm_clkm,        CLK_SOURCE_NOR,         42,     &periph_h_regs, 0, nor),
-       TEGRA_INIT_DATA_MUX("sdmmc1",   NULL,           "sdhci-tegra.0",        mux_pllpcm_clkm,        CLK_SOURCE_SDMMC1,      14,     &periph_l_regs, 0, sdmmc1),
-       TEGRA_INIT_DATA_MUX("sdmmc2",   NULL,           "sdhci-tegra.1",        mux_pllpcm_clkm,        CLK_SOURCE_SDMMC2,      9,      &periph_l_regs, 0, sdmmc2),
-       TEGRA_INIT_DATA_MUX("sdmmc3",   NULL,           "sdhci-tegra.2",        mux_pllpcm_clkm,        CLK_SOURCE_SDMMC3,      69,     &periph_u_regs, 0, sdmmc3),
-       TEGRA_INIT_DATA_MUX("sdmmc4",   NULL,           "sdhci-tegra.3",        mux_pllpcm_clkm,        CLK_SOURCE_SDMMC4,      15,     &periph_l_regs, 0, sdmmc4),
-       TEGRA_INIT_DATA_MUX("cve",      NULL,           "cve",                  mux_pllpdc_clkm,        CLK_SOURCE_CVE,         49,     &periph_h_regs, 0, cve),
-       TEGRA_INIT_DATA_MUX("tvo",      NULL,           "tvo",                  mux_pllpdc_clkm,        CLK_SOURCE_TVO,         49,     &periph_h_regs, 0, tvo),
-       TEGRA_INIT_DATA_MUX("tvdac",    NULL,           "tvdac",                mux_pllpdc_clkm,        CLK_SOURCE_TVDAC,       53,     &periph_h_regs, 0, tvdac),
-       TEGRA_INIT_DATA_MUX("actmon",   NULL,           "actmon",               mux_pllpc_clk32k_clkm,  CLK_SOURCE_ACTMON,      119,    &periph_v_regs, 0, actmon),
-       TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor",   "tegra_camera",         mux_pllmcpa,            CLK_SOURCE_VI_SENSOR,   20,     &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
-       TEGRA_INIT_DATA_DIV16("i2c1",   "div-clk",      "tegra-i2c.0",          mux_pllp_clkm,          CLK_SOURCE_I2C1,        12,     &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1),
-       TEGRA_INIT_DATA_DIV16("i2c2",   "div-clk",      "tegra-i2c.1",          mux_pllp_clkm,          CLK_SOURCE_I2C2,        54,     &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2),
-       TEGRA_INIT_DATA_DIV16("i2c3",   "div-clk",      "tegra-i2c.2",          mux_pllp_clkm,          CLK_SOURCE_I2C3,        67,     &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3),
-       TEGRA_INIT_DATA_DIV16("i2c4",   "div-clk",      "tegra-i2c.3",          mux_pllp_clkm,          CLK_SOURCE_I2C4,        103,    &periph_v_regs, TEGRA_PERIPH_ON_APB, i2c4),
-       TEGRA_INIT_DATA_DIV16("i2c5",   "div-clk",      "tegra-i2c.4",          mux_pllp_clkm,          CLK_SOURCE_I2C5,        47,     &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c5),
-       TEGRA_INIT_DATA_UART("uarta",   NULL,           "tegra_uart.0",         mux_pllpcm_clkm,        CLK_SOURCE_UARTA,       6,      &periph_l_regs, uarta),
-       TEGRA_INIT_DATA_UART("uartb",   NULL,           "tegra_uart.1",         mux_pllpcm_clkm,        CLK_SOURCE_UARTB,       7,      &periph_l_regs, uartb),
-       TEGRA_INIT_DATA_UART("uartc",   NULL,           "tegra_uart.2",         mux_pllpcm_clkm,        CLK_SOURCE_UARTC,       55,     &periph_h_regs, uartc),
-       TEGRA_INIT_DATA_UART("uartd",   NULL,           "tegra_uart.3",         mux_pllpcm_clkm,        CLK_SOURCE_UARTD,       65,     &periph_u_regs, uartd),
-       TEGRA_INIT_DATA_UART("uarte",   NULL,           "tegra_uart.4",         mux_pllpcm_clkm,        CLK_SOURCE_UARTE,       66,     &periph_u_regs, uarte),
-       TEGRA_INIT_DATA_MUX8("hdmi",    NULL,           "hdmi",                 mux_pllpmdacd2_clkm,    CLK_SOURCE_HDMI,        51,     &periph_h_regs, 0, hdmi),
-       TEGRA_INIT_DATA_MUX8("extern1", NULL,           "extern1",              mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1,     120,    &periph_v_regs, 0, extern1),
-       TEGRA_INIT_DATA_MUX8("extern2", NULL,           "extern2",              mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2,     121,    &periph_v_regs, 0, extern2),
-       TEGRA_INIT_DATA_MUX8("extern3", NULL,           "extern3",              mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3,     122,    &periph_v_regs, 0, extern3),
-       TEGRA_INIT_DATA("pwm",          NULL,           "pwm",                  mux_pllpc_clk32k_clkm,  CLK_SOURCE_PWM,         28, 2, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, 0, pwm),
+       TEGRA_INIT_DATA_MUX("spdif_out", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_SPDIF_OUT),
+       TEGRA_INIT_DATA_MUX("d_audio", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, 0, TEGRA30_CLK_D_AUDIO),
+       TEGRA_INIT_DATA_MUX("dam0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, TEGRA30_CLK_DAM0),
+       TEGRA_INIT_DATA_MUX("dam1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, TEGRA30_CLK_DAM1),
+       TEGRA_INIT_DATA_MUX("dam2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, TEGRA30_CLK_DAM2),
+       TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2),
+       TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE),
+       TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI),
+       TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_PWM),
 };
 
 static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
-       TEGRA_INIT_DATA_NODIV("disp1",  NULL, "tegradc.0", mux_pllpmdacd2_clkm,      CLK_SOURCE_DISP1,  29, 3, 27, &periph_l_regs, 0, disp1),
-       TEGRA_INIT_DATA_NODIV("disp2",  NULL, "tegradc.1", mux_pllpmdacd2_clkm,      CLK_SOURCE_DISP2,  29, 3, 26, &periph_l_regs, 0, disp2),
-       TEGRA_INIT_DATA_NODIV("dsib",   NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB,   25, 1, 82, &periph_u_regs, 0, dsib),
+       TEGRA_INIT_DATA_NODIV("dsib", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, 0, TEGRA30_CLK_DSIB),
 };
 
 static void __init tegra30_periph_clk_init(void)
@@ -1522,170 +1134,20 @@ static void __init tegra30_periph_clk_init(void)
        struct clk *clk;
        int i;
 
-       /* apbdma */
-       clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34,
-                                   &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-apbdma");
-       clks[apbdma] = clk;
-
-       /* rtc */
-       clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
-                                   TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 4, &periph_l_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "rtc-tegra");
-       clks[rtc] = clk;
-
-       /* timer */
-       clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0,
-                                   5, &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "timer");
-       clks[timer] = clk;
-
-       /* kbc */
-       clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
-                                   TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 36, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-kbc");
-       clks[kbc] = clk;
-
-       /* csus */
-       clk = tegra_clk_register_periph_gate("csus", "clk_m",
-                                   TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 92, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "csus", "tengra_camera");
-       clks[csus] = clk;
-
-       /* vcp */
-       clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29,
-                                   &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "vcp", "tegra-avp");
-       clks[vcp] = clk;
-
-       /* bsea */
-       clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0,
-                                   62, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "bsea", "tegra-avp");
-       clks[bsea] = clk;
-
-       /* bsev */
-       clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0,
-                                   63, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "bsev", "tegra-aes");
-       clks[bsev] = clk;
-
-       /* usbd */
-       clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0,
-                                   22, &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "fsl-tegra-udc");
-       clks[usbd] = clk;
-
-       /* usb2 */
-       clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0,
-                                   58, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-ehci.1");
-       clks[usb2] = clk;
-
-       /* usb3 */
-       clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0,
-                                   59, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra-ehci.2");
-       clks[usb3] = clk;
-
        /* dsia */
        clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base,
-                                   0, 48, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "dsia", "tegradc.0");
-       clks[dsia] = clk;
-
-       /* csi */
-       clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
-                                   0, 52, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "csi", "tegra_camera");
-       clks[csi] = clk;
-
-       /* isp */
-       clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23,
-                                   &periph_l_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "isp", "tegra_camera");
-       clks[isp] = clk;
+                                   0, 48, periph_clk_enb_refcnt);
+       clks[TEGRA30_CLK_DSIA] = clk;
 
        /* pcie */
        clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0,
-                                   70, &periph_u_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "pcie", "tegra-pcie");
-       clks[pcie] = clk;
+                                   70, periph_clk_enb_refcnt);
+       clks[TEGRA30_CLK_PCIE] = clk;
 
        /* afi */
        clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72,
-                                   &periph_u_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "afi", "tegra-pcie");
-       clks[afi] = clk;
-
-       /* pciex */
-       clk = tegra_clk_register_periph_gate("pciex", "pll_e", 0, clk_base, 0,
-                                   74, &periph_u_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "pciex", "tegra-pcie");
-       clks[pciex] = clk;
-
-       /* kfuse */
-       clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 40, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "kfuse-tegra");
-       clks[kfuse] = clk;
-
-       /* fuse */
-       clk = tegra_clk_register_periph_gate("fuse", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 39, &periph_h_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "fuse", "fuse-tegra");
-       clks[fuse] = clk;
-
-       /* fuse_burn */
-       clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 39, &periph_h_regs,
                                    periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "fuse_burn", "fuse-tegra");
-       clks[fuse_burn] = clk;
-
-       /* apbif */
-       clk = tegra_clk_register_periph_gate("apbif", "clk_m", 0,
-                                   clk_base, 0, 107, &periph_v_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "apbif", "tegra30-ahub");
-       clks[apbif] = clk;
-
-       /* hda2hdmi */
-       clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 128, &periph_w_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda");
-       clks[hda2hdmi] = clk;
-
-       /* sata_cold */
-       clk = tegra_clk_register_periph_gate("sata_cold", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 129, &periph_w_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "tegra_sata_cold");
-       clks[sata_cold] = clk;
-
-       /* dtv */
-       clk = tegra_clk_register_periph_gate("dtv", "clk_m",
-                                   TEGRA_PERIPH_ON_APB,
-                                   clk_base, 0, 79, &periph_u_regs,
-                                   periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, NULL, "dtv");
-       clks[dtv] = clk;
+       clks[TEGRA30_CLK_AFI] = clk;
 
        /* emc */
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
@@ -1694,84 +1156,37 @@ static void __init tegra30_periph_clk_init(void)
                               clk_base + CLK_SOURCE_EMC,
                               30, 2, 0, NULL);
        clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
-                                   57, &periph_h_regs, periph_clk_enb_refcnt);
-       clk_register_clkdev(clk, "emc", NULL);
-       clks[emc] = clk;
+                                   57, periph_clk_enb_refcnt);
+       clks[TEGRA30_CLK_EMC] = clk;
+
+       /* cml0 */
+       clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
+                               0, 0, &cml_lock);
+       clks[TEGRA30_CLK_CML0] = clk;
+
+       /* cml1 */
+       clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX,
+                               1, 0, &cml_lock);
+       clks[TEGRA30_CLK_CML1] = clk;
 
        for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
                data = &tegra_periph_clk_list[i];
-               clk = tegra_clk_register_periph(data->name, data->parent_names,
+               clk = tegra_clk_register_periph(data->name, data->p.parent_names,
                                data->num_parents, &data->periph,
                                clk_base, data->offset, data->flags);
-               clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
 
        for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
                data = &tegra_periph_nodiv_clk_list[i];
                clk = tegra_clk_register_periph_nodiv(data->name,
-                                       data->parent_names,
+                                       data->p.parent_names,
                                        data->num_parents, &data->periph,
                                        clk_base, data->offset);
-               clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
-}
-
-static void __init tegra30_fixed_clk_init(void)
-{
-       struct clk *clk;
-
-       /* clk_32k */
-       clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
-                               32768);
-       clk_register_clkdev(clk, "clk_32k", NULL);
-       clks[clk_32k] = clk;
 
-       /* clk_m_div2 */
-       clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
-                               CLK_SET_RATE_PARENT, 1, 2);
-       clk_register_clkdev(clk, "clk_m_div2", NULL);
-       clks[clk_m_div2] = clk;
-
-       /* clk_m_div4 */
-       clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
-                               CLK_SET_RATE_PARENT, 1, 4);
-       clk_register_clkdev(clk, "clk_m_div4", NULL);
-       clks[clk_m_div4] = clk;
-
-       /* cml0 */
-       clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
-                               0, 0, &cml_lock);
-       clk_register_clkdev(clk, "cml0", NULL);
-       clks[cml0] = clk;
-
-       /* cml1 */
-       clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX,
-                               1, 0, &cml_lock);
-       clk_register_clkdev(clk, "cml1", NULL);
-       clks[cml1] = clk;
-}
-
-static void __init tegra30_osc_clk_init(void)
-{
-       struct clk *clk;
-       unsigned int pll_ref_div;
-
-       tegra30_clk_measure_input_freq();
-
-       /* clk_m */
-       clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
-                               input_freq);
-       clk_register_clkdev(clk, "clk_m", NULL);
-       clks[clk_m] = clk;
-
-       /* pll_ref */
-       pll_ref_div = tegra30_get_pll_ref_div();
-       clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
-                               CLK_SET_RATE_PARENT, 1, pll_ref_div);
-       clk_register_clkdev(clk, "pll_ref", NULL);
-       clks[pll_ref] = clk;
+       tegra_periph_clk_init(clk_base, pmc_base, tegra30_clks, &pll_p_params);
 }
 
 /* Tegra30 CPU clock and reset control functions */
@@ -1913,48 +1328,49 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
 };
 
 static struct tegra_clk_init_table init_table[] __initdata = {
-       {uarta, pll_p, 408000000, 0},
-       {uartb, pll_p, 408000000, 0},
-       {uartc, pll_p, 408000000, 0},
-       {uartd, pll_p, 408000000, 0},
-       {uarte, pll_p, 408000000, 0},
-       {pll_a, clk_max, 564480000, 1},
-       {pll_a_out0, clk_max, 11289600, 1},
-       {extern1, pll_a_out0, 0, 1},
-       {clk_out_1_mux, extern1, 0, 0},
-       {clk_out_1, clk_max, 0, 1},
-       {blink, clk_max, 0, 1},
-       {i2s0, pll_a_out0, 11289600, 0},
-       {i2s1, pll_a_out0, 11289600, 0},
-       {i2s2, pll_a_out0, 11289600, 0},
-       {i2s3, pll_a_out0, 11289600, 0},
-       {i2s4, pll_a_out0, 11289600, 0},
-       {sdmmc1, pll_p, 48000000, 0},
-       {sdmmc2, pll_p, 48000000, 0},
-       {sdmmc3, pll_p, 48000000, 0},
-       {pll_m, clk_max, 0, 1},
-       {pclk, clk_max, 0, 1},
-       {csite, clk_max, 0, 1},
-       {emc, clk_max, 0, 1},
-       {mselect, clk_max, 0, 1},
-       {sbc1, pll_p, 100000000, 0},
-       {sbc2, pll_p, 100000000, 0},
-       {sbc3, pll_p, 100000000, 0},
-       {sbc4, pll_p, 100000000, 0},
-       {sbc5, pll_p, 100000000, 0},
-       {sbc6, pll_p, 100000000, 0},
-       {host1x, pll_c, 150000000, 0},
-       {disp1, pll_p, 600000000, 0},
-       {disp2, pll_p, 600000000, 0},
-       {twd, clk_max, 0, 1},
-       {gr2d, pll_c, 300000000, 0},
-       {gr3d, pll_c, 300000000, 0},
-       {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+       {TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0},
+       {TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0},
+       {TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0},
+       {TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0},
+       {TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0},
+       {TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1},
+       {TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1},
+       {TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1},
+       {TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0},
+       {TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0},
+       {TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0},
+       {TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0},
+       {TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0},
+       {TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0},
+       {TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0},
+       {TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0},
+       {TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0},
+       {TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1},
+       {TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0},
+       {TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0},
+       {TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0},
+       {TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry. */
 };
 
 static void __init tegra30_clock_apply_init_table(void)
 {
-       tegra_init_from_table(init_table, clks, clk_max);
+       tegra_init_from_table(init_table, clks, TEGRA30_CLK_CLK_MAX);
 }
 
 /*
@@ -1963,19 +1379,18 @@ static void __init tegra30_clock_apply_init_table(void)
  * table under two names.
  */
 static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
-       TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL),
-       TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL),
-       TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL),
-       TEGRA_CLK_DUPLICATE(bsev, "tegra-avp", "bsev"),
-       TEGRA_CLK_DUPLICATE(bsev, "nvavp", "bsev"),
-       TEGRA_CLK_DUPLICATE(vde, "tegra-aes", "vde"),
-       TEGRA_CLK_DUPLICATE(bsea, "tegra-aes", "bsea"),
-       TEGRA_CLK_DUPLICATE(bsea, "nvavp", "bsea"),
-       TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL),
-       TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"),
-       TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"),
-       TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"),
-       TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "utmip-pad", NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "tegra-ehci.0", NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "tegra-otg", NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEV, "tegra-avp", "bsev"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEV, "nvavp", "bsev"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VDE, "tegra-aes", "vde"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEA, "tegra-aes", "bsea"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEA, "nvavp", "bsea"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML1, "tegra_sata_cml", NULL),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML0, "tegra_pcie", "cml"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VCP, "nvavp", "vcp"),
+       TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), /* MUST be the last entry */
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
@@ -1986,7 +1401,6 @@ static const struct of_device_id pmc_match[] __initconst = {
 static void __init tegra30_clock_init(struct device_node *np)
 {
        struct device_node *node;
-       int i;
 
        clk_base = of_iomap(np, 0);
        if (!clk_base) {
@@ -2006,29 +1420,27 @@ static void __init tegra30_clock_init(struct device_node *np)
                BUG();
        }
 
-       tegra30_osc_clk_init();
-       tegra30_fixed_clk_init();
+       clks = tegra_clk_init(clk_base, TEGRA30_CLK_CLK_MAX,
+                               TEGRA30_CLK_PERIPH_BANKS);
+       if (!clks)
+               return;
+
+       if (tegra_osc_clk_init(clk_base, tegra30_clks, tegra30_input_freq,
+               ARRAY_SIZE(tegra30_input_freq), &input_freq, NULL) < 0)
+               return;
+
+
+       tegra_fixed_clk_init(tegra30_clks);
        tegra30_pll_init();
        tegra30_super_clk_init();
        tegra30_periph_clk_init();
-       tegra30_audio_clk_init();
-       tegra30_pmc_clk_init();
-
-       for (i = 0; i < ARRAY_SIZE(clks); i++) {
-               if (IS_ERR(clks[i])) {
-                       pr_err("Tegra30 clk %d: register failed with %ld\n",
-                              i, PTR_ERR(clks[i]));
-                       BUG();
-               }
-               if (!clks[i])
-                       clks[i] = ERR_PTR(-EINVAL);
-       }
+       tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks, &pll_a_params);
+       tegra_pmc_clk_init(pmc_base, tegra30_clks);
 
-       tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max);
+       tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
 
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       tegra_add_of_provider(np);
+       tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
        tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
 
index 86581ac1fd6985ffcae150aa0737521c3edbd5a5..c0a7d77235105472d225d6f528c81e675866fd3c 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/clk/tegra.h>
+#include <linux/reset-controller.h>
+#include <linux/tegra-soc.h>
 
 #include "clk.h"
 
+#define CLK_OUT_ENB_L                  0x010
+#define CLK_OUT_ENB_H                  0x014
+#define CLK_OUT_ENB_U                  0x018
+#define CLK_OUT_ENB_V                  0x360
+#define CLK_OUT_ENB_W                  0x364
+#define CLK_OUT_ENB_X                  0x280
+#define CLK_OUT_ENB_SET_L              0x320
+#define CLK_OUT_ENB_CLR_L              0x324
+#define CLK_OUT_ENB_SET_H              0x328
+#define CLK_OUT_ENB_CLR_H              0x32c
+#define CLK_OUT_ENB_SET_U              0x330
+#define CLK_OUT_ENB_CLR_U              0x334
+#define CLK_OUT_ENB_SET_V              0x440
+#define CLK_OUT_ENB_CLR_V              0x444
+#define CLK_OUT_ENB_SET_W              0x448
+#define CLK_OUT_ENB_CLR_W              0x44c
+#define CLK_OUT_ENB_SET_X              0x284
+#define CLK_OUT_ENB_CLR_X              0x288
+
+#define RST_DEVICES_L                  0x004
+#define RST_DEVICES_H                  0x008
+#define RST_DEVICES_U                  0x00C
+#define RST_DFLL_DVCO                  0x2F4
+#define RST_DEVICES_V                  0x358
+#define RST_DEVICES_W                  0x35C
+#define RST_DEVICES_X                  0x28C
+#define RST_DEVICES_SET_L              0x300
+#define RST_DEVICES_CLR_L              0x304
+#define RST_DEVICES_SET_H              0x308
+#define RST_DEVICES_CLR_H              0x30c
+#define RST_DEVICES_SET_U              0x310
+#define RST_DEVICES_CLR_U              0x314
+#define RST_DEVICES_SET_V              0x430
+#define RST_DEVICES_CLR_V              0x434
+#define RST_DEVICES_SET_W              0x438
+#define RST_DEVICES_CLR_W              0x43c
+#define RST_DEVICES_SET_X              0x290
+#define RST_DEVICES_CLR_X              0x294
+
 /* Global data of Tegra CPU CAR ops */
 static struct tegra_cpu_car_ops dummy_car_ops;
 struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
 
+int *periph_clk_enb_refcnt;
+static int periph_banks;
+static struct clk **clks;
+static int clk_num;
+static struct clk_onecell_data clk_data;
+
+static struct tegra_clk_periph_regs periph_regs[] = {
+       [0] = {
+               .enb_reg = CLK_OUT_ENB_L,
+               .enb_set_reg = CLK_OUT_ENB_SET_L,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_L,
+               .rst_reg = RST_DEVICES_L,
+               .rst_set_reg = RST_DEVICES_SET_L,
+               .rst_clr_reg = RST_DEVICES_CLR_L,
+       },
+       [1] = {
+               .enb_reg = CLK_OUT_ENB_H,
+               .enb_set_reg = CLK_OUT_ENB_SET_H,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_H,
+               .rst_reg = RST_DEVICES_H,
+               .rst_set_reg = RST_DEVICES_SET_H,
+               .rst_clr_reg = RST_DEVICES_CLR_H,
+       },
+       [2] = {
+               .enb_reg = CLK_OUT_ENB_U,
+               .enb_set_reg = CLK_OUT_ENB_SET_U,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_U,
+               .rst_reg = RST_DEVICES_U,
+               .rst_set_reg = RST_DEVICES_SET_U,
+               .rst_clr_reg = RST_DEVICES_CLR_U,
+       },
+       [3] = {
+               .enb_reg = CLK_OUT_ENB_V,
+               .enb_set_reg = CLK_OUT_ENB_SET_V,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_V,
+               .rst_reg = RST_DEVICES_V,
+               .rst_set_reg = RST_DEVICES_SET_V,
+               .rst_clr_reg = RST_DEVICES_CLR_V,
+       },
+       [4] = {
+               .enb_reg = CLK_OUT_ENB_W,
+               .enb_set_reg = CLK_OUT_ENB_SET_W,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_W,
+               .rst_reg = RST_DEVICES_W,
+               .rst_set_reg = RST_DEVICES_SET_W,
+               .rst_clr_reg = RST_DEVICES_CLR_W,
+       },
+       [5] = {
+               .enb_reg = CLK_OUT_ENB_X,
+               .enb_set_reg = CLK_OUT_ENB_SET_X,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_X,
+               .rst_reg = RST_DEVICES_X,
+               .rst_set_reg = RST_DEVICES_SET_X,
+               .rst_clr_reg = RST_DEVICES_CLR_X,
+       },
+};
+
+static void __iomem *clk_base;
+
+static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
+               unsigned long id)
+{
+       /*
+        * If peripheral is on the APB bus then we must read the APB bus to
+        * flush the write operation in apb bus. This will avoid peripheral
+        * access after disabling clock. Since the reset driver has no
+        * knowledge of which reset IDs represent which devices, simply do
+        * this all the time.
+        */
+       tegra_read_chipid();
+
+       writel_relaxed(BIT(id % 32),
+                       clk_base + periph_regs[id / 32].rst_set_reg);
+
+       return 0;
+}
+
+static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
+               unsigned long id)
+{
+       writel_relaxed(BIT(id % 32),
+                       clk_base + periph_regs[id / 32].rst_clr_reg);
+
+       return 0;
+}
+
+struct tegra_clk_periph_regs *get_reg_bank(int clkid)
+{
+       int reg_bank = clkid / 32;
+
+       if (reg_bank < periph_banks)
+               return &periph_regs[reg_bank];
+       else {
+               WARN_ON(1);
+               return NULL;
+       }
+}
+
+struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
+{
+       clk_base = regs;
+
+       if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
+               return NULL;
+
+       periph_clk_enb_refcnt = kzalloc(32 * banks *
+                               sizeof(*periph_clk_enb_refcnt), GFP_KERNEL);
+       if (!periph_clk_enb_refcnt)
+               return NULL;
+
+       periph_banks = banks;
+
+       clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL);
+       if (!clks)
+               kfree(periph_clk_enb_refcnt);
+
+       clk_num = num;
+
+       return clks;
+}
+
 void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
                                struct clk *clks[], int clk_max)
 {
@@ -74,6 +236,58 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
        }
 }
 
+static struct reset_control_ops rst_ops = {
+       .assert = tegra_clk_rst_assert,
+       .deassert = tegra_clk_rst_deassert,
+};
+
+static struct reset_controller_dev rst_ctlr = {
+       .ops = &rst_ops,
+       .owner = THIS_MODULE,
+       .of_reset_n_cells = 1,
+};
+
+void __init tegra_add_of_provider(struct device_node *np)
+{
+       int i;
+
+       for (i = 0; i < clk_num; i++) {
+               if (IS_ERR(clks[i])) {
+                       pr_err
+                           ("Tegra clk %d: register failed with %ld\n",
+                            i, PTR_ERR(clks[i]));
+               }
+               if (!clks[i])
+                       clks[i] = ERR_PTR(-EINVAL);
+       }
+
+       clk_data.clks = clks;
+       clk_data.clk_num = clk_num;
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       rst_ctlr.of_node = np;
+       rst_ctlr.nr_resets = clk_num * 32;
+       reset_controller_register(&rst_ctlr);
+}
+
+void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++, dev_clks++)
+               clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
+                               dev_clks->dev_id);
+}
+
+struct clk ** __init tegra_lookup_dt_id(int clk_id,
+                                       struct tegra_clk *tegra_clk)
+{
+       if (tegra_clk[clk_id].present)
+               return &clks[tegra_clk[clk_id].dt_id];
+       else
+               return NULL;
+}
+
 tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
 
 void __init tegra_clocks_apply_init_table(void)
index 07cfacd91686b949f75bedeb6cc0bcb4c0ff0c54..16ec8d6bb87f287724ff53a362b8c39de2880193 100644 (file)
@@ -37,6 +37,8 @@ struct tegra_clk_sync_source {
        container_of(_hw, struct tegra_clk_sync_source, hw)
 
 extern const struct clk_ops tegra_clk_sync_source_ops;
+extern int *periph_clk_enb_refcnt;
+
 struct clk *tegra_clk_register_sync_source(const char *name,
                unsigned long fixed_rate, unsigned long max_rate);
 
@@ -188,12 +190,15 @@ struct tegra_clk_pll_params {
        u32             ext_misc_reg[3];
        u32             pmc_divnm_reg;
        u32             pmc_divp_reg;
+       u32             flags;
        int             stepa_shift;
        int             stepb_shift;
        int             lock_delay;
        int             max_p;
        struct pdiv_map *pdiv_tohw;
        struct div_nmp  *div_nmp;
+       struct tegra_clk_pll_freq_table *freq_table;
+       unsigned long   fixed_rate;
 };
 
 /**
@@ -233,10 +238,7 @@ struct tegra_clk_pll {
        struct clk_hw   hw;
        void __iomem    *clk_base;
        void __iomem    *pmc;
-       u32             flags;
-       unsigned long   fixed_rate;
        spinlock_t      *lock;
-       struct tegra_clk_pll_freq_table *freq_table;
        struct tegra_clk_pll_params     *params;
 };
 
@@ -258,56 +260,49 @@ extern const struct clk_ops tegra_clk_pll_ops;
 extern const struct clk_ops tegra_clk_plle_ops;
 struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+               unsigned long flags, struct tegra_clk_pll_params *pll_params,
+               spinlock_t *lock);
 
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+               unsigned long flags, struct tegra_clk_pll_params *pll_params,
+               spinlock_t *lock);
 
 struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
                            void __iomem *clk_base, void __iomem *pmc,
-                           unsigned long flags, unsigned long fixed_rate,
+                           unsigned long flags,
                            struct tegra_clk_pll_params *pll_params,
-                           u32 pll_flags,
-                           struct tegra_clk_pll_freq_table *freq_table,
                            spinlock_t *lock);
 
 struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
                           void __iomem *clk_base, void __iomem *pmc,
-                          unsigned long flags, unsigned long fixed_rate,
+                          unsigned long flags,
                           struct tegra_clk_pll_params *pll_params,
-                          u32 pll_flags,
-                          struct tegra_clk_pll_freq_table *freq_table,
                           spinlock_t *lock);
 
 struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
                           void __iomem *clk_base, void __iomem *pmc,
-                          unsigned long flags, unsigned long fixed_rate,
+                          unsigned long flags,
                           struct tegra_clk_pll_params *pll_params,
-                          u32 pll_flags,
-                          struct tegra_clk_pll_freq_table *freq_table,
                           spinlock_t *lock);
 
 struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
                           void __iomem *clk_base, void __iomem *pmc,
-                          unsigned long flags, unsigned long fixed_rate,
+                          unsigned long flags,
                           struct tegra_clk_pll_params *pll_params,
-                          u32 pll_flags,
-                          struct tegra_clk_pll_freq_table *freq_table,
                           spinlock_t *lock, unsigned long parent_rate);
 
 struct clk *tegra_clk_register_plle_tegra114(const char *name,
                                const char *parent_name,
                                void __iomem *clk_base, unsigned long flags,
-                               unsigned long fixed_rate,
                                struct tegra_clk_pll_params *pll_params,
-                               struct tegra_clk_pll_freq_table *freq_table,
                                spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
+                          void __iomem *clk_base, unsigned long flags,
+                          struct tegra_clk_pll_params *pll_params,
+                          spinlock_t *lock);
+
 /**
  * struct tegra_clk_pll_out - PLL divider down clock
  *
@@ -395,13 +390,13 @@ struct tegra_clk_periph_gate {
 #define TEGRA_PERIPH_MANUAL_RESET BIT(1)
 #define TEGRA_PERIPH_ON_APB BIT(2)
 #define TEGRA_PERIPH_WAR_1005168 BIT(3)
+#define TEGRA_PERIPH_NO_DIV BIT(4)
+#define TEGRA_PERIPH_NO_GATE BIT(5)
 
-void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
 extern const struct clk_ops tegra_clk_periph_gate_ops;
 struct clk *tegra_clk_register_periph_gate(const char *name,
                const char *parent_name, u8 gate_flags, void __iomem *clk_base,
-               unsigned long flags, int clk_num,
-               struct tegra_clk_periph_regs *pregs, int *enable_refcnt);
+               unsigned long flags, int clk_num, int *enable_refcnt);
 
 /**
  * struct clk-periph - peripheral clock
@@ -443,26 +438,26 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
 
 #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags,            \
                         _div_shift, _div_width, _div_frac_width,       \
-                        _div_flags, _clk_num, _enb_refcnt, _regs,      \
-                        _gate_flags, _table)                           \
+                        _div_flags, _clk_num,\
+                        _gate_flags, _table, _lock)                    \
        {                                                               \
                .mux = {                                                \
                        .flags = _mux_flags,                            \
                        .shift = _mux_shift,                            \
                        .mask = _mux_mask,                              \
                        .table = _table,                                \
+                       .lock = _lock,                                  \
                },                                                      \
                .divider = {                                            \
                        .flags = _div_flags,                            \
                        .shift = _div_shift,                            \
                        .width = _div_width,                            \
                        .frac_width = _div_frac_width,                  \
+                       .lock = _lock,                                  \
                },                                                      \
                .gate = {                                               \
                        .flags = _gate_flags,                           \
                        .clk_num = _clk_num,                            \
-                       .enable_refcnt = _enb_refcnt,                   \
-                       .regs = _regs,                                  \
                },                                                      \
                .mux_ops = &clk_mux_ops,                                \
                .div_ops = &tegra_clk_frac_div_ops,                     \
@@ -472,7 +467,10 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
 struct tegra_periph_init_data {
        const char *name;
        int clk_id;
-       const char **parent_names;
+       union {
+               const char **parent_names;
+               const char *parent_name;
+       } p;
        int num_parents;
        struct tegra_clk_periph periph;
        u32 offset;
@@ -483,20 +481,19 @@ struct tegra_periph_init_data {
 
 #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
                        _mux_shift, _mux_mask, _mux_flags, _div_shift,  \
-                       _div_width, _div_frac_width, _div_flags, _regs, \
-                       _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
-                       _flags) \
+                       _div_width, _div_frac_width, _div_flags,        \
+                       _clk_num, _gate_flags, _clk_id, _table,         \
+                       _flags, _lock) \
        {                                                               \
                .name = _name,                                          \
                .clk_id = _clk_id,                                      \
-               .parent_names = _parent_names,                          \
+               .p.parent_names = _parent_names,                        \
                .num_parents = ARRAY_SIZE(_parent_names),               \
                .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask,       \
                                           _mux_flags, _div_shift,      \
                                           _div_width, _div_frac_width, \
                                           _div_flags, _clk_num,        \
-                                          _enb_refcnt, _regs,          \
-                                          _gate_flags, _table),        \
+                                          _gate_flags, _table, _lock), \
                .offset = _offset,                                      \
                .con_id = _con_id,                                      \
                .dev_id = _dev_id,                                      \
@@ -505,13 +502,13 @@ struct tegra_periph_init_data {
 
 #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
                        _mux_shift, _mux_width, _mux_flags, _div_shift, \
-                       _div_width, _div_frac_width, _div_flags, _regs, \
-                       _clk_num, _enb_refcnt, _gate_flags, _clk_id)    \
+                       _div_width, _div_frac_width, _div_flags, \
+                       _clk_num, _gate_flags, _clk_id) \
        TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
                        _mux_shift, BIT(_mux_width) - 1, _mux_flags,    \
                        _div_shift, _div_width, _div_frac_width, _div_flags, \
-                       _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
-                       NULL, 0)
+                       _clk_num, _gate_flags, _clk_id,\
+                       NULL, 0, NULL)
 
 /**
  * struct clk_super_mux - super clock
@@ -581,12 +578,49 @@ struct tegra_clk_duplicate {
                },                              \
        }
 
+struct tegra_clk {
+       int                     dt_id;
+       bool                    present;
+};
+
+struct tegra_devclk {
+       int             dt_id;
+       char            *dev_id;
+       char            *con_id;
+};
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
                struct clk *clks[], int clk_max);
 
 void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
                struct clk *clks[], int clk_max);
 
+struct tegra_clk_periph_regs *get_reg_bank(int clkid);
+struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
+
+struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
+
+void tegra_add_of_provider(struct device_node *np);
+void tegra_register_devclks(struct tegra_devclk *dev_clks, int num);
+
+void tegra_audio_clk_init(void __iomem *clk_base,
+                       void __iomem *pmc_base, struct tegra_clk *tegra_clks,
+                       struct tegra_clk_pll_params *pll_params);
+
+void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
+                       struct tegra_clk *tegra_clks,
+                       struct tegra_clk_pll_params *pll_params);
+
+void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
+void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
+int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks,
+                               unsigned long *input_freqs, int num,
+                               unsigned long *osc_freq,
+                               unsigned long *pll_ref_freq);
+void tegra_super_clk_gen4_init(void __iomem *clk_base,
+                       void __iomem *pmc_base, struct tegra_clk *tegra_clks,
+                       struct tegra_clk_pll_params *pll_params);
+
 void tegra114_clock_tune_cpu_trimmers_high(void);
 void tegra114_clock_tune_cpu_trimmers_low(void);
 void tegra114_clock_tune_cpu_trimmers_init(void);
index 16d7b4ac94be21210779cd7c87d9440a78666162..8d19f7c06010c364ff6ee758c15096c252f9f4bd 100644 (file)
@@ -839,9 +839,6 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
 
        /* set default policy */
        ret = cpufreq_set_policy(policy, &new_policy);
-       policy->user_policy.policy = policy->policy;
-       policy->user_policy.governor = policy->governor;
-
        if (ret) {
                pr_debug("setting policy failed\n");
                if (cpufreq_driver->exit)
@@ -1016,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       if (frozen)
-               /* Restore the saved policy when doing light-weight init */
-               policy = cpufreq_policy_restore(cpu);
-       else
+       /*
+        * Restore the saved policy when doing light-weight init and fall back
+        * to the full init if that fails.
+        */
+       policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
+       if (!policy) {
+               frozen = false;
                policy = cpufreq_policy_alloc();
-
-       if (!policy)
-               goto nomem_out;
-
+               if (!policy)
+                       goto nomem_out;
+       }
 
        /*
         * In the resume path, since we restore a saved policy, the assignment
@@ -1069,8 +1068,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
         */
        cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
-       policy->user_policy.min = policy->min;
-       policy->user_policy.max = policy->max;
+       if (!frozen) {
+               policy->user_policy.min = policy->min;
+               policy->user_policy.max = policy->max;
+       }
 
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                     CPUFREQ_START, policy);
@@ -1101,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 
        cpufreq_init_policy(policy);
 
+       if (!frozen) {
+               policy->user_policy.policy = policy->policy;
+               policy->user_policy.governor = policy->governor;
+       }
+
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        up_read(&cpufreq_rwsem);
 
@@ -1118,8 +1124,11 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
-       if (frozen)
+       if (frozen) {
+               /* Do not leave stale fallback data behind. */
+               per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
                cpufreq_policy_put_kobj(policy);
+       }
        cpufreq_policy_free(policy);
 
 nomem_out:
index 5f1cbae369611062c18ee50982ffa5c6f724d30f..d51f17ed691e023196bbd7e56a3341d4025ce092 100644 (file)
@@ -581,7 +581,8 @@ static void intel_pstate_timer_func(unsigned long __data)
 }
 
 #define ICPU(model, policy) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
+       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
+                       (unsigned long)&policy }
 
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, core_params),
@@ -614,6 +615,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu = all_cpu_data[cpunum];
 
        intel_pstate_get_cpu_pstates(cpu);
+       if (!cpu->pstate.current_pstate) {
+               all_cpu_data[cpunum] = NULL;
+               kfree(cpu);
+               return -ENODATA;
+       }
 
        cpu->cpu = cpunum;
 
index 36795639df0da2d828c784b61c82a728037f6e1c..6e51114057d0963605ef1dfc80b231946e1b88f7 100644 (file)
@@ -65,7 +65,7 @@ static struct cpuidle_driver calxeda_idle_driver = {
        .state_count = 2,
 };
 
-static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
+static int calxeda_cpuidle_probe(struct platform_device *pdev)
 {
        return cpuidle_register(&calxeda_idle_driver, NULL);
 }
index 9dd6e01eac33050b8304c5f8758440e7286606f2..f757a0f428bde807a8e5402af8404e98314c2bf8 100644 (file)
@@ -1410,14 +1410,12 @@ static const struct platform_device_info ixp_dev_info __initdata = {
 static int __init ixp_module_init(void)
 {
        int num = ARRAY_SIZE(ixp4xx_algos);
-       int i, err ;
+       int i, err;
 
        pdev = platform_device_register_full(&ixp_dev_info);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
 
-       dev = &pdev->dev;
-
        spin_lock_init(&desc_lock);
        spin_lock_init(&emerg_lock);
 
index ef63b9058f3c09d9d9dea56096bc5edda6d3b125..ed610b4975186b8e389de7360d4d3c8e6f5785e3 100644 (file)
@@ -535,11 +535,41 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
 }
 EXPORT_SYMBOL_GPL(dma_get_slave_channel);
 
+struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
+{
+       dma_cap_mask_t mask;
+       struct dma_chan *chan;
+       int err;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       /* lock against __dma_request_channel */
+       mutex_lock(&dma_list_mutex);
+
+       chan = private_candidate(&mask, device, NULL, NULL);
+       if (chan) {
+               err = dma_chan_get(chan);
+               if (err) {
+                       pr_debug("%s: failed to get %s: (%d)\n",
+                               __func__, dma_chan_name(chan), err);
+                       chan = NULL;
+               }
+       }
+
+       mutex_unlock(&dma_list_mutex);
+
+       return chan;
+}
+EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
+
 /**
  * __dma_request_channel - try to allocate an exclusive channel
  * @mask: capabilities that the channel must satisfy
  * @fn: optional callback to disposition available channels
  * @fn_param: opaque parameter to pass to dma_filter_fn
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
  */
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                       dma_filter_fn fn, void *fn_param)
@@ -591,18 +621,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
  * dma_request_slave_channel - try to allocate an exclusive slave channel
  * @dev:       pointer to client device structure
  * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
-struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name)
 {
+       struct dma_chan *chan;
+
        /* If device-tree is present get slave info from here */
        if (dev->of_node)
                return of_dma_request_slave_channel(dev->of_node, name);
 
        /* If device was enumerated by ACPI get slave info from here */
-       if (ACPI_HANDLE(dev))
-               return acpi_dma_request_slave_chan_by_name(dev, name);
+       if (ACPI_HANDLE(dev)) {
+               chan = acpi_dma_request_slave_chan_by_name(dev, name);
+               if (chan)
+                       return chan;
+       }
 
-       return NULL;
+       return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
+
+/**
+ * dma_request_slave_channel - try to allocate an exclusive slave channel
+ * @dev:       pointer to client device structure
+ * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
+ */
+struct dma_chan *dma_request_slave_channel(struct device *dev,
+                                          const char *name)
+{
+       struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
+       if (IS_ERR(ch))
+               return NULL;
+       return ch;
 }
 EXPORT_SYMBOL_GPL(dma_request_slave_channel);
 
index 1a49c777607c50d313482f3ead21c19572a1cf8d..87529181efccb9851467cc04be04bd91fecb15b3 100644 (file)
@@ -817,7 +817,15 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
        dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, dma_src)) {
+               dev_err(dev, "mapping src buffer failed\n");
+               goto free_resources;
+       }
        dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dev, dma_dest)) {
+               dev_err(dev, "mapping dest buffer failed\n");
+               goto unmap_src;
+       }
        flags = DMA_PREP_INTERRUPT;
        tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
                                                   IOAT_TEST_SIZE, flags);
@@ -855,8 +863,9 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
 unmap_dma:
-       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
        dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+unmap_src:
+       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
 free_resources:
        dma->device_free_chan_resources(dma_chan);
 out:
index 8869500ab92b84a4b93f4111f8936e6722d4911c..c6a01ea8bc591c289777d2ab837ef48887cf64d1 100644 (file)
@@ -893,33 +893,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
                                           struct of_dma *ofdma)
 {
        struct mmp_pdma_device *d = ofdma->of_dma_data;
-       struct dma_chan *chan, *candidate;
+       struct dma_chan *chan;
+       struct mmp_pdma_chan *c;
 
-retry:
-       candidate = NULL;
-
-       /* walk the list of channels registered with the current instance and
-        * find one that is currently unused */
-       list_for_each_entry(chan, &d->device.channels, device_node)
-               if (chan->client_count == 0) {
-                       candidate = chan;
-                       break;
-               }
-
-       if (!candidate)
+       chan = dma_get_any_slave_channel(&d->device);
+       if (!chan)
                return NULL;
 
-       /* dma_get_slave_channel will return NULL if we lost a race between
-        * the lookup and the reservation */
-       chan = dma_get_slave_channel(candidate);
-
-       if (chan) {
-               struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
-               c->drcmr = dma_spec->args[0];
-               return chan;
-       }
+       c = to_mmp_pdma_chan(chan);
+       c->drcmr = dma_spec->args[0];
 
-       goto retry;
+       return chan;
 }
 
 static int mmp_pdma_probe(struct platform_device *op)
index 0b88dd3d05f4880f41561f455f79c5eb9ca0a885..e8fe9dc455f4d8989e6d75618fecdd7ce351647f 100644 (file)
@@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
  * @np:                device node to get DMA request from
  * @name:      name of desired channel
  *
- * Returns pointer to appropriate dma channel on success or NULL on error.
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
 struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                                              const char *name)
@@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
        struct of_dma           *ofdma;
        struct dma_chan         *chan;
        int                     count, i;
+       int                     ret_no_channel = -ENODEV;
 
        if (!np || !name) {
                pr_err("%s: not enough information provided\n", __func__);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        count = of_property_count_strings(np, "dma-names");
        if (count < 0) {
                pr_err("%s: dma-names property of node '%s' missing or empty\n",
                        __func__, np->full_name);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        for (i = 0; i < count; i++) {
@@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                mutex_lock(&of_dma_lock);
                ofdma = of_dma_find_controller(&dma_spec);
 
-               if (ofdma)
+               if (ofdma) {
                        chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
-               else
+               } else {
+                       ret_no_channel = -EPROBE_DEFER;
                        chan = NULL;
+               }
 
                mutex_unlock(&of_dma_lock);
 
@@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                        return chan;
        }
 
-       return NULL;
+       return ERR_PTR(ret_no_channel);
 }
 
 /**
index 73654e33f13b98c66ebce532646056ecdce79c61..d11bb3620f2783115b7a91058a297dfbf657033d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DMA driver for Nvidia's Tegra20 APB DMA controller.
  *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2013, NVIDIA 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,
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_dma.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
-#include <linux/clk/tegra.h>
 
 #include "dmaengine.h"
 
@@ -199,6 +200,7 @@ struct tegra_dma_channel {
        void                    *callback_param;
 
        /* Channel-slave specific configuration */
+       unsigned int slave_id;
        struct dma_slave_config dma_sconfig;
        struct tegra_dma_channel_regs   channel_reg;
 };
@@ -208,6 +210,7 @@ struct tegra_dma {
        struct dma_device               dma_dev;
        struct device                   *dev;
        struct clk                      *dma_clk;
+       struct reset_control            *rst;
        spinlock_t                      global_lock;
        void __iomem                    *base_addr;
        const struct tegra_dma_chip_data *chip_data;
@@ -339,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc,
        }
 
        memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
+       if (!tdc->slave_id)
+               tdc->slave_id = sconfig->slave_id;
        tdc->config_init = true;
        return 0;
 }
@@ -941,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
        ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
 
        csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW;
-       csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
+       csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
        if (flags & DMA_PREP_INTERRUPT)
                csr |= TEGRA_APBDMA_CSR_IE_EOC;
 
@@ -1085,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
        csr |= TEGRA_APBDMA_CSR_FLOW;
        if (flags & DMA_PREP_INTERRUPT)
                csr |= TEGRA_APBDMA_CSR_IE_EOC;
-       csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
+       csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
 
        apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
 
@@ -1205,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
                kfree(sg_req);
        }
        clk_disable_unprepare(tdma->dma_clk);
+
+       tdc->slave_id = 0;
+}
+
+static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
+                                          struct of_dma *ofdma)
+{
+       struct tegra_dma *tdma = ofdma->of_dma_data;
+       struct dma_chan *chan;
+       struct tegra_dma_channel *tdc;
+
+       chan = dma_get_any_slave_channel(&tdma->dma_dev);
+       if (!chan)
+               return NULL;
+
+       tdc = to_tegra_dma_chan(chan);
+       tdc->slave_id = dma_spec->args[0];
+
+       return chan;
 }
 
 /* Tegra20 specific DMA controller information */
@@ -1282,6 +1306,12 @@ static int tegra_dma_probe(struct platform_device *pdev)
                return PTR_ERR(tdma->dma_clk);
        }
 
+       tdma->rst = devm_reset_control_get(&pdev->dev, "dma");
+       if (IS_ERR(tdma->rst)) {
+               dev_err(&pdev->dev, "Error: Missing reset\n");
+               return PTR_ERR(tdma->rst);
+       }
+
        spin_lock_init(&tdma->global_lock);
 
        pm_runtime_enable(&pdev->dev);
@@ -1302,9 +1332,9 @@ static int tegra_dma_probe(struct platform_device *pdev)
        }
 
        /* Reset DMA controller */
-       tegra_periph_reset_assert(tdma->dma_clk);
+       reset_control_assert(tdma->rst);
        udelay(2);
-       tegra_periph_reset_deassert(tdma->dma_clk);
+       reset_control_deassert(tdma->rst);
 
        /* Enable global DMA registers */
        tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE);
@@ -1376,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
+       ret = of_dma_controller_register(pdev->dev.of_node,
+                                        tegra_dma_of_xlate, tdma);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Tegra20 APB DMA OF registration failed %d\n", ret);
+               goto err_unregister_dma_dev;
+       }
+
        dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
                        cdata->nr_channels);
        return 0;
 
+err_unregister_dma_dev:
+       dma_async_device_unregister(&tdma->dma_dev);
 err_irq:
        while (--i >= 0) {
                struct tegra_dma_channel *tdc = &tdma->channels[i];
index f8642759116770afa976a23f12f14f1f42149be4..8e7fa4dbaed867ca45cb9c885db53543a65a74b9 100644 (file)
@@ -20,6 +20,10 @@ menuconfig DRM
          details.  You should also select and configure AGP
          (/dev/agpgart) support if it is available for your platform.
 
+config DRM_MIPI_DSI
+       bool
+       depends on DRM
+
 config DRM_USB
        tristate
        depends on DRM
@@ -188,6 +192,10 @@ source "drivers/gpu/drm/tilcdc/Kconfig"
 
 source "drivers/gpu/drm/qxl/Kconfig"
 
+source "drivers/gpu/drm/bochs/Kconfig"
+
 source "drivers/gpu/drm/msm/Kconfig"
 
 source "drivers/gpu/drm/tegra/Kconfig"
+
+source "drivers/gpu/drm/panel/Kconfig"
index cc08b845f9655a6b8bb516dab365da2d4c829198..292a79d64146274428ad1ef251d08e1d78d46bf5 100644 (file)
@@ -18,6 +18,7 @@ drm-y       :=        drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 drm-$(CONFIG_PCI) += ati_pcigart.o
+drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 
 drm-usb-y   := drm_usb.o
 
@@ -31,6 +32,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 CFLAGS_drm_trace_points.o := -I$(src)
 
 obj-$(CONFIG_DRM)      += drm.o
+obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
 obj-$(CONFIG_DRM_USB)   += drm_usb.o
 obj-$(CONFIG_DRM_TTM)  += ttm/
 obj-$(CONFIG_DRM_TDFX) += tdfx/
@@ -56,6 +58,8 @@ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP) += omapdrm/
 obj-$(CONFIG_DRM_TILCDC)       += tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
+obj-$(CONFIG_DRM_BOCHS) += bochs/
 obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y                  += i2c/
+obj-y                  += panel/
index 62d0ff3efddf9bb5a08e1b209b5a40c6b8148e47..acf3a36c9ebc453737b1a849aa6715f41b241d68 100644 (file)
@@ -128,6 +128,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
                return -ENOMEM;
        }
 
+       platform_set_drvdata(dev->platformdev, dev);
        dev->dev_private = priv;
 
        /* Get the implementation specific driver data. */
@@ -381,7 +382,7 @@ static int armada_drm_probe(struct platform_device *pdev)
 
 static int armada_drm_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&armada_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
        return 0;
 }
 
index af0b868a9dfd6c5b3849f147f01fbf2cc29c4471..50535fd5a88d258492b90ca9e9e9cebfaf2de563 100644 (file)
@@ -189,53 +189,6 @@ static int ast_get_dram_info(struct drm_device *dev)
        return 0;
 }
 
-uint32_t ast_get_max_dclk(struct drm_device *dev, int bpp)
-{
-       struct ast_private *ast = dev->dev_private;
-       uint32_t dclk, jreg;
-       uint32_t dram_bus_width, mclk, dram_bandwidth, actual_dram_bandwidth, dram_efficency = 500;
-
-       dram_bus_width = ast->dram_bus_width;
-       mclk = ast->mclk;
-
-       if (ast->chip == AST2100 ||
-           ast->chip == AST1100 ||
-           ast->chip == AST2200 ||
-           ast->chip == AST2150 ||
-           ast->dram_bus_width == 16)
-               dram_efficency = 600;
-       else if (ast->chip == AST2300)
-               dram_efficency = 400;
-
-       dram_bandwidth = mclk * dram_bus_width * 2 / 8;
-       actual_dram_bandwidth = dram_bandwidth * dram_efficency / 1000;
-
-       if (ast->chip == AST1180)
-               dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
-       else {
-               jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-               if ((jreg & 0x08) && (ast->chip == AST2000))
-                       dclk = actual_dram_bandwidth / ((bpp + 1 + 16) / 8);
-               else if ((jreg & 0x08) && (bpp == 8))
-                       dclk = actual_dram_bandwidth / ((bpp + 1 + 24) / 8);
-               else
-                       dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
-       }
-
-       if (ast->chip == AST2100 ||
-           ast->chip == AST2200 ||
-           ast->chip == AST2300 ||
-           ast->chip == AST1180) {
-               if (dclk > 200)
-                       dclk = 200;
-       } else {
-               if (dclk > 165)
-                       dclk = 165;
-       }
-
-       return dclk;
-}
-
 static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
@@ -449,7 +402,7 @@ int ast_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void ast_bo_unref(struct ast_bo **bo)
+static void ast_bo_unref(struct ast_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index 7fc9f7272b56e7e9ebe846b650e9e2f18f28cc5f..cca063b110831aa4d4fc2f46afd6e9cc35ac30b9 100644 (file)
@@ -404,7 +404,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
        }
 }
 
-void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
+static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
                      struct ast_vbios_mode_info *vbios_mode)
 {
        struct ast_private *ast = dev->dev_private;
@@ -415,7 +415,7 @@ void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
        ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
 }
 
-bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
+static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
                     struct ast_vbios_mode_info *vbios_mode)
 {
        switch (crtc->fb->bits_per_pixel) {
@@ -427,7 +427,7 @@ bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
        return true;
 }
 
-void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)
+static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        u32 addr;
@@ -623,7 +623,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = {
        .destroy = ast_crtc_destroy,
 };
 
-int ast_crtc_init(struct drm_device *dev)
+static int ast_crtc_init(struct drm_device *dev)
 {
        struct ast_crtc *crtc;
        int i;
@@ -710,7 +710,7 @@ static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = {
        .mode_set = ast_encoder_mode_set,
 };
 
-int ast_encoder_init(struct drm_device *dev)
+static int ast_encoder_init(struct drm_device *dev)
 {
        struct ast_encoder *ast_encoder;
 
@@ -777,7 +777,7 @@ static const struct drm_connector_funcs ast_connector_funcs = {
        .destroy = ast_connector_destroy,
 };
 
-int ast_connector_init(struct drm_device *dev)
+static int ast_connector_init(struct drm_device *dev)
 {
        struct ast_connector *ast_connector;
        struct drm_connector *connector;
@@ -810,7 +810,7 @@ int ast_connector_init(struct drm_device *dev)
 }
 
 /* allocate cursor cache and pin at start of VRAM */
-int ast_cursor_init(struct drm_device *dev)
+static int ast_cursor_init(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
        int size;
@@ -847,7 +847,7 @@ fail:
        return ret;
 }
 
-void ast_cursor_fini(struct drm_device *dev)
+static void ast_cursor_fini(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
        ttm_bo_kunmap(&ast->cache_kmap);
@@ -965,7 +965,7 @@ static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
        kfree(i2c);
 }
 
-void ast_show_cursor(struct drm_crtc *crtc)
+static void ast_show_cursor(struct drm_crtc *crtc)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        u8 jreg;
@@ -976,7 +976,7 @@ void ast_show_cursor(struct drm_crtc *crtc)
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
 }
 
-void ast_hide_cursor(struct drm_crtc *crtc)
+static void ast_hide_cursor(struct drm_crtc *crtc)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
index 32aecb34dbced78308a393833e177fd46a1e5c9b..4ea9b17ac17a9c5459617898718f1145eaf232ba 100644 (file)
@@ -80,7 +80,7 @@ static int ast_ttm_global_init(struct ast_private *ast)
        return 0;
 }
 
-void
+static void
 ast_ttm_global_release(struct ast_private *ast)
 {
        if (ast->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void ast_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo)
+static bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &ast_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func ast_tt_backend_func = {
 };
 
 
-struct ttm_tt *ast_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *ast_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig
new file mode 100644 (file)
index 0000000..c8fcf12
--- /dev/null
@@ -0,0 +1,11 @@
+config DRM_BOCHS
+       tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
+       depends on DRM && PCI
+       select DRM_KMS_HELPER
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select DRM_TTM
+       help
+         Choose this option for qemu.
+         If M is selected the module will be called bochs-drm.
diff --git a/drivers/gpu/drm/bochs/Makefile b/drivers/gpu/drm/bochs/Makefile
new file mode 100644 (file)
index 0000000..844a556
--- /dev/null
@@ -0,0 +1,4 @@
+ccflags-y := -Iinclude/drm
+bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_fbdev.o bochs_hw.o
+
+obj-$(CONFIG_DRM_BOCHS)        += bochs-drm.o
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
new file mode 100644 (file)
index 0000000..741965c
--- /dev/null
@@ -0,0 +1,164 @@
+#include <linux/io.h>
+#include <linux/fb.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_page_alloc.h>
+
+/* ---------------------------------------------------------------------- */
+
+#define VBE_DISPI_IOPORT_INDEX           0x01CE
+#define VBE_DISPI_IOPORT_DATA            0x01CF
+
+#define VBE_DISPI_INDEX_ID               0x0
+#define VBE_DISPI_INDEX_XRES             0x1
+#define VBE_DISPI_INDEX_YRES             0x2
+#define VBE_DISPI_INDEX_BPP              0x3
+#define VBE_DISPI_INDEX_ENABLE           0x4
+#define VBE_DISPI_INDEX_BANK             0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
+#define VBE_DISPI_INDEX_X_OFFSET         0x8
+#define VBE_DISPI_INDEX_Y_OFFSET         0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0                    0xB0C0
+#define VBE_DISPI_ID1                    0xB0C1
+#define VBE_DISPI_ID2                    0xB0C2
+#define VBE_DISPI_ID3                    0xB0C3
+#define VBE_DISPI_ID4                    0xB0C4
+#define VBE_DISPI_ID5                    0xB0C5
+
+#define VBE_DISPI_DISABLED               0x00
+#define VBE_DISPI_ENABLED                0x01
+#define VBE_DISPI_GETCAPS                0x02
+#define VBE_DISPI_8BIT_DAC               0x20
+#define VBE_DISPI_LFB_ENABLED            0x40
+#define VBE_DISPI_NOCLEARMEM             0x80
+
+/* ---------------------------------------------------------------------- */
+
+enum bochs_types {
+       BOCHS_QEMU_STDVGA,
+       BOCHS_UNKNOWN,
+};
+
+struct bochs_framebuffer {
+       struct drm_framebuffer base;
+       struct drm_gem_object *obj;
+};
+
+struct bochs_device {
+       /* hw */
+       void __iomem   *mmio;
+       int            ioports;
+       void __iomem   *fb_map;
+       unsigned long  fb_base;
+       unsigned long  fb_size;
+
+       /* mode */
+       u16 xres;
+       u16 yres;
+       u16 yres_virtual;
+       u32 stride;
+       u32 bpp;
+
+       /* drm */
+       struct drm_device  *dev;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;
+       struct drm_connector connector;
+       bool mode_config_initialized;
+
+       /* ttm */
+       struct {
+               struct drm_global_reference mem_global_ref;
+               struct ttm_bo_global_ref bo_global_ref;
+               struct ttm_bo_device bdev;
+               bool initialized;
+       } ttm;
+
+       /* fbdev */
+       struct {
+               struct bochs_framebuffer gfb;
+               struct drm_fb_helper helper;
+               int size;
+               int x1, y1, x2, y2; /* dirty rect */
+               spinlock_t dirty_lock;
+               bool initialized;
+       } fb;
+};
+
+#define to_bochs_framebuffer(x) container_of(x, struct bochs_framebuffer, base)
+
+struct bochs_bo {
+       struct ttm_buffer_object bo;
+       struct ttm_placement placement;
+       struct ttm_bo_kmap_obj kmap;
+       struct drm_gem_object gem;
+       u32 placements[3];
+       int pin_count;
+};
+
+static inline struct bochs_bo *bochs_bo(struct ttm_buffer_object *bo)
+{
+       return container_of(bo, struct bochs_bo, bo);
+}
+
+static inline struct bochs_bo *gem_to_bochs_bo(struct drm_gem_object *gem)
+{
+       return container_of(gem, struct bochs_bo, gem);
+}
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
+{
+       return drm_vma_node_offset_addr(&bo->bo.vma_node);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* bochs_hw.c */
+int bochs_hw_init(struct drm_device *dev, uint32_t flags);
+void bochs_hw_fini(struct drm_device *dev);
+
+void bochs_hw_setmode(struct bochs_device *bochs,
+                     struct drm_display_mode *mode);
+void bochs_hw_setbase(struct bochs_device *bochs,
+                     int x, int y, u64 addr);
+
+/* bochs_mm.c */
+int bochs_mm_init(struct bochs_device *bochs);
+void bochs_mm_fini(struct bochs_device *bochs);
+int bochs_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+                    struct drm_gem_object **obj);
+int bochs_gem_init_object(struct drm_gem_object *obj);
+void bochs_gem_free_object(struct drm_gem_object *obj);
+int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
+                     struct drm_mode_create_dumb *args);
+int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+                          uint32_t handle, uint64_t *offset);
+
+int bochs_framebuffer_init(struct drm_device *dev,
+                          struct bochs_framebuffer *gfb,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_gem_object *obj);
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int bochs_bo_unpin(struct bochs_bo *bo);
+
+extern const struct drm_mode_config_funcs bochs_mode_funcs;
+
+/* bochs_kms.c */
+int bochs_kms_init(struct bochs_device *bochs);
+void bochs_kms_fini(struct bochs_device *bochs);
+
+/* bochs_fbdev.c */
+int bochs_fbdev_init(struct bochs_device *bochs);
+void bochs_fbdev_fini(struct bochs_device *bochs);
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
new file mode 100644 (file)
index 0000000..395bba2
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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/mm.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "bochs.h"
+
+static bool enable_fbdev = true;
+module_param_named(fbdev, enable_fbdev, bool, 0444);
+MODULE_PARM_DESC(fbdev, "register fbdev device");
+
+/* ---------------------------------------------------------------------- */
+/* drm interface                                                          */
+
+static int bochs_unload(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+
+       bochs_fbdev_fini(bochs);
+       bochs_kms_fini(bochs);
+       bochs_mm_fini(bochs);
+       bochs_hw_fini(dev);
+       kfree(bochs);
+       dev->dev_private = NULL;
+       return 0;
+}
+
+static int bochs_load(struct drm_device *dev, unsigned long flags)
+{
+       struct bochs_device *bochs;
+       int ret;
+
+       bochs = kzalloc(sizeof(*bochs), GFP_KERNEL);
+       if (bochs == NULL)
+               return -ENOMEM;
+       dev->dev_private = bochs;
+       bochs->dev = dev;
+
+       ret = bochs_hw_init(dev, flags);
+       if (ret)
+               goto err;
+
+       ret = bochs_mm_init(bochs);
+       if (ret)
+               goto err;
+
+       ret = bochs_kms_init(bochs);
+       if (ret)
+               goto err;
+
+       if (enable_fbdev)
+               bochs_fbdev_init(bochs);
+
+       return 0;
+
+err:
+       bochs_unload(dev);
+       return ret;
+}
+
+static const struct file_operations bochs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = drm_open,
+       .release        = drm_release,
+       .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = drm_compat_ioctl,
+#endif
+       .poll           = drm_poll,
+       .read           = drm_read,
+       .llseek         = no_llseek,
+       .mmap           = bochs_mmap,
+};
+
+static struct drm_driver bochs_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET,
+       .load                   = bochs_load,
+       .unload                 = bochs_unload,
+       .fops                   = &bochs_fops,
+       .name                   = "bochs-drm",
+       .desc                   = "bochs dispi vga interface (qemu stdvga)",
+       .date                   = "20130925",
+       .major                  = 1,
+       .minor                  = 0,
+       .gem_free_object        = bochs_gem_free_object,
+       .dumb_create            = bochs_dumb_create,
+       .dumb_map_offset        = bochs_dumb_mmap_offset,
+       .dumb_destroy           = drm_gem_dumb_destroy,
+};
+
+/* ---------------------------------------------------------------------- */
+/* pci interface                                                          */
+
+static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return -ENOMEM;
+
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+       remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
+       kfree(ap);
+
+       return 0;
+}
+
+static int bochs_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
+{
+       int ret;
+
+       ret = bochs_kick_out_firmware_fb(pdev);
+       if (ret)
+               return ret;
+
+       return drm_get_pci_dev(pdev, ent, &bochs_driver);
+}
+
+static void bochs_pci_remove(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+
+       drm_put_dev(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = {
+       {
+               .vendor      = 0x1234,
+               .device      = 0x1111,
+               .subvendor   = 0x1af4,
+               .subdevice   = 0x1100,
+               .driver_data = BOCHS_QEMU_STDVGA,
+       },
+       {
+               .vendor      = 0x1234,
+               .device      = 0x1111,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = BOCHS_UNKNOWN,
+       },
+       { /* end of list */ }
+};
+
+static struct pci_driver bochs_pci_driver = {
+       .name =         "bochs-drm",
+       .id_table =     bochs_pci_tbl,
+       .probe =        bochs_pci_probe,
+       .remove =       bochs_pci_remove,
+};
+
+/* ---------------------------------------------------------------------- */
+/* module init/exit                                                       */
+
+static int __init bochs_init(void)
+{
+       return drm_pci_init(&bochs_driver, &bochs_pci_driver);
+}
+
+static void __exit bochs_exit(void)
+{
+       drm_pci_exit(&bochs_driver, &bochs_pci_driver);
+}
+
+module_init(bochs_init);
+module_exit(bochs_exit);
+
+MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
new file mode 100644 (file)
index 0000000..4da5206
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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 "bochs.h"
+
+/* ---------------------------------------------------------------------- */
+
+static struct fb_ops bochsfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_fillrect = sys_fillrect,
+       .fb_copyarea = sys_copyarea,
+       .fb_imageblit = sys_imageblit,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int bochsfb_create_object(struct bochs_device *bochs,
+                                struct drm_mode_fb_cmd2 *mode_cmd,
+                                struct drm_gem_object **gobj_p)
+{
+       struct drm_device *dev = bochs->dev;
+       struct drm_gem_object *gobj;
+       u32 size;
+       int ret = 0;
+
+       size = mode_cmd->pitches[0] * mode_cmd->height;
+       ret = bochs_gem_create(dev, size, true, &gobj);
+       if (ret)
+               return ret;
+
+       *gobj_p = gobj;
+       return ret;
+}
+
+static int bochsfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct bochs_device *bochs =
+               container_of(helper, struct bochs_device, fb.helper);
+       struct drm_device *dev = bochs->dev;
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_mode_fb_cmd2 mode_cmd;
+       struct device *device = &dev->pdev->dev;
+       struct drm_gem_object *gobj = NULL;
+       struct bochs_bo *bo = NULL;
+       int size, ret;
+
+       if (sizes->surface_bpp != 32)
+               return -EINVAL;
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                                                         sizes->surface_depth);
+       size = mode_cmd.pitches[0] * mode_cmd.height;
+
+       /* alloc, pin & map bo */
+       ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
+       if (ret) {
+               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
+               return ret;
+       }
+
+       bo = gem_to_bochs_bo(gobj);
+
+       ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+       if (ret)
+               return ret;
+
+       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+       if (ret) {
+               DRM_ERROR("failed to pin fbcon\n");
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
+                         &bo->kmap);
+       if (ret) {
+               DRM_ERROR("failed to kmap fbcon\n");
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ttm_bo_unreserve(&bo->bo);
+
+       /* init fb device */
+       info = framebuffer_alloc(0, device);
+       if (info == NULL)
+               return -ENOMEM;
+
+       info->par = &bochs->fb.helper;
+
+       ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
+       if (ret)
+               return ret;
+
+       bochs->fb.size = size;
+
+       /* setup helper */
+       fb = &bochs->fb.gfb.base;
+       bochs->fb.helper.fb = fb;
+       bochs->fb.helper.fbdev = info;
+
+       strcpy(info->fix.id, "bochsdrmfb");
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &bochsfb_ops;
+
+       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+       drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width,
+                              sizes->fb_height);
+
+       info->screen_base = bo->kmap.virtual;
+       info->screen_size = size;
+
+#if 0
+       /* FIXME: get this right for mmap(/dev/fb0) */
+       info->fix.smem_start = bochs_bo_mmap_offset(bo);
+       info->fix.smem_len = size;
+#endif
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret) {
+               DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int bochs_fbdev_destroy(struct bochs_device *bochs)
+{
+       struct bochs_framebuffer *gfb = &bochs->fb.gfb;
+       struct fb_info *info;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (bochs->fb.helper.fbdev) {
+               info = bochs->fb.helper.fbdev;
+
+               unregister_framebuffer(info);
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+       }
+
+       if (gfb->obj) {
+               drm_gem_object_unreference_unlocked(gfb->obj);
+               gfb->obj = NULL;
+       }
+
+       drm_fb_helper_fini(&bochs->fb.helper);
+       drm_framebuffer_unregister_private(&gfb->base);
+       drm_framebuffer_cleanup(&gfb->base);
+
+       return 0;
+}
+
+void bochs_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                       u16 blue, int regno)
+{
+}
+
+void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                       u16 *blue, int regno)
+{
+       *red   = regno;
+       *green = regno;
+       *blue  = regno;
+}
+
+static struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
+       .gamma_set = bochs_fb_gamma_set,
+       .gamma_get = bochs_fb_gamma_get,
+       .fb_probe = bochsfb_create,
+};
+
+int bochs_fbdev_init(struct bochs_device *bochs)
+{
+       int ret;
+
+       bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
+       spin_lock_init(&bochs->fb.dirty_lock);
+
+       ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
+                                1, 1);
+       if (ret)
+               return ret;
+
+       drm_fb_helper_single_add_all_connectors(&bochs->fb.helper);
+       drm_helper_disable_unused_functions(bochs->dev);
+       drm_fb_helper_initial_config(&bochs->fb.helper, 32);
+
+       bochs->fb.initialized = true;
+       return 0;
+}
+
+void bochs_fbdev_fini(struct bochs_device *bochs)
+{
+       if (!bochs->fb.initialized)
+               return;
+
+       bochs_fbdev_destroy(bochs);
+       bochs->fb.initialized = false;
+}
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
new file mode 100644 (file)
index 0000000..dbe619e
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * 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 "bochs.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
+{
+       if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
+               return;
+
+       if (bochs->mmio) {
+               int offset = ioport - 0x3c0 + 0x400;
+               writeb(val, bochs->mmio + offset);
+       } else {
+               outb(val, ioport);
+       }
+}
+
+static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
+{
+       u16 ret = 0;
+
+       if (bochs->mmio) {
+               int offset = 0x500 + (reg << 1);
+               ret = readw(bochs->mmio + offset);
+       } else {
+               outw(reg, VBE_DISPI_IOPORT_INDEX);
+               ret = inw(VBE_DISPI_IOPORT_DATA);
+       }
+       return ret;
+}
+
+static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
+{
+       if (bochs->mmio) {
+               int offset = 0x500 + (reg << 1);
+               writew(val, bochs->mmio + offset);
+       } else {
+               outw(reg, VBE_DISPI_IOPORT_INDEX);
+               outw(val, VBE_DISPI_IOPORT_DATA);
+       }
+}
+
+int bochs_hw_init(struct drm_device *dev, uint32_t flags)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct pci_dev *pdev = dev->pdev;
+       unsigned long addr, size, mem, ioaddr, iosize;
+       u16 id;
+
+       if (/* (ent->driver_data == BOCHS_QEMU_STDVGA) && */
+           (pdev->resource[2].flags & IORESOURCE_MEM)) {
+               /* mmio bar with vga and bochs registers present */
+               if (pci_request_region(pdev, 2, "bochs-drm") != 0) {
+                       DRM_ERROR("Cannot request mmio region\n");
+                       return -EBUSY;
+               }
+               ioaddr = pci_resource_start(pdev, 2);
+               iosize = pci_resource_len(pdev, 2);
+               bochs->mmio = ioremap(ioaddr, iosize);
+               if (bochs->mmio == NULL) {
+                       DRM_ERROR("Cannot map mmio region\n");
+                       return -ENOMEM;
+               }
+       } else {
+               ioaddr = VBE_DISPI_IOPORT_INDEX;
+               iosize = 2;
+               if (!request_region(ioaddr, iosize, "bochs-drm")) {
+                       DRM_ERROR("Cannot request ioports\n");
+                       return -EBUSY;
+               }
+               bochs->ioports = 1;
+       }
+
+       id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
+       mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K)
+               * 64 * 1024;
+       if ((id & 0xfff0) != VBE_DISPI_ID0) {
+               DRM_ERROR("ID mismatch\n");
+               return -ENODEV;
+       }
+
+       if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0)
+               return -ENODEV;
+       addr = pci_resource_start(pdev, 0);
+       size = pci_resource_len(pdev, 0);
+       if (addr == 0)
+               return -ENODEV;
+       if (size != mem) {
+               DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n",
+                       size, mem);
+               size = min(size, mem);
+       }
+
+       if (pci_request_region(pdev, 0, "bochs-drm") != 0) {
+               DRM_ERROR("Cannot request framebuffer\n");
+               return -EBUSY;
+       }
+
+       bochs->fb_map = ioremap(addr, size);
+       if (bochs->fb_map == NULL) {
+               DRM_ERROR("Cannot map framebuffer\n");
+               return -ENOMEM;
+       }
+       bochs->fb_base = addr;
+       bochs->fb_size = size;
+
+       DRM_INFO("Found bochs VGA, ID 0x%x.\n", id);
+       DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n",
+                size / 1024, addr,
+                bochs->ioports ? "ioports" : "mmio",
+                ioaddr);
+       return 0;
+}
+
+void bochs_hw_fini(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+
+       if (bochs->mmio)
+               iounmap(bochs->mmio);
+       if (bochs->ioports)
+               release_region(VBE_DISPI_IOPORT_INDEX, 2);
+       if (bochs->fb_map)
+               iounmap(bochs->fb_map);
+       pci_release_regions(dev->pdev);
+}
+
+void bochs_hw_setmode(struct bochs_device *bochs,
+                     struct drm_display_mode *mode)
+{
+       bochs->xres = mode->hdisplay;
+       bochs->yres = mode->vdisplay;
+       bochs->bpp = 32;
+       bochs->stride = mode->hdisplay * (bochs->bpp / 8);
+       bochs->yres_virtual = bochs->fb_size / bochs->stride;
+
+       DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
+                        bochs->xres, bochs->yres, bochs->bpp,
+                        bochs->yres_virtual);
+
+       bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
+
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP,         bochs->bpp);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES,        bochs->xres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES,        bochs->yres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK,        0);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH,  bochs->xres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,
+                         bochs->yres_virtual);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET,    0);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET,    0);
+
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
+                         VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+}
+
+void bochs_hw_setbase(struct bochs_device *bochs,
+                     int x, int y, u64 addr)
+{
+       unsigned long offset = (unsigned long)addr +
+               y * bochs->stride +
+               x * (bochs->bpp / 8);
+       int vy = offset / bochs->stride;
+       int vx = (offset % bochs->stride) * 8 / bochs->bpp;
+
+       DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
+                        x, y, addr, offset, vx, vy);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
+}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
new file mode 100644 (file)
index 0000000..62ec7d4
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * 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 "bochs.h"
+
+static int defx = 1024;
+static int defy = 768;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+       default:
+               return;
+       }
+}
+
+static bool bochs_crtc_mode_fixup(struct drm_crtc *crtc,
+                                 const struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+                                   struct drm_framebuffer *old_fb)
+{
+       struct bochs_device *bochs =
+               container_of(crtc, struct bochs_device, crtc);
+       struct bochs_framebuffer *bochs_fb;
+       struct bochs_bo *bo;
+       u64 gpu_addr = 0;
+       int ret;
+
+       if (old_fb) {
+               bochs_fb = to_bochs_framebuffer(old_fb);
+               bo = gem_to_bochs_bo(bochs_fb->obj);
+               ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+               if (ret) {
+                       DRM_ERROR("failed to reserve old_fb bo\n");
+               } else {
+                       bochs_bo_unpin(bo);
+                       ttm_bo_unreserve(&bo->bo);
+               }
+       }
+
+       if (WARN_ON(crtc->fb == NULL))
+               return -EINVAL;
+
+       bochs_fb = to_bochs_framebuffer(crtc->fb);
+       bo = gem_to_bochs_bo(bochs_fb->obj);
+       ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+       if (ret)
+               return ret;
+
+       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+       if (ret) {
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ttm_bo_unreserve(&bo->bo);
+       bochs_hw_setbase(bochs, x, y, gpu_addr);
+       return 0;
+}
+
+static int bochs_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 bochs_device *bochs =
+               container_of(crtc, struct bochs_device, crtc);
+
+       bochs_hw_setmode(bochs, mode);
+       bochs_crtc_mode_set_base(crtc, x, y, old_fb);
+       return 0;
+}
+
+static void bochs_crtc_prepare(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_commit(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                u16 *blue, uint32_t start, uint32_t size)
+{
+}
+
+/* These provide the minimum set of functions required to handle a CRTC */
+static const struct drm_crtc_funcs bochs_crtc_funcs = {
+       .gamma_set = bochs_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
+       .dpms = bochs_crtc_dpms,
+       .mode_fixup = bochs_crtc_mode_fixup,
+       .mode_set = bochs_crtc_mode_set,
+       .mode_set_base = bochs_crtc_mode_set_base,
+       .prepare = bochs_crtc_prepare,
+       .commit = bochs_crtc_commit,
+       .load_lut = bochs_crtc_load_lut,
+};
+
+static void bochs_crtc_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_crtc *crtc = &bochs->crtc;
+
+       drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
+       drm_mode_crtc_set_gamma_size(crtc, 256);
+       drm_crtc_helper_add(crtc, &bochs_helper_funcs);
+}
+
+static bool bochs_encoder_mode_fixup(struct drm_encoder *encoder,
+                                    const struct drm_display_mode *mode,
+                                    struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void bochs_encoder_mode_set(struct drm_encoder *encoder,
+                                  struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void bochs_encoder_dpms(struct drm_encoder *encoder, int state)
+{
+}
+
+static void bochs_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void bochs_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = {
+       .dpms = bochs_encoder_dpms,
+       .mode_fixup = bochs_encoder_mode_fixup,
+       .mode_set = bochs_encoder_mode_set,
+       .prepare = bochs_encoder_prepare,
+       .commit = bochs_encoder_commit,
+};
+
+static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+static void bochs_encoder_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_encoder *encoder = &bochs->encoder;
+
+       encoder->possible_crtcs = 0x1;
+       drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs,
+                        DRM_MODE_ENCODER_DAC);
+       drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs);
+}
+
+
+int bochs_connector_get_modes(struct drm_connector *connector)
+{
+       int count;
+
+       count = drm_add_modes_noedid(connector, 8192, 8192);
+       drm_set_preferred_mode(connector, defx, defy);
+       return count;
+}
+
+static int bochs_connector_mode_valid(struct drm_connector *connector,
+                                     struct drm_display_mode *mode)
+{
+       struct bochs_device *bochs =
+               container_of(connector, struct bochs_device, connector);
+       unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+       /*
+        * Make sure we can fit two framebuffers into video memory.
+        * This allows up to 1600x1200 with 16 MB (default size).
+        * If you want more try this:
+        *     'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
+        */
+       if (size * 2 > bochs->fb_size)
+               return MODE_BAD;
+
+       return MODE_OK;
+}
+
+static struct drm_encoder *
+bochs_connector_best_encoder(struct drm_connector *connector)
+{
+       int enc_id = connector->encoder_ids[0];
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+
+       /* pick the encoder ids */
+       if (enc_id) {
+               obj = drm_mode_object_find(connector->dev, enc_id,
+                                          DRM_MODE_OBJECT_ENCODER);
+               if (!obj)
+                       return NULL;
+               encoder = obj_to_encoder(obj);
+               return encoder;
+       }
+       return NULL;
+}
+
+static enum drm_connector_status bochs_connector_detect(struct drm_connector
+                                                       *connector, bool force)
+{
+       return connector_status_connected;
+}
+
+struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
+       .get_modes = bochs_connector_get_modes,
+       .mode_valid = bochs_connector_mode_valid,
+       .best_encoder = bochs_connector_best_encoder,
+};
+
+struct drm_connector_funcs bochs_connector_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = bochs_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+};
+
+static void bochs_connector_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_connector *connector = &bochs->connector;
+
+       drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
+                          DRM_MODE_CONNECTOR_VIRTUAL);
+       drm_connector_helper_add(connector,
+                                &bochs_connector_connector_helper_funcs);
+}
+
+
+int bochs_kms_init(struct bochs_device *bochs)
+{
+       drm_mode_config_init(bochs->dev);
+       bochs->mode_config_initialized = true;
+
+       bochs->dev->mode_config.max_width = 8192;
+       bochs->dev->mode_config.max_height = 8192;
+
+       bochs->dev->mode_config.fb_base = bochs->fb_base;
+       bochs->dev->mode_config.preferred_depth = 24;
+       bochs->dev->mode_config.prefer_shadow = 0;
+
+       bochs->dev->mode_config.funcs = (void *)&bochs_mode_funcs;
+
+       bochs_crtc_init(bochs->dev);
+       bochs_encoder_init(bochs->dev);
+       bochs_connector_init(bochs->dev);
+       drm_mode_connector_attach_encoder(&bochs->connector,
+                                         &bochs->encoder);
+
+       return 0;
+}
+
+void bochs_kms_fini(struct bochs_device *bochs)
+{
+       if (bochs->mode_config_initialized) {
+               drm_mode_config_cleanup(bochs->dev);
+               bochs->mode_config_initialized = false;
+       }
+}
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
new file mode 100644 (file)
index 0000000..ce68587
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * 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 "bochs.h"
+
+static void bochs_ttm_placement(struct bochs_bo *bo, int domain);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd)
+{
+       return container_of(bd, struct bochs_device, ttm.bdev);
+}
+
+static int bochs_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+       return ttm_mem_global_init(ref->object);
+}
+
+static void bochs_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+       ttm_mem_global_release(ref->object);
+}
+
+static int bochs_ttm_global_init(struct bochs_device *bochs)
+{
+       struct drm_global_reference *global_ref;
+       int r;
+
+       global_ref = &bochs->ttm.mem_global_ref;
+       global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+       global_ref->size = sizeof(struct ttm_mem_global);
+       global_ref->init = &bochs_ttm_mem_global_init;
+       global_ref->release = &bochs_ttm_mem_global_release;
+       r = drm_global_item_ref(global_ref);
+       if (r != 0) {
+               DRM_ERROR("Failed setting up TTM memory accounting "
+                         "subsystem.\n");
+               return r;
+       }
+
+       bochs->ttm.bo_global_ref.mem_glob =
+               bochs->ttm.mem_global_ref.object;
+       global_ref = &bochs->ttm.bo_global_ref.ref;
+       global_ref->global_type = DRM_GLOBAL_TTM_BO;
+       global_ref->size = sizeof(struct ttm_bo_global);
+       global_ref->init = &ttm_bo_global_init;
+       global_ref->release = &ttm_bo_global_release;
+       r = drm_global_item_ref(global_ref);
+       if (r != 0) {
+               DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+               drm_global_item_unref(&bochs->ttm.mem_global_ref);
+               return r;
+       }
+
+       return 0;
+}
+
+static void bochs_ttm_global_release(struct bochs_device *bochs)
+{
+       if (bochs->ttm.mem_global_ref.release == NULL)
+               return;
+
+       drm_global_item_unref(&bochs->ttm.bo_global_ref.ref);
+       drm_global_item_unref(&bochs->ttm.mem_global_ref);
+       bochs->ttm.mem_global_ref.release = NULL;
+}
+
+
+static void bochs_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+       struct bochs_bo *bo;
+
+       bo = container_of(tbo, struct bochs_bo, bo);
+       drm_gem_object_release(&bo->gem);
+       kfree(bo);
+}
+
+static bool bochs_ttm_bo_is_bochs_bo(struct ttm_buffer_object *bo)
+{
+       if (bo->destroy == &bochs_bo_ttm_destroy)
+               return true;
+       return false;
+}
+
+static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+                                 struct ttm_mem_type_manager *man)
+{
+       switch (type) {
+       case TTM_PL_SYSTEM:
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_MASK_CACHING;
+               man->default_caching = TTM_PL_FLAG_CACHED;
+               break;
+       case TTM_PL_VRAM:
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_FIXED |
+                       TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_FLAG_UNCACHED |
+                       TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_WC;
+               break;
+       default:
+               DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void
+bochs_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+       struct bochs_bo *bochsbo = bochs_bo(bo);
+
+       if (!bochs_ttm_bo_is_bochs_bo(bo))
+               return;
+
+       bochs_ttm_placement(bochsbo, TTM_PL_FLAG_SYSTEM);
+       *pl = bochsbo->placement;
+}
+
+static int bochs_bo_verify_access(struct ttm_buffer_object *bo,
+                                 struct file *filp)
+{
+       struct bochs_bo *bochsbo = bochs_bo(bo);
+
+       return drm_vma_node_verify_access(&bochsbo->gem.vma_node, filp);
+}
+
+static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+                                   struct ttm_mem_reg *mem)
+{
+       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+       struct bochs_device *bochs = bochs_bdev(bdev);
+
+       mem->bus.addr = NULL;
+       mem->bus.offset = 0;
+       mem->bus.size = mem->num_pages << PAGE_SHIFT;
+       mem->bus.base = 0;
+       mem->bus.is_iomem = false;
+       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+               return -EINVAL;
+       switch (mem->mem_type) {
+       case TTM_PL_SYSTEM:
+               /* system memory */
+               return 0;
+       case TTM_PL_VRAM:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = bochs->fb_base;
+               mem->bus.is_iomem = true;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static void bochs_ttm_io_mem_free(struct ttm_bo_device *bdev,
+                                 struct ttm_mem_reg *mem)
+{
+}
+
+static int bochs_bo_move(struct ttm_buffer_object *bo,
+                        bool evict, bool interruptible,
+                        bool no_wait_gpu,
+                        struct ttm_mem_reg *new_mem)
+{
+       return ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+}
+
+
+static void bochs_ttm_backend_destroy(struct ttm_tt *tt)
+{
+       ttm_tt_fini(tt);
+       kfree(tt);
+}
+
+static struct ttm_backend_func bochs_tt_backend_func = {
+       .destroy = &bochs_ttm_backend_destroy,
+};
+
+static struct ttm_tt *bochs_ttm_tt_create(struct ttm_bo_device *bdev,
+                                         unsigned long size,
+                                         uint32_t page_flags,
+                                         struct page *dummy_read_page)
+{
+       struct ttm_tt *tt;
+
+       tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
+       if (tt == NULL)
+               return NULL;
+       tt->func = &bochs_tt_backend_func;
+       if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
+               kfree(tt);
+               return NULL;
+       }
+       return tt;
+}
+
+struct ttm_bo_driver bochs_bo_driver = {
+       .ttm_tt_create = bochs_ttm_tt_create,
+       .ttm_tt_populate = ttm_pool_populate,
+       .ttm_tt_unpopulate = ttm_pool_unpopulate,
+       .init_mem_type = bochs_bo_init_mem_type,
+       .evict_flags = bochs_bo_evict_flags,
+       .move = bochs_bo_move,
+       .verify_access = bochs_bo_verify_access,
+       .io_mem_reserve = &bochs_ttm_io_mem_reserve,
+       .io_mem_free = &bochs_ttm_io_mem_free,
+};
+
+int bochs_mm_init(struct bochs_device *bochs)
+{
+       struct ttm_bo_device *bdev = &bochs->ttm.bdev;
+       int ret;
+
+       ret = bochs_ttm_global_init(bochs);
+       if (ret)
+               return ret;
+
+       ret = ttm_bo_device_init(&bochs->ttm.bdev,
+                                bochs->ttm.bo_global_ref.ref.object,
+                                &bochs_bo_driver, DRM_FILE_PAGE_OFFSET,
+                                true);
+       if (ret) {
+               DRM_ERROR("Error initialising bo driver; %d\n", ret);
+               return ret;
+       }
+
+       ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+                            bochs->fb_size >> PAGE_SHIFT);
+       if (ret) {
+               DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
+               return ret;
+       }
+
+       bochs->ttm.initialized = true;
+       return 0;
+}
+
+void bochs_mm_fini(struct bochs_device *bochs)
+{
+       if (!bochs->ttm.initialized)
+               return;
+
+       ttm_bo_device_release(&bochs->ttm.bdev);
+       bochs_ttm_global_release(bochs);
+       bochs->ttm.initialized = false;
+}
+
+static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
+{
+       u32 c = 0;
+       bo->placement.fpfn = 0;
+       bo->placement.lpfn = 0;
+       bo->placement.placement = bo->placements;
+       bo->placement.busy_placement = bo->placements;
+       if (domain & TTM_PL_FLAG_VRAM) {
+               bo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED
+                       | TTM_PL_FLAG_VRAM;
+       }
+       if (domain & TTM_PL_FLAG_SYSTEM) {
+               bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+       }
+       if (!c) {
+               bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+       }
+       bo->placement.num_placement = c;
+       bo->placement.num_busy_placement = c;
+}
+
+static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo)
+{
+       return bo->bo.offset;
+}
+
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+       int i, ret;
+
+       if (bo->pin_count) {
+               bo->pin_count++;
+               if (gpu_addr)
+                       *gpu_addr = bochs_bo_gpu_offset(bo);
+               return 0;
+       }
+
+       bochs_ttm_placement(bo, pl_flag);
+       for (i = 0; i < bo->placement.num_placement; i++)
+               bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+       if (ret)
+               return ret;
+
+       bo->pin_count = 1;
+       if (gpu_addr)
+               *gpu_addr = bochs_bo_gpu_offset(bo);
+       return 0;
+}
+
+int bochs_bo_unpin(struct bochs_bo *bo)
+{
+       int i, ret;
+
+       if (!bo->pin_count) {
+               DRM_ERROR("unpin bad %p\n", bo);
+               return 0;
+       }
+       bo->pin_count--;
+
+       if (bo->pin_count)
+               return 0;
+
+       for (i = 0; i < bo->placement.num_placement; i++)
+               bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int bochs_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *file_priv;
+       struct bochs_device *bochs;
+
+       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+               return drm_mmap(filp, vma);
+
+       file_priv = filp->private_data;
+       bochs = file_priv->minor->dev->dev_private;
+       return ttm_bo_mmap(filp, vma, &bochs->ttm.bdev);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int bochs_bo_create(struct drm_device *dev, int size, int align,
+                          uint32_t flags, struct bochs_bo **pbochsbo)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct bochs_bo *bochsbo;
+       size_t acc_size;
+       int ret;
+
+       bochsbo = kzalloc(sizeof(struct bochs_bo), GFP_KERNEL);
+       if (!bochsbo)
+               return -ENOMEM;
+
+       ret = drm_gem_object_init(dev, &bochsbo->gem, size);
+       if (ret) {
+               kfree(bochsbo);
+               return ret;
+       }
+
+       bochsbo->bo.bdev = &bochs->ttm.bdev;
+       bochsbo->bo.bdev->dev_mapping = dev->dev_mapping;
+
+       bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+       acc_size = ttm_bo_dma_acc_size(&bochs->ttm.bdev, size,
+                                      sizeof(struct bochs_bo));
+
+       ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size,
+                         ttm_bo_type_device, &bochsbo->placement,
+                         align >> PAGE_SHIFT, false, NULL, acc_size,
+                         NULL, bochs_bo_ttm_destroy);
+       if (ret)
+               return ret;
+
+       *pbochsbo = bochsbo;
+       return 0;
+}
+
+int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+                    struct drm_gem_object **obj)
+{
+       struct bochs_bo *bochsbo;
+       int ret;
+
+       *obj = NULL;
+
+       size = ALIGN(size, PAGE_SIZE);
+       if (size == 0)
+               return -EINVAL;
+
+       ret = bochs_bo_create(dev, size, 0, 0, &bochsbo);
+       if (ret) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("failed to allocate GEM object\n");
+               return ret;
+       }
+       *obj = &bochsbo->gem;
+       return 0;
+}
+
+int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
+                     struct drm_mode_create_dumb *args)
+{
+       struct drm_gem_object *gobj;
+       u32 handle;
+       int ret;
+
+       args->pitch = args->width * ((args->bpp + 7) / 8);
+       args->size = args->pitch * args->height;
+
+       ret = bochs_gem_create(dev, args->size, false,
+                              &gobj);
+       if (ret)
+               return ret;
+
+       ret = drm_gem_handle_create(file, gobj, &handle);
+       drm_gem_object_unreference_unlocked(gobj);
+       if (ret)
+               return ret;
+
+       args->handle = handle;
+       return 0;
+}
+
+static void bochs_bo_unref(struct bochs_bo **bo)
+{
+       struct ttm_buffer_object *tbo;
+
+       if ((*bo) == NULL)
+               return;
+
+       tbo = &((*bo)->bo);
+       ttm_bo_unref(&tbo);
+       if (tbo == NULL)
+               *bo = NULL;
+
+}
+
+void bochs_gem_free_object(struct drm_gem_object *obj)
+{
+       struct bochs_bo *bochs_bo = gem_to_bochs_bo(obj);
+
+       if (!bochs_bo)
+               return;
+       bochs_bo_unref(&bochs_bo);
+}
+
+int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+                          uint32_t handle, uint64_t *offset)
+{
+       struct drm_gem_object *obj;
+       int ret;
+       struct bochs_bo *bo;
+
+       mutex_lock(&dev->struct_mutex);
+       obj = drm_gem_object_lookup(dev, file, handle);
+       if (obj == NULL) {
+               ret = -ENOENT;
+               goto out_unlock;
+       }
+
+       bo = gem_to_bochs_bo(obj);
+       *offset = bochs_bo_mmap_offset(bo);
+
+       drm_gem_object_unreference(obj);
+       ret = 0;
+out_unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct bochs_framebuffer *bochs_fb = to_bochs_framebuffer(fb);
+       if (bochs_fb->obj)
+               drm_gem_object_unreference_unlocked(bochs_fb->obj);
+       drm_framebuffer_cleanup(fb);
+       kfree(fb);
+}
+
+static const struct drm_framebuffer_funcs bochs_fb_funcs = {
+       .destroy = bochs_user_framebuffer_destroy,
+};
+
+int bochs_framebuffer_init(struct drm_device *dev,
+                          struct bochs_framebuffer *gfb,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_gem_object *obj)
+{
+       int ret;
+
+       drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
+       gfb->obj = obj;
+       ret = drm_framebuffer_init(dev, &gfb->base, &bochs_fb_funcs);
+       if (ret) {
+               DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+static struct drm_framebuffer *
+bochs_user_framebuffer_create(struct drm_device *dev,
+                             struct drm_file *filp,
+                             struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       struct drm_gem_object *obj;
+       struct bochs_framebuffer *bochs_fb;
+       int ret;
+
+       DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
+              mode_cmd->width, mode_cmd->height,
+              (mode_cmd->pixel_format)       & 0xff,
+              (mode_cmd->pixel_format >> 8)  & 0xff,
+              (mode_cmd->pixel_format >> 16) & 0xff,
+              (mode_cmd->pixel_format >> 24) & 0xff);
+
+       if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
+               return ERR_PTR(-ENOENT);
+
+       obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+       if (obj == NULL)
+               return ERR_PTR(-ENOENT);
+
+       bochs_fb = kzalloc(sizeof(*bochs_fb), GFP_KERNEL);
+       if (!bochs_fb) {
+               drm_gem_object_unreference_unlocked(obj);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ret = bochs_framebuffer_init(dev, bochs_fb, mode_cmd, obj);
+       if (ret) {
+               drm_gem_object_unreference_unlocked(obj);
+               kfree(bochs_fb);
+               return ERR_PTR(ret);
+       }
+       return &bochs_fb->base;
+}
+
+const struct drm_mode_config_funcs bochs_mode_funcs = {
+       .fb_create = bochs_user_framebuffer_create,
+};
index b6aded73838bca0fb11c5a936db40a8db1e1e180..117d3eca5e3782e5db3571a968d8e92111c1da4c 100644 (file)
@@ -222,7 +222,7 @@ void cirrus_fbdev_fini(struct cirrus_device *cdev);
 void cirrus_driver_irq_preinstall(struct drm_device *dev);
 int cirrus_driver_irq_postinstall(struct drm_device *dev);
 void cirrus_driver_irq_uninstall(struct drm_device *dev);
-irqreturn_t cirrus_driver_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t cirrus_driver_irq_handler(int irq, void *arg);
 
                                /* cirrus_kms.c */
 int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
index b27e95666fabf6fb28d56b07cd62fd3363776a0b..e63a7533f849b0511c60be45a4e75f3b0c1e373b 100644 (file)
@@ -233,6 +233,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
        info->apertures->ranges[0].size = cdev->mc.vram_size;
 
+       info->fix.smem_start = cdev->dev->mode_config.fb_base;
+       info->fix.smem_len = cdev->mc.vram_size;
+
        info->screen_base = sysram;
        info->screen_size = size;
 
index 78e76f24343d17bad9bc81e5474f900fbd090b33..4b0170cf53fd9225f07f731766cb8fe71fb40e91 100644 (file)
@@ -255,7 +255,7 @@ int cirrus_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void cirrus_bo_unref(struct cirrus_bo **bo)
+static void cirrus_bo_unref(struct cirrus_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index adabc3daaa5b4f644969944a28de07921ab1895d..530f78f84deed250a2f96350254657b49a0166c9 100644 (file)
@@ -102,7 +102,7 @@ static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
 }
 
-void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
+static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
 {
        struct cirrus_device *cdev = crtc->dev->dev_private;
        u32 addr;
@@ -273,8 +273,8 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
                sr07 |= 0x11;
                break;
        case 16:
-               sr07 |= 0xc1;
-               hdr = 0xc0;
+               sr07 |= 0x17;
+               hdr = 0xc1;
                break;
        case 24:
                sr07 |= 0x15;
@@ -453,7 +453,7 @@ static void cirrus_encoder_commit(struct drm_encoder *encoder)
 {
 }
 
-void cirrus_encoder_destroy(struct drm_encoder *encoder)
+static void cirrus_encoder_destroy(struct drm_encoder *encoder)
 {
        struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
        drm_encoder_cleanup(encoder);
@@ -492,7 +492,7 @@ static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
 }
 
 
-int cirrus_vga_get_modes(struct drm_connector *connector)
+static int cirrus_vga_get_modes(struct drm_connector *connector)
 {
        int count;
 
@@ -509,7 +509,7 @@ static int cirrus_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
+static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
                                                  *connector)
 {
        int enc_id = connector->encoder_ids[0];
index 75becdeac07d710e1322a64096df65850bf31fd4..8b37c25ff9bd0074810fc942fcee38fab3cbab4a 100644 (file)
@@ -80,7 +80,7 @@ static int cirrus_ttm_global_init(struct cirrus_device *cirrus)
        return 0;
 }
 
-void
+static void
 cirrus_ttm_global_release(struct cirrus_device *cirrus)
 {
        if (cirrus->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void cirrus_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
+static bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &cirrus_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func cirrus_tt_backend_func = {
 };
 
 
-struct ttm_tt *cirrus_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *cirrus_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
@@ -375,26 +375,6 @@ int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr)
        return 0;
 }
 
-int cirrus_bo_unpin(struct cirrus_bo *bo)
-{
-       int i, ret;
-       if (!bo->pin_count) {
-               DRM_ERROR("unpin bad %p\n", bo);
-               return 0;
-       }
-       bo->pin_count--;
-       if (bo->pin_count)
-               return 0;
-
-       for (i = 0; i < bo->placement.num_placement ; i++)
-               bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
-       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
 int cirrus_bo_push_sysram(struct cirrus_bo *bo)
 {
        int i, ret;
index e301d653d97e42f4537efdb50806cdc682930505..dde205cef384c08db92d114c16138c607ddc1da0 100644 (file)
@@ -53,7 +53,7 @@
  */
 int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
 {
-       DRM_AGP_KERN *kern;
+       struct agp_kern_info *kern;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
@@ -198,17 +198,15 @@ int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
 int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
        struct drm_agp_mem *entry;
-       DRM_AGP_MEM *memory;
+       struct agp_memory *memory;
        unsigned long pages;
        u32 type;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
-       if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
+       if (!(entry = kzalloc(sizeof(*entry), GFP_KERNEL)))
                return -ENOMEM;
 
-       memset(entry, 0, sizeof(*entry));
-
        pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
        type = (u32) request->type;
        if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) {
@@ -393,14 +391,16 @@ int drm_agp_free_ioctl(struct drm_device *dev, void *data,
  * Gets the drm_agp_t structure which is made available by the agpgart module
  * via the inter_module_* functions. Creates and initializes a drm_agp_head
  * structure.
+ *
+ * Note that final cleanup of the kmalloced structure is directly done in
+ * drm_pci_agp_destroy.
  */
 struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
        struct drm_agp_head *head = NULL;
 
-       if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
+       if (!(head = kzalloc(sizeof(*head), GFP_KERNEL)))
                return NULL;
-       memset((void *)head, 0, sizeof(*head));
        head->bridge = agp_find_bridge(dev->pdev);
        if (!head->bridge) {
                if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
@@ -439,7 +439,7 @@ void drm_agp_clear(struct drm_device *dev)
 {
        struct drm_agp_mem *entry, *tempe;
 
-       if (!drm_core_has_AGP(dev) || !dev->agp)
+       if (!dev->agp)
                return;
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return;
@@ -459,21 +459,6 @@ void drm_agp_clear(struct drm_device *dev)
        dev->agp->enabled = 0;
 }
 
-/**
- * drm_agp_destroy - Destroy AGP head
- * @dev: DRM device
- *
- * Destroy resources that were previously allocated via drm_agp_initp. Caller
- * must ensure to clean up all AGP resources before calling this. See
- * drm_agp_clear().
- *
- * Call this to destroy AGP heads allocated via drm_agp_init().
- */
-void drm_agp_destroy(struct drm_agp_head *agp)
-{
-       kfree(agp);
-}
-
 /**
  * Binds a collection of pages into AGP memory at the given offset, returning
  * the AGP memory structure containing them.
@@ -481,14 +466,14 @@ void drm_agp_destroy(struct drm_agp_head *agp)
  * No reference is held on the pages during this time -- it is up to the
  * caller to handle that.
  */
-DRM_AGP_MEM *
+struct agp_memory *
 drm_agp_bind_pages(struct drm_device *dev,
                   struct page **pages,
                   unsigned long num_pages,
                   uint32_t gtt_offset,
                   u32 type)
 {
-       DRM_AGP_MEM *mem;
+       struct agp_memory *mem;
        int ret, i;
 
        DRM_DEBUG("\n");
index 39a718340319ea13ce3f813ea30b82d60c0b9264..0406110f83edd2ac3f607fe575c8e7b6c491e88a 100644 (file)
@@ -114,7 +114,7 @@ int drm_buffer_copy_from_user(struct drm_buffer *buf,
 
        for (idx = 0; idx < nr_pages; ++idx) {
 
-               if (DRM_COPY_FROM_USER(buf->data[idx],
+               if (copy_from_user(buf->data[idx],
                        user_data + idx * PAGE_SIZE,
                        min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
                        DRM_ERROR("Failed to copy user data (%p) to drm buffer"
index 471e051d295e383b61ebb2a2a19c0e0d67d8827a..edec31fe3fed865aa2669e7c8e17aec912a82058 100644 (file)
@@ -261,7 +261,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
                struct drm_agp_mem *entry;
                int valid = 0;
 
-               if (!drm_core_has_AGP(dev)) {
+               if (!dev->agp) {
                        kfree(map);
                        return -EINVAL;
                }
@@ -303,9 +303,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 
                break;
        }
-       case _DRM_GEM:
-               DRM_ERROR("tried to addmap GEM object\n");
-               break;
        case _DRM_SCATTER_GATHER:
                if (!dev->sg) {
                        kfree(map);
@@ -483,9 +480,6 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
                dmah.size = map->size;
                __drm_pci_free(dev, &dmah);
                break;
-       case _DRM_GEM:
-               DRM_ERROR("tried to rmmap GEM object\n");
-               break;
        }
        kfree(map);
 
@@ -1396,7 +1390,7 @@ int drm_mapbufs(struct drm_device *dev, void *data,
        spin_unlock(&dev->count_lock);
 
        if (request->count >= dma->buf_count) {
-               if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+               if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP))
                    || (drm_core_check_feature(dev, DRIVER_SG)
                        && (dma->flags & _DRM_DMA_USE_SG))) {
                        struct drm_local_map *map = dev->agp_buffer_map;
index d6cf77c472e710cf246193dca874bd3b8bc72b9e..266a01d7f6353db7a5e28d23a86215e85bf18d78 100644 (file)
@@ -2767,10 +2767,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (fb->funcs->dirty) {
-               drm_modeset_lock_all(dev);
                ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
                                       clips, num_clips);
-               drm_modeset_unlock_all(dev);
        } else {
                ret = -ENOSYS;
        }
index 01361aba033b4a39888a41bc15c4a7f5e4052152..245fe4fa9c9edd5b36ca2448652020558edb3e8c 100644 (file)
@@ -536,7 +536,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
         * are later needed by vblank and swap-completion
         * timestamping. They are derived from true hwmode.
         */
-       drm_calc_timestamping_constants(crtc);
+       drm_calc_timestamping_constants(crtc, &crtc->hwmode);
 
        /* FIXME: add subpixel order */
 done:
index d9137e49c4e81594a992297a1dd10181006faf06..345be03c23db27203d4ce69bd74586a77e8f6ab1 100644 (file)
@@ -315,9 +315,6 @@ long drm_ioctl(struct file *filp,
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
-       atomic_inc(&dev->ioctl_count);
-       ++file_priv->ioctl_count;
-
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
                goto err_i1;
@@ -410,7 +407,6 @@ long drm_ioctl(struct file *filp,
 
        if (kdata != stack_kdata)
                kfree(kdata);
-       atomic_dec(&dev->ioctl_count);
        if (retcode)
                DRM_DEBUG("ret = %d\n", retcode);
        return retcode;
index 8835dcddfac3ab7c3ee1a4ba72360443e730aa74..b924306b84775f39592887a632f76553297c5a57 100644 (file)
@@ -605,347 +605,347 @@ static const struct drm_display_mode edid_cea_modes[] = {
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
                   752, 800, 0, 480, 490, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 2 - 720x480@60Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 3 - 720x480@60Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 4 - 1280x720@60Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 5 - 1920x1080i@60Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 6 - 1440x480i@60Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 7 - 1440x480i@60Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 8 - 1440x240@60Hz */
        { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 9 - 1440x240@60Hz */
        { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 10 - 2880x480i@60Hz */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 11 - 2880x480i@60Hz */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 12 - 2880x240@60Hz */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 13 - 2880x240@60Hz */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 14 - 1440x480@60Hz */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 15 - 1440x480@60Hz */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 16 - 1920x1080@60Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 17 - 720x576@50Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 18 - 720x576@50Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 19 - 1280x720@50Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 20 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 21 - 1440x576i@50Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 22 - 1440x576i@50Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 23 - 1440x288@50Hz */
        { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 24 - 1440x288@50Hz */
        { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 25 - 2880x576i@50Hz */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 26 - 2880x576i@50Hz */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 27 - 2880x288@50Hz */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 28 - 2880x288@50Hz */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 29 - 1440x576@50Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 30 - 1440x576@50Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 31 - 1920x1080@50Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 32 - 1920x1080@24Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
                   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 24, },
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 33 - 1920x1080@25Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 25, },
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 34 - 1920x1080@30Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 30, },
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 35 - 2880x480@60Hz */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 36 - 2880x480@60Hz */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 37 - 2880x576@50Hz */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 38 - 2880x576@50Hz */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 39 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
                   2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 40 - 1920x1080i@100Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 41 - 1280x720@100Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 42 - 720x576@100Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 43 - 720x576@100Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 44 - 1440x576i@100Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 45 - 1440x576i@100Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 46 - 1920x1080i@120Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 47 - 1280x720@120Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 48 - 720x480@120Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 49 - 720x480@120Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 50 - 1440x480i@120Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 51 - 1440x480i@120Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 52 - 720x576@200Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 53 - 720x576@200Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 54 - 1440x576i@200Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 55 - 1440x576i@200Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 56 - 720x480@240Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 57 - 720x480@240Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 58 - 1440x480i@240 */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 59 - 1440x480i@240 */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 60 - 1280x720@24Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 24, },
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 61 - 1280x720@25Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
                   3740, 3960, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 25, },
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 62 - 1280x720@30Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 30, },
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 63 - 1920x1080@120Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 120, },
+        .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 64 - 1920x1080@100Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 100, },
+        .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 };
 
 /*
@@ -2562,25 +2562,40 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
        return modes;
 }
 
-static int
-do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
+static struct drm_display_mode *
+drm_display_mode_from_vic_index(struct drm_connector *connector,
+                               const u8 *video_db, u8 video_len,
+                               u8 video_index)
 {
        struct drm_device *dev = connector->dev;
-       const u8 *mode;
+       struct drm_display_mode *newmode;
        u8 cea_mode;
-       int modes = 0;
 
-       for (mode = db; mode < db + len; mode++) {
-               cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */
-               if (cea_mode < ARRAY_SIZE(edid_cea_modes)) {
-                       struct drm_display_mode *newmode;
-                       newmode = drm_mode_duplicate(dev,
-                                                    &edid_cea_modes[cea_mode]);
-                       if (newmode) {
-                               newmode->vrefresh = 0;
-                               drm_mode_probed_add(connector, newmode);
-                               modes++;
-                       }
+       if (video_db == NULL || video_index >= video_len)
+               return NULL;
+
+       /* CEA modes are numbered 1..127 */
+       cea_mode = (video_db[video_index] & 127) - 1;
+       if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
+               return NULL;
+
+       newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+       newmode->vrefresh = 0;
+
+       return newmode;
+}
+
+static int
+do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
+{
+       int i, modes = 0;
+
+       for (i = 0; i < len; i++) {
+               struct drm_display_mode *mode;
+               mode = drm_display_mode_from_vic_index(connector, db, len, i);
+               if (mode) {
+                       drm_mode_probed_add(connector, mode);
+                       modes++;
                }
        }
 
@@ -2674,21 +2689,13 @@ static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
 static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                               const u8 *video_db, u8 video_len, u8 video_index)
 {
-       struct drm_device *dev = connector->dev;
        struct drm_display_mode *newmode;
        int modes = 0;
-       u8 cea_mode;
-
-       if (video_db == NULL || video_index >= video_len)
-               return 0;
-
-       /* CEA modes are numbered 1..127 */
-       cea_mode = (video_db[video_index] & 127) - 1;
-       if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
-               return 0;
 
        if (structure & (1 << 0)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
                        drm_mode_probed_add(connector, newmode);
@@ -2696,7 +2703,9 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                }
        }
        if (structure & (1 << 6)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
                        drm_mode_probed_add(connector, newmode);
@@ -2704,7 +2713,9 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                }
        }
        if (structure & (1 << 8)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
                        drm_mode_probed_add(connector, newmode);
@@ -2728,7 +2739,7 @@ static int
 do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
                   const u8 *video_db, u8 video_len)
 {
-       int modes = 0, offset = 0, i, multi_present = 0;
+       int modes = 0, offset = 0, i, multi_present = 0, multi_len;
        u8 vic_len, hdmi_3d_len = 0;
        u16 mask;
        u16 structure_all;
@@ -2774,32 +2785,84 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
        }
        offset += 1 + vic_len;
 
-       if (!(multi_present == 1 || multi_present == 2))
-               goto out;
+       if (multi_present == 1)
+               multi_len = 2;
+       else if (multi_present == 2)
+               multi_len = 4;
+       else
+               multi_len = 0;
 
-       if ((multi_present == 1 && len < (9 + offset)) ||
-           (multi_present == 2 && len < (11 + offset)))
+       if (len < (8 + offset + hdmi_3d_len - 1))
                goto out;
 
-       if ((multi_present == 1 && hdmi_3d_len < 2) ||
-           (multi_present == 2 && hdmi_3d_len < 4))
+       if (hdmi_3d_len < multi_len)
                goto out;
 
-       /* 3D_Structure_ALL */
-       structure_all = (db[8 + offset] << 8) | db[9 + offset];
+       if (multi_present == 1 || multi_present == 2) {
+               /* 3D_Structure_ALL */
+               structure_all = (db[8 + offset] << 8) | db[9 + offset];
 
-       /* check if 3D_MASK is present */
-       if (multi_present == 2)
-               mask = (db[10 + offset] << 8) | db[11 + offset];
-       else
-               mask = 0xffff;
-
-       for (i = 0; i < 16; i++) {
-               if (mask & (1 << i))
-                       modes += add_3d_struct_modes(connector,
-                                                    structure_all,
-                                                    video_db,
-                                                    video_len, i);
+               /* check if 3D_MASK is present */
+               if (multi_present == 2)
+                       mask = (db[10 + offset] << 8) | db[11 + offset];
+               else
+                       mask = 0xffff;
+
+               for (i = 0; i < 16; i++) {
+                       if (mask & (1 << i))
+                               modes += add_3d_struct_modes(connector,
+                                               structure_all,
+                                               video_db,
+                                               video_len, i);
+               }
+       }
+
+       offset += multi_len;
+
+       for (i = 0; i < (hdmi_3d_len - multi_len); i++) {
+               int vic_index;
+               struct drm_display_mode *newmode = NULL;
+               unsigned int newflag = 0;
+               bool detail_present;
+
+               detail_present = ((db[8 + offset + i] & 0x0f) > 7);
+
+               if (detail_present && (i + 1 == hdmi_3d_len - multi_len))
+                       break;
+
+               /* 2D_VIC_order_X */
+               vic_index = db[8 + offset + i] >> 4;
+
+               /* 3D_Structure_X */
+               switch (db[8 + offset + i] & 0x0f) {
+               case 0:
+                       newflag = DRM_MODE_FLAG_3D_FRAME_PACKING;
+                       break;
+               case 6:
+                       newflag = DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
+                       break;
+               case 8:
+                       /* 3D_Detail_X */
+                       if ((db[9 + offset + i] >> 4) == 1)
+                               newflag = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+                       break;
+               }
+
+               if (newflag != 0) {
+                       newmode = drm_display_mode_from_vic_index(connector,
+                                                                 video_db,
+                                                                 video_len,
+                                                                 vic_index);
+
+                       if (newmode) {
+                               newmode->flags |= newflag;
+                               drm_mode_probed_add(connector, newmode);
+                               modes++;
+                       }
+               }
+
+               if (detail_present)
+                       i++;
        }
 
 out:
index 9081172ef0573a0eb1b17ac8e3681b0c559486cc..1b4c7a5442c5de22210925c2cea8317790340b04 100644 (file)
@@ -141,7 +141,7 @@ static int edid_size(const u8 *edid, int data_size)
        return (edid[0x7e] + 1) * EDID_LENGTH;
 }
 
-static u8 *edid_load(struct drm_connector *connector, const char *name,
+static void *edid_load(struct drm_connector *connector, const char *name,
                        const char *connector_name)
 {
        const struct firmware *fw = NULL;
@@ -263,7 +263,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
        if (*last == '\n')
                *last = '\0';
 
-       edid = (struct edid *) edid_load(connector, edidname, connector_name);
+       edid = edid_load(connector, edidname, connector_name);
        if (IS_ERR_OR_NULL(edid))
                return 0;
 
index 0a19401aff803bcf2a1ff4dddcbd1fab42a0a187..98a03639b413d834d08c5c73c0ef08cec3d37c55 100644 (file)
@@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
        struct drm_crtc *crtc;
        int bound = 0, crtcs_bound = 0;
 
+       /* Sometimes user space wants everything disabled, so don't steal the
+        * display if there's a master. */
+       if (dev->primary->master)
+               return false;
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (crtc->fb)
                        crtcs_bound++;
@@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 
        if (bound < crtcs_bound)
                return false;
+
        return true;
 }
 
index c5b929c3f77ae617d14fa87b387557bbf3cd3f7b..7f2af9aca03895b97c75af76968093a61930b501 100644 (file)
@@ -232,7 +232,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
                goto out_put_pid;
        }
 
-       priv->ioctl_count = 0;
        /* for compatibility root is always authenticated */
        priv->always_authenticated = capable(CAP_SYS_ADMIN);
        priv->authenticated = priv->always_authenticated;
@@ -392,9 +391,6 @@ static void drm_legacy_dev_reinit(struct drm_device *dev)
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
-       atomic_set(&dev->ioctl_count, 0);
-       atomic_set(&dev->vma_count, 0);
-
        dev->sigdata.lock = NULL;
 
        dev->context_flag = 0;
@@ -578,12 +574,7 @@ int drm_release(struct inode *inode, struct file *filp)
         */
 
        if (!--dev->open_count) {
-               if (atomic_read(&dev->ioctl_count)) {
-                       DRM_ERROR("Device busy: %d\n",
-                                 atomic_read(&dev->ioctl_count));
-                       retcode = -EBUSY;
-               } else
-                       retcode = drm_lastclose(dev);
+               retcode = drm_lastclose(dev);
                if (drm_device_is_unplugged(dev))
                        drm_put_dev(dev);
        }
index 4761adedad2abe5f03ae586354436f3bf1b32cbb..5bbad873c798a8e2168f50c33828f27828c378ed 100644 (file)
 int
 drm_gem_init(struct drm_device *dev)
 {
-       struct drm_gem_mm *mm;
+       struct drm_vma_offset_manager *vma_offset_manager;
 
        mutex_init(&dev->object_name_lock);
        idr_init(&dev->object_name_idr);
 
-       mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
-       if (!mm) {
+       vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL);
+       if (!vma_offset_manager) {
                DRM_ERROR("out of memory\n");
                return -ENOMEM;
        }
 
-       dev->mm_private = mm;
-       drm_vma_offset_manager_init(&mm->vma_manager,
+       dev->vma_offset_manager = vma_offset_manager;
+       drm_vma_offset_manager_init(vma_offset_manager,
                                    DRM_FILE_PAGE_OFFSET_START,
                                    DRM_FILE_PAGE_OFFSET_SIZE);
 
@@ -113,11 +113,10 @@ drm_gem_init(struct drm_device *dev)
 void
 drm_gem_destroy(struct drm_device *dev)
 {
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       drm_vma_offset_manager_destroy(&mm->vma_manager);
-       kfree(mm);
-       dev->mm_private = NULL;
+       drm_vma_offset_manager_destroy(dev->vma_offset_manager);
+       kfree(dev->vma_offset_manager);
+       dev->vma_offset_manager = NULL;
 }
 
 /**
@@ -129,11 +128,12 @@ int drm_gem_object_init(struct drm_device *dev,
 {
        struct file *filp;
 
+       drm_gem_private_object_init(dev, obj, size);
+
        filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
        if (IS_ERR(filp))
                return PTR_ERR(filp);
 
-       drm_gem_private_object_init(dev, obj, size);
        obj->filp = filp;
 
        return 0;
@@ -175,11 +175,6 @@ drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
        mutex_unlock(&filp->prime.lock);
 }
 
-static void drm_gem_object_ref_bug(struct kref *list_kref)
-{
-       BUG();
-}
-
 /**
  * Called after the last handle to the object has been closed
  *
@@ -195,13 +190,6 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj)
        if (obj->name) {
                idr_remove(&dev->object_name_idr, obj->name);
                obj->name = 0;
-               /*
-                * The object name held a reference to this object, drop
-                * that now.
-               *
-               * This cannot be the last reference, since the handle holds one too.
-                */
-               kref_put(&obj->refcount, drm_gem_object_ref_bug);
        }
 }
 
@@ -374,9 +362,8 @@ void
 drm_gem_free_mmap_offset(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       drm_vma_offset_remove(&mm->vma_manager, &obj->vma_node);
+       drm_vma_offset_remove(dev->vma_offset_manager, &obj->vma_node);
 }
 EXPORT_SYMBOL(drm_gem_free_mmap_offset);
 
@@ -398,9 +385,8 @@ int
 drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
+       return drm_vma_offset_add(dev->vma_offset_manager, &obj->vma_node,
                                  size / PAGE_SIZE);
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset_size);
@@ -602,9 +588,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
                        goto err;
 
                obj->name = ret;
-
-               /* Allocate a reference for the name table.  */
-               drm_gem_object_reference(obj);
        }
 
        args->name = (uint64_t) obj->name;
@@ -833,7 +816,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
        struct drm_device *dev = priv->minor->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
        struct drm_gem_object *obj;
        struct drm_vma_offset_node *node;
        int ret = 0;
@@ -843,7 +825,8 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 
        mutex_lock(&dev->struct_mutex);
 
-       node = drm_vma_offset_exact_lookup(&mm->vma_manager, vma->vm_pgoff,
+       node = drm_vma_offset_exact_lookup(dev->vma_offset_manager,
+                                          vma->vm_pgoff,
                                           vma_pages(vma));
        if (!node) {
                mutex_unlock(&dev->struct_mutex);
index 7d5a152eeb0288f05e5770a9699b92e253f689e4..7473035dd28b781ed8f382d0e8b6cd3743df772e 100644 (file)
@@ -186,14 +186,14 @@ int drm_clients_info(struct seq_file *m, void *data)
        struct drm_file *priv;
 
        mutex_lock(&dev->struct_mutex);
-       seq_printf(m, "a dev    pid    uid      magic     ioctls\n\n");
+       seq_printf(m, "a dev    pid    uid      magic\n\n");
        list_for_each_entry(priv, &dev->filelist, lhead) {
-               seq_printf(m, "%c %3d %5d %5d %10u %10lu\n",
+               seq_printf(m, "%c %3d %5d %5d %10u\n",
                           priv->authenticated ? 'y' : 'n',
                           priv->minor->index,
                           pid_vnr(priv->pid),
                           from_kuid_munged(seq_user_ns(m), priv->uid),
-                          priv->magic, priv->ioctl_count);
+                          priv->magic);
        }
        mutex_unlock(&dev->struct_mutex);
        return 0;
@@ -234,14 +234,18 @@ int drm_vma_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_vma_entry *pt;
        struct vm_area_struct *vma;
+       unsigned long vma_count = 0;
 #if defined(__i386__)
        unsigned int pgprot;
 #endif
 
        mutex_lock(&dev->struct_mutex);
-       seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
-                  atomic_read(&dev->vma_count),
-                  high_memory, (void *)(unsigned long)virt_to_phys(high_memory));
+       list_for_each_entry(pt, &dev->vmalist, head)
+               vma_count++;
+
+       seq_printf(m, "vma use count: %lu, high_memory = %pK, 0x%pK\n",
+                  vma_count, high_memory,
+                  (void *)(unsigned long)virt_to_phys(high_memory));
 
        list_for_each_entry(pt, &dev->vmalist, head) {
                vma = pt->vma;
index 64c34d5876ffc7c8378b3df4a389db203dd1c576..c2676b5908d9f6edbcf4dd8d9fb126cfb93cd5ab 100644 (file)
@@ -368,7 +368,7 @@ int drm_irq_uninstall(struct drm_device *dev)
        if (dev->num_crtcs) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                for (i = 0; i < dev->num_crtcs; i++) {
-                       DRM_WAKEUP(&dev->vblank[i].queue);
+                       wake_up(&dev->vblank[i].queue);
                        dev->vblank[i].enabled = false;
                        dev->vblank[i].last =
                                dev->driver->get_vblank_counter(dev, i);
@@ -436,45 +436,41 @@ int drm_control(struct drm_device *dev, void *data,
 }
 
 /**
- * drm_calc_timestamping_constants - Calculate and
- * store various constants which are later needed by
- * vblank and swap-completion timestamping, e.g, by
- * drm_calc_vbltimestamp_from_scanoutpos().
- * They are derived from crtc's true scanout timing,
- * so they take things like panel scaling or other
- * adjustments into account.
+ * drm_calc_timestamping_constants - Calculate vblank timestamp constants
  *
  * @crtc drm_crtc whose timestamp constants should be updated.
+ * @mode display mode containing the scanout timings
  *
+ * Calculate and store various constants which are later
+ * needed by vblank and swap-completion timestamping, e.g,
+ * by drm_calc_vbltimestamp_from_scanoutpos(). They are
+ * derived from crtc's true scanout timing, so they take
+ * things like panel scaling or other adjustments into account.
  */
-void drm_calc_timestamping_constants(struct drm_crtc *crtc)
+void drm_calc_timestamping_constants(struct drm_crtc *crtc,
+                                    const struct drm_display_mode *mode)
 {
-       s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
-       u64 dotclock;
-
-       /* Dot clock in Hz: */
-       dotclock = (u64) crtc->hwmode.clock * 1000;
-
-       /* Fields of interlaced scanout modes are only half a frame duration.
-        * Double the dotclock to get half the frame-/line-/pixelduration.
-        */
-       if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE)
-               dotclock *= 2;
+       int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
+       int dotclock = mode->crtc_clock;
 
        /* Valid dotclock? */
        if (dotclock > 0) {
-               int frame_size;
-               /* Convert scanline length in pixels and video dot clock to
-                * line duration, frame duration and pixel duration in
-                * nanoseconds:
+               int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
+
+               /*
+                * Convert scanline length in pixels and video
+                * dot clock to line duration, frame duration
+                * and pixel duration in nanoseconds:
                 */
-               pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
-               linedur_ns  = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
-                                             1000000000), dotclock);
-               frame_size = crtc->hwmode.crtc_htotal *
-                               crtc->hwmode.crtc_vtotal;
-               framedur_ns = (s64) div64_u64((u64) frame_size * 1000000000,
-                                             dotclock);
+               pixeldur_ns = 1000000 / dotclock;
+               linedur_ns  = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
+               framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
+
+               /*
+                * Fields of interlaced scanout modes are only half a frame duration.
+                */
+               if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+                       framedur_ns /= 2;
        } else
                DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
                          crtc->base.id);
@@ -484,11 +480,11 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc)
        crtc->framedur_ns = framedur_ns;
 
        DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
-                 crtc->base.id, crtc->hwmode.crtc_htotal,
-                 crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay);
+                 crtc->base.id, mode->crtc_htotal,
+                 mode->crtc_vtotal, mode->crtc_vdisplay);
        DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
-                 crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
-                 (int) linedur_ns, (int) pixeldur_ns);
+                 crtc->base.id, dotclock, framedur_ns,
+                 linedur_ns, pixeldur_ns);
 }
 EXPORT_SYMBOL(drm_calc_timestamping_constants);
 
@@ -521,6 +517,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  *         0 = Default.
  *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
  * @refcrtc: drm_crtc* of crtc which defines scanout timing.
+ * @mode: mode which defines the scanout timings
  *
  * Returns negative value on error, failure or if not supported in current
  * video mode:
@@ -540,14 +537,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                                          int *max_error,
                                          struct timeval *vblank_time,
                                          unsigned flags,
-                                         struct drm_crtc *refcrtc)
+                                         const struct drm_crtc *refcrtc,
+                                         const struct drm_display_mode *mode)
 {
        ktime_t stime, etime, mono_time_offset;
        struct timeval tv_etime;
-       struct drm_display_mode *mode;
-       int vbl_status, vtotal, vdisplay;
+       int vbl_status;
        int vpos, hpos, i;
-       s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
+       int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
        bool invbl;
 
        if (crtc < 0 || crtc >= dev->num_crtcs) {
@@ -561,10 +558,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                return -EIO;
        }
 
-       mode = &refcrtc->hwmode;
-       vtotal = mode->crtc_vtotal;
-       vdisplay = mode->crtc_vdisplay;
-
        /* Durations of frames, lines, pixels in nanoseconds. */
        framedur_ns = refcrtc->framedur_ns;
        linedur_ns  = refcrtc->linedur_ns;
@@ -573,7 +566,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
        /* If mode timing undefined, just return as no-op:
         * Happens during initial modesetting of a crtc.
         */
-       if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) {
+       if (framedur_ns == 0) {
                DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
                return -EAGAIN;
        }
@@ -590,7 +583,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                 * Get vertical and horizontal scanout position vpos, hpos,
                 * and bounding timestamps stime, etime, pre/post query.
                 */
-               vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos,
+               vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
                                                               &hpos, &stime, &etime);
 
                /*
@@ -611,18 +604,18 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
 
                /* Accept result with <  max_error nsecs timing uncertainty. */
-               if (duration_ns <= (s64) *max_error)
+               if (duration_ns <= *max_error)
                        break;
        }
 
        /* Noisy system timing? */
        if (i == DRM_TIMESTAMP_MAXRETRIES) {
                DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
-                         crtc, (int) duration_ns/1000, *max_error/1000, i);
+                         crtc, duration_ns/1000, *max_error/1000, i);
        }
 
        /* Return upper bound of timestamp precision error. */
-       *max_error = (int) duration_ns;
+       *max_error = duration_ns;
 
        /* Check if in vblank area:
         * vpos is >=0 in video scanout area, but negative
@@ -635,25 +628,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
         * since start of scanout at first display scanline. delta_ns
         * can be negative if start of scanout hasn't happened yet.
         */
-       delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
-
-       /* Is vpos outside nominal vblank area, but less than
-        * 1/100 of a frame height away from start of vblank?
-        * If so, assume this isn't a massively delayed vblank
-        * interrupt, but a vblank interrupt that fired a few
-        * microseconds before true start of vblank. Compensate
-        * by adding a full frame duration to the final timestamp.
-        * Happens, e.g., on ATI R500, R600.
-        *
-        * We only do this if DRM_CALLED_FROM_VBLIRQ.
-        */
-       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
-           ((vdisplay - vpos) < vtotal / 100)) {
-               delta_ns = delta_ns - framedur_ns;
-
-               /* Signal this correction as "applied". */
-               vbl_status |= 0x8;
-       }
+       delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
 
        if (!drm_timestamp_monotonic)
                etime = ktime_sub(etime, mono_time_offset);
@@ -673,7 +648,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                  crtc, (int)vbl_status, hpos, vpos,
                  (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
                  (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
-                 (int)duration_ns/1000, i);
+                 duration_ns/1000, i);
 
        vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
        if (invbl)
@@ -960,7 +935,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
        if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
            (drm_vblank_offdelay > 0))
                mod_timer(&dev->vblank_disable_timer,
-                         jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
+                         jiffies + ((drm_vblank_offdelay * HZ)/1000));
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
@@ -980,7 +955,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        vblank_disable_and_save(dev, crtc);
-       DRM_WAKEUP(&dev->vblank[crtc].queue);
+       wake_up(&dev->vblank[crtc].queue);
 
        /* Send any queued vblank events, lest the natives grow disquiet */
        seq = drm_vblank_count_and_time(dev, crtc, &now);
@@ -1244,7 +1219,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
                  vblwait->request.sequence, crtc);
        dev->vblank[crtc].last_wait = vblwait->request.sequence;
-       DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ,
                    (((drm_vblank_count(dev, crtc) -
                       vblwait->request.sequence) <= (1 << 23)) ||
                     !dev->irq_enabled));
@@ -1363,7 +1338,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
                          crtc, (int) diff_ns);
        }
 
-       DRM_WAKEUP(&dev->vblank[crtc].queue);
+       wake_up(&dev->vblank[crtc].queue);
        drm_handle_vblank_events(dev, crtc);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
index 64e44fad8ae84282d43f449d21772c4346acab68..00c67c0f238127d1d36c8ba17e6caf184412c446 100644 (file)
@@ -82,19 +82,19 @@ static void *agp_remap(unsigned long offset, unsigned long size,
 }
 
 /** Wrapper around agp_free_memory() */
-void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+void drm_free_agp(struct agp_memory * handle, int pages)
 {
        agp_free_memory(handle);
 }
 
 /** Wrapper around agp_bind_memory() */
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+int drm_bind_agp(struct agp_memory * handle, unsigned int start)
 {
        return agp_bind_memory(handle, start);
 }
 
 /** Wrapper around agp_unbind_memory() */
-int drm_unbind_agp(DRM_AGP_MEM * handle)
+int drm_unbind_agp(struct agp_memory * handle)
 {
        return agp_unbind_memory(handle);
 }
@@ -110,8 +110,7 @@ static inline void *agp_remap(unsigned long offset, unsigned long size,
 
 void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                map->handle = agp_remap(map->offset, map->size, dev);
        else
                map->handle = ioremap(map->offset, map->size);
@@ -120,8 +119,7 @@ EXPORT_SYMBOL(drm_core_ioremap);
 
 void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                map->handle = agp_remap(map->offset, map->size, dev);
        else
                map->handle = ioremap_wc(map->offset, map->size);
@@ -133,8 +131,7 @@ void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
        if (!map->handle || !map->size)
                return;
 
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                vunmap(map->handle);
        else
                iounmap(map->handle);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
new file mode 100644 (file)
index 0000000..b155ee2
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * MIPI DSI Bus
+ *
+ * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ */
+
+#include <drm/drm_mipi_dsi.h>
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include <video/mipi_display.h>
+
+static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
+{
+       return of_driver_match_device(dev, drv);
+}
+
+static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
+       .runtime_suspend = pm_generic_runtime_suspend,
+       .runtime_resume = pm_generic_runtime_resume,
+       .suspend = pm_generic_suspend,
+       .resume = pm_generic_resume,
+       .freeze = pm_generic_freeze,
+       .thaw = pm_generic_thaw,
+       .poweroff = pm_generic_poweroff,
+       .restore = pm_generic_restore,
+};
+
+static struct bus_type mipi_dsi_bus_type = {
+       .name = "mipi-dsi",
+       .match = mipi_dsi_device_match,
+       .pm = &mipi_dsi_device_pm_ops,
+};
+
+static void mipi_dsi_dev_release(struct device *dev)
+{
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+
+       of_node_put(dev->of_node);
+       kfree(dsi);
+}
+
+static const struct device_type mipi_dsi_device_type = {
+       .release = mipi_dsi_dev_release,
+};
+
+static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
+{
+       struct mipi_dsi_device *dsi;
+
+       dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
+       if (!dsi)
+               return ERR_PTR(-ENOMEM);
+
+       dsi->host = host;
+       dsi->dev.bus = &mipi_dsi_bus_type;
+       dsi->dev.parent = host->dev;
+       dsi->dev.type = &mipi_dsi_device_type;
+
+       device_initialize(&dsi->dev);
+
+       return dsi;
+}
+
+static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
+{
+       struct mipi_dsi_host *host = dsi->host;
+
+       dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
+
+       return device_add(&dsi->dev);
+}
+
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+       struct mipi_dsi_device *dsi;
+       struct device *dev = host->dev;
+       int ret;
+       u32 reg;
+
+       ret = of_property_read_u32(node, "reg", &reg);
+       if (ret) {
+               dev_err(dev, "device node %s has no valid reg property: %d\n",
+                       node->full_name, ret);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (reg > 3) {
+               dev_err(dev, "device node %s has invalid reg property: %u\n",
+                       node->full_name, reg);
+               return ERR_PTR(-EINVAL);
+       }
+
+       dsi = mipi_dsi_device_alloc(host);
+       if (IS_ERR(dsi)) {
+               dev_err(dev, "failed to allocate DSI device %s: %ld\n",
+                       node->full_name, PTR_ERR(dsi));
+               return dsi;
+       }
+
+       dsi->dev.of_node = of_node_get(node);
+       dsi->channel = reg;
+
+       ret = mipi_dsi_device_add(dsi);
+       if (ret) {
+               dev_err(dev, "failed to add DSI device %s: %d\n",
+                       node->full_name, ret);
+               kfree(dsi);
+               return ERR_PTR(ret);
+       }
+
+       return dsi;
+}
+
+int mipi_dsi_host_register(struct mipi_dsi_host *host)
+{
+       struct device_node *node;
+
+       for_each_available_child_of_node(host->dev->of_node, node)
+               of_mipi_dsi_device_add(host, node);
+
+       return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_host_register);
+
+static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
+{
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+
+       device_unregister(&dsi->dev);
+
+       return 0;
+}
+
+void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
+{
+       device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+}
+EXPORT_SYMBOL(mipi_dsi_host_unregister);
+
+/**
+ * mipi_dsi_attach - attach a DSI device to its DSI host
+ * @dsi: DSI peripheral
+ */
+int mipi_dsi_attach(struct mipi_dsi_device *dsi)
+{
+       const struct mipi_dsi_host_ops *ops = dsi->host->ops;
+
+       if (!ops || !ops->attach)
+               return -ENOSYS;
+
+       return ops->attach(dsi->host, dsi);
+}
+EXPORT_SYMBOL(mipi_dsi_attach);
+
+/**
+ * mipi_dsi_detach - detach a DSI device from its DSI host
+ * @dsi: DSI peripheral
+ */
+int mipi_dsi_detach(struct mipi_dsi_device *dsi)
+{
+       const struct mipi_dsi_host_ops *ops = dsi->host->ops;
+
+       if (!ops || !ops->detach)
+               return -ENOSYS;
+
+       return ops->detach(dsi->host, dsi);
+}
+EXPORT_SYMBOL(mipi_dsi_detach);
+
+/**
+ * mipi_dsi_dcs_write - send DCS write command
+ * @dsi: DSI device
+ * @channel: virtual channel
+ * @data: pointer to the command followed by parameters
+ * @len: length of @data
+ */
+int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel,
+                      const void *data, size_t len)
+{
+       const struct mipi_dsi_host_ops *ops = dsi->host->ops;
+       struct mipi_dsi_msg msg = {
+               .channel = channel,
+               .tx_buf = data,
+               .tx_len = len
+       };
+
+       if (!ops || !ops->transfer)
+               return -ENOSYS;
+
+       switch (len) {
+       case 0:
+               return -EINVAL;
+       case 1:
+               msg.type = MIPI_DSI_DCS_SHORT_WRITE;
+               break;
+       case 2:
+               msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+               break;
+       default:
+               msg.type = MIPI_DSI_DCS_LONG_WRITE;
+               break;
+       }
+
+       return ops->transfer(dsi->host, &msg);
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write);
+
+/**
+ * mipi_dsi_dcs_read - send DCS read request command
+ * @dsi: DSI device
+ * @channel: virtual channel
+ * @cmd: DCS read command
+ * @data: pointer to read buffer
+ * @len: length of @data
+ *
+ * Function returns number of read bytes or error code.
+ */
+ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel,
+                         u8 cmd, void *data, size_t len)
+{
+       const struct mipi_dsi_host_ops *ops = dsi->host->ops;
+       struct mipi_dsi_msg msg = {
+               .channel = channel,
+               .type = MIPI_DSI_DCS_READ,
+               .tx_buf = &cmd,
+               .tx_len = 1,
+               .rx_buf = data,
+               .rx_len = len
+       };
+
+       if (!ops || !ops->transfer)
+               return -ENOSYS;
+
+       return ops->transfer(dsi->host, &msg);
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_read);
+
+static int mipi_dsi_drv_probe(struct device *dev)
+{
+       struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+
+       return drv->probe(dsi);
+}
+
+static int mipi_dsi_drv_remove(struct device *dev)
+{
+       struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+
+       return drv->remove(dsi);
+}
+
+/**
+ * mipi_dsi_driver_register - register a driver for DSI devices
+ * @drv: DSI driver structure
+ */
+int mipi_dsi_driver_register(struct mipi_dsi_driver *drv)
+{
+       drv->driver.bus = &mipi_dsi_bus_type;
+       if (drv->probe)
+               drv->driver.probe = mipi_dsi_drv_probe;
+       if (drv->remove)
+               drv->driver.remove = mipi_dsi_drv_remove;
+
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(mipi_dsi_driver_register);
+
+/**
+ * mipi_dsi_driver_unregister - unregister a driver for DSI devices
+ * @drv: DSI driver structure
+ */
+void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(mipi_dsi_driver_unregister);
+
+static int __init mipi_dsi_bus_init(void)
+{
+       return bus_register(&mipi_dsi_bus_type);
+}
+postcore_initcall(mipi_dsi_bus_init);
+
+MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
+MODULE_DESCRIPTION("MIPI DSI Bus");
+MODULE_LICENSE("GPL and additional rights");
index 85071a1c4547921f53fd5372c2664a3066d00ef4..b0733153dfd294f178ff1818618fadbe63a1d144 100644 (file)
@@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
                                /* if equal delete the probed mode */
                                mode->status = pmode->status;
                                /* Merge type bits together */
-                               mode->type = pmode->type;
+                               mode->type |= pmode->type;
                                list_del(&pmode->head);
                                drm_mode_destroy(connector->dev, pmode);
                                break;
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
new file mode 100644 (file)
index 0000000..2ef988e
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013, NVIDIA 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, sub license,
+ * 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 NON-INFRINGEMENT. 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.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_panel.h>
+
+static DEFINE_MUTEX(panel_lock);
+static LIST_HEAD(panel_list);
+
+void drm_panel_init(struct drm_panel *panel)
+{
+       INIT_LIST_HEAD(&panel->list);
+}
+EXPORT_SYMBOL(drm_panel_init);
+
+int drm_panel_add(struct drm_panel *panel)
+{
+       mutex_lock(&panel_lock);
+       list_add_tail(&panel->list, &panel_list);
+       mutex_unlock(&panel_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_panel_add);
+
+void drm_panel_remove(struct drm_panel *panel)
+{
+       mutex_lock(&panel_lock);
+       list_del_init(&panel->list);
+       mutex_unlock(&panel_lock);
+}
+EXPORT_SYMBOL(drm_panel_remove);
+
+int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
+{
+       if (panel->connector)
+               return -EBUSY;
+
+       panel->connector = connector;
+       panel->drm = connector->dev;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_panel_attach);
+
+int drm_panel_detach(struct drm_panel *panel)
+{
+       panel->connector = NULL;
+       panel->drm = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_panel_detach);
+
+#ifdef CONFIG_OF
+struct drm_panel *of_drm_find_panel(struct device_node *np)
+{
+       struct drm_panel *panel;
+
+       mutex_lock(&panel_lock);
+
+       list_for_each_entry(panel, &panel_list, list) {
+               if (panel->dev->of_node == np) {
+                       mutex_unlock(&panel_lock);
+                       return panel;
+               }
+       }
+
+       mutex_unlock(&panel_lock);
+       return NULL;
+}
+EXPORT_SYMBOL(of_drm_find_panel);
+#endif
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("DRM panel infrastructure");
+MODULE_LICENSE("GPL and additional rights");
index 02679793c9e2e73d3d175136bbfb638a7cd0784f..5736aaa7e86cb069d30fd458b5842fd42defae17 100644 (file)
@@ -262,16 +262,11 @@ static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
        return 0;
 }
 
-static int drm_pci_agp_init(struct drm_device *dev)
+static void drm_pci_agp_init(struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev)) {
+       if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
                if (drm_pci_device_is_agp(dev))
                        dev->agp = drm_agp_init(dev);
-               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-                   && (dev->agp == NULL)) {
-                       DRM_ERROR("Cannot initialize the agpgart module.\n");
-                       return -EINVAL;
-               }
                if (dev->agp) {
                        dev->agp->agp_mtrr = arch_phys_wc_add(
                                dev->agp->agp_info.aper_base,
@@ -279,15 +274,14 @@ static int drm_pci_agp_init(struct drm_device *dev)
                                1024 * 1024);
                }
        }
-       return 0;
 }
 
-static void drm_pci_agp_destroy(struct drm_device *dev)
+void drm_pci_agp_destroy(struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) && dev->agp) {
+       if (dev->agp) {
                arch_phys_wc_del(dev->agp->agp_mtrr);
                drm_agp_clear(dev);
-               drm_agp_destroy(dev->agp);
+               kfree(dev->agp);
                dev->agp = NULL;
        }
 }
@@ -299,8 +293,6 @@ static struct drm_bus drm_pci_bus = {
        .set_busid = drm_pci_set_busid,
        .set_unique = drm_pci_set_unique,
        .irq_by_busid = drm_pci_irq_by_busid,
-       .agp_init = drm_pci_agp_init,
-       .agp_destroy = drm_pci_agp_destroy,
 };
 
 /**
@@ -338,17 +330,25 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                pci_set_drvdata(pdev, dev);
 
+       drm_pci_agp_init(dev);
+
        ret = drm_dev_register(dev, ent->driver_data);
        if (ret)
-               goto err_pci;
+               goto err_agp;
 
        DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
                 driver->date, pci_name(pdev), dev->primary->index);
 
+       /* No locking needed since shadow-attach is single-threaded since it may
+        * only be called from the per-driver module init hook. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list);
+
        return 0;
 
-err_pci:
+err_agp:
+       drm_pci_agp_destroy(dev);
        pci_disable_device(pdev);
 err_free:
        drm_dev_free(dev);
@@ -375,7 +375,6 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 
        DRM_DEBUG("\n");
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->kdriver.pci = pdriver;
        driver->bus = &drm_pci_bus;
 
@@ -383,6 +382,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
                return pci_register_driver(pdriver);
 
        /* If not using KMS, fall back to stealth mode manual scanning. */
+       INIT_LIST_HEAD(&driver->legacy_dev_list);
        for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
                pid = &pdriver->id_table[i];
 
@@ -452,6 +452,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
        return -1;
 }
 
+void drm_pci_agp_destroy(struct drm_device *dev) {}
 #endif
 
 EXPORT_SYMBOL(drm_pci_init);
@@ -465,8 +466,11 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
        if (driver->driver_features & DRIVER_MODESET) {
                pci_unregister_driver(pdriver);
        } else {
-               list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+               list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list,
+                                        legacy_dev_list) {
                        drm_put_dev(dev);
+                       list_del(&dev->legacy_dev_list);
+               }
        }
        DRM_INFO("Module unloaded\n");
 }
index fc24fee8ec833b6bdb2c26ada2b45e947622b941..21fc82006b78c3423c801b54ef5acd40d4f79805 100644 (file)
@@ -147,18 +147,6 @@ int drm_platform_init(struct drm_driver *driver, struct platform_device *platfor
 
        driver->kdriver.platform_device = platform_device;
        driver->bus = &drm_platform_bus;
-       INIT_LIST_HEAD(&driver->device_list);
        return drm_get_platform_dev(platform_device, driver);
 }
 EXPORT_SYMBOL(drm_platform_init);
-
-void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device)
-{
-       struct drm_device *dev, *tmp;
-       DRM_DEBUG("\n");
-
-       list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-               drm_put_dev(dev);
-       DRM_INFO("Module unloaded\n");
-}
-EXPORT_SYMBOL(drm_platform_exit);
index 66dd3a001cf1b5ee43ec75f190b03146e7bbe46d..98a33c580ca1aeceed513f2af38b6742cee30f85 100644 (file)
@@ -99,13 +99,19 @@ void drm_ut_debug_printk(unsigned int request_level,
                         const char *function_name,
                         const char *format, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        if (drm_debug & request_level) {
-               if (function_name)
-                       printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
                va_start(args, format);
-               vprintk(format, args);
+               vaf.fmt = format;
+               vaf.va = &args;
+
+               if (function_name)
+                       printk(KERN_DEBUG "[%s:%s], %pV", prefix,
+                              function_name, &vaf);
+               else
+                       printk(KERN_DEBUG "%pV", &vaf);
                va_end(args);
        }
 }
@@ -521,16 +527,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
 
        mutex_lock(&drm_global_mutex);
 
-       if (dev->driver->bus->agp_init) {
-               ret = dev->driver->bus->agp_init(dev);
-               if (ret)
-                       goto out_unlock;
-       }
-
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
-                       goto err_agp;
+                       goto out_unlock;
        }
 
        if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
@@ -557,8 +557,6 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
                        goto err_unload;
        }
 
-       list_add_tail(&dev->driver_item, &dev->driver->device_list);
-
        ret = 0;
        goto out_unlock;
 
@@ -571,9 +569,6 @@ err_render_node:
        drm_unplug_minor(dev->render);
 err_control_node:
        drm_unplug_minor(dev->control);
-err_agp:
-       if (dev->driver->bus->agp_destroy)
-               dev->driver->bus->agp_destroy(dev);
 out_unlock:
        mutex_unlock(&drm_global_mutex);
        return ret;
@@ -597,8 +592,8 @@ void drm_dev_unregister(struct drm_device *dev)
        if (dev->driver->unload)
                dev->driver->unload(dev);
 
-       if (dev->driver->bus->agp_destroy)
-               dev->driver->bus->agp_destroy(dev);
+       if (dev->agp)
+               drm_pci_agp_destroy(dev);
 
        drm_vblank_cleanup(dev);
 
@@ -608,7 +603,5 @@ void drm_dev_unregister(struct drm_device *dev)
        drm_unplug_minor(dev->control);
        drm_unplug_minor(dev->render);
        drm_unplug_minor(dev->primary);
-
-       list_del(&dev->driver_item);
 }
 EXPORT_SYMBOL(drm_dev_unregister);
index b179b70e7853b4bb4eb69c9a97a57295ae26a084..0f8cb1ae76074d2bf21d75d678585222019f2cdd 100644 (file)
@@ -1,4 +1,5 @@
 #include <drm/drmP.h>
+#include <drm/drm_usb.h>
 #include <linux/usb.h>
 #include <linux/module.h>
 
@@ -63,7 +64,6 @@ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver)
        int res;
        DRM_DEBUG("\n");
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->kdriver.usb = udriver;
        driver->bus = &drm_usb_bus;
 
index 93e95d7efd575fc7bf084e431ae560793e733728..24e045c4f53140270ebbb28f9a6be21209b704a7 100644 (file)
@@ -101,7 +101,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        /*
         * Find the right map
         */
-       if (!drm_core_has_AGP(dev))
+       if (!dev->agp)
                goto vm_fault_error;
 
        if (!dev->agp || !dev->agp->cant_use_aperture)
@@ -220,7 +220,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
 
        map = vma->vm_private_data;
 
@@ -266,9 +265,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                                dmah.size = map->size;
                                __drm_pci_free(dev, &dmah);
                                break;
-                       case _DRM_GEM:
-                               DRM_ERROR("tried to rmmap GEM object\n");
-                               break;
                        }
                        kfree(map);
                }
@@ -408,7 +404,6 @@ void drm_vm_open_locked(struct drm_device *dev,
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_inc(&dev->vma_count);
 
        vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
        if (vma_entry) {
@@ -436,7 +431,6 @@ void drm_vm_close_locked(struct drm_device *dev,
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
 
        list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
                if (pt->vma == vma) {
@@ -595,7 +589,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
        switch (map->type) {
 #if !defined(__arm__)
        case _DRM_AGP:
-               if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
+               if (dev->agp && dev->agp->cant_use_aperture) {
                        /*
                         * On some platforms we can't talk to bus dma address from the CPU, so for
                         * memory of type DRM_AGP, we'll deal with sorting out the real physical
index 22b8f5eced80f3407b0fa9fc365c1d9e349d7e54..9d096a0c5f8d5f6bf0583d37f5efe433085504e4 100644 (file)
@@ -14,6 +14,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
+#include <linux/anon_inodes.h>
+
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
@@ -119,6 +121,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
        drm_vblank_offdelay = VBLANK_OFF_DELAY;
 
+       platform_set_drvdata(dev->platformdev, dev);
+
        return 0;
 
 err_drm_device:
@@ -150,9 +154,14 @@ static int exynos_drm_unload(struct drm_device *dev)
        return 0;
 }
 
+static const struct file_operations exynos_drm_gem_fops = {
+       .mmap = exynos_drm_gem_mmap_buffer,
+};
+
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_exynos_file_private *file_priv;
+       struct file *anon_filp;
        int ret;
 
        file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
@@ -167,6 +176,16 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
                file->driver_priv = NULL;
        }
 
+       anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
+                                       NULL, 0);
+       if (IS_ERR(anon_filp)) {
+               kfree(file_priv);
+               return PTR_ERR(anon_filp);
+       }
+
+       anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
+       file_priv->anon_filp = anon_filp;
+
        return ret;
 }
 
@@ -179,6 +198,7 @@ static void exynos_drm_preclose(struct drm_device *dev,
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct exynos_drm_private *private = dev->dev_private;
+       struct drm_exynos_file_private *file_priv;
        struct drm_pending_vblank_event *v, *vt;
        struct drm_pending_event *e, *et;
        unsigned long flags;
@@ -204,6 +224,9 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
+       file_priv = file->driver_priv;
+       if (file_priv->anon_filp)
+               fput(file_priv->anon_filp);
 
        kfree(file->driver_priv);
        file->driver_priv = NULL;
@@ -305,7 +328,7 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
 
 static int exynos_drm_platform_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&exynos_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index eaa19668bf00328657bdd370c304f27cf66ece5e..0eaf5a27e120e586129074446e816b902d7316f3 100644 (file)
@@ -226,6 +226,7 @@ struct exynos_drm_ipp_private {
 struct drm_exynos_file_private {
        struct exynos_drm_g2d_private   *g2d_priv;
        struct exynos_drm_ipp_private   *ipp_priv;
+       struct file                     *anon_filp;
 };
 
 /*
index a61878bf5dcd091cf31ed64a8374d230b580dc1e..a20440ce32e6c39ee450d926f668f5638df0cca8 100644 (file)
@@ -347,7 +347,7 @@ static void fimd_wait_for_vblank(struct device *dev)
         */
        if (!wait_event_timeout(ctx->wait_vsync_queue,
                                !atomic_read(&ctx->wait_vsync_event),
-                               DRM_HZ/20))
+                               HZ/20))
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
@@ -706,7 +706,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
        /* set wait vsync event to zero and wake up queue. */
        if (atomic_read(&ctx->wait_vsync_event)) {
                atomic_set(&ctx->wait_vsync_event, 0);
-               DRM_WAKEUP(&ctx->wait_vsync_queue);
+               wake_up(&ctx->wait_vsync_queue);
        }
 out:
        return IRQ_HANDLED;
@@ -954,7 +954,7 @@ static int fimd_probe(struct platform_device *pdev)
        }
 
        ctx->driver_data = drm_fimd_get_driver_data(pdev);
-       DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
+       init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
        subdrv = &ctx->subdrv;
index 1ade191d84f4d6514fd16871cb54cbdc3208d925..49b8c9b2290225dcf9cdf5993075c30ea0fd475e 100644 (file)
@@ -338,46 +338,22 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
                        &args->offset);
 }
 
-static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
-                                                       struct file *filp)
-{
-       struct drm_file *file_priv;
-
-       /* find current process's drm_file from filelist. */
-       list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
-               if (file_priv->filp == filp)
-                       return file_priv;
-
-       WARN_ON(1);
-
-       return ERR_PTR(-EFAULT);
-}
-
-static int exynos_drm_gem_mmap_buffer(struct file *filp,
+int exynos_drm_gem_mmap_buffer(struct file *filp,
                                      struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = filp->private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
        struct drm_device *drm_dev = obj->dev;
        struct exynos_drm_gem_buf *buffer;
-       struct drm_file *file_priv;
        unsigned long vm_size;
        int ret;
 
+       WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
        vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        vma->vm_private_data = obj;
        vma->vm_ops = drm_dev->driver->gem_vm_ops;
 
-       /* restore it to driver's fops. */
-       filp->f_op = fops_get(drm_dev->driver->fops);
-
-       file_priv = exynos_drm_find_drm_file(drm_dev, filp);
-       if (IS_ERR(file_priv))
-               return PTR_ERR(file_priv);
-
-       /* restore it to drm_file. */
-       filp->private_data = file_priv;
-
        update_vm_cache_attr(exynos_gem_obj, vma);
 
        vm_size = vma->vm_end - vma->vm_start;
@@ -411,15 +387,13 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
        return 0;
 }
 
-static const struct file_operations exynos_drm_gem_fops = {
-       .mmap = exynos_drm_gem_mmap_buffer,
-};
-
 int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
+       struct drm_exynos_file_private *exynos_file_priv;
        struct drm_exynos_gem_mmap *args = data;
        struct drm_gem_object *obj;
+       struct file *anon_filp;
        unsigned long addr;
 
        if (!(dev->driver->driver_features & DRIVER_GEM)) {
@@ -427,47 +401,25 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                return -ENODEV;
        }
 
+       mutex_lock(&dev->struct_mutex);
+
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (!obj) {
                DRM_ERROR("failed to lookup gem object.\n");
+               mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
 
-       /*
-        * We have to use gem object and its fops for specific mmaper,
-        * but vm_mmap() can deliver only filp. So we have to change
-        * filp->f_op and filp->private_data temporarily, then restore
-        * again. So it is important to keep lock until restoration the
-        * settings to prevent others from misuse of filp->f_op or
-        * filp->private_data.
-        */
-       mutex_lock(&dev->struct_mutex);
-
-       /*
-        * Set specific mmper's fops. And it will be restored by
-        * exynos_drm_gem_mmap_buffer to dev->driver->fops.
-        * This is used to call specific mapper temporarily.
-        */
-       file_priv->filp->f_op = &exynos_drm_gem_fops;
-
-       /*
-        * Set gem object to private_data so that specific mmaper
-        * can get the gem object. And it will be restored by
-        * exynos_drm_gem_mmap_buffer to drm_file.
-        */
-       file_priv->filp->private_data = obj;
+       exynos_file_priv = file_priv->driver_priv;
+       anon_filp = exynos_file_priv->anon_filp;
+       anon_filp->private_data = obj;
 
-       addr = vm_mmap(file_priv->filp, 0, args->size,
-                       PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+       addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, 0);
 
        drm_gem_object_unreference(obj);
 
        if (IS_ERR_VALUE(addr)) {
-               /* check filp->f_op, filp->private_data are restored */
-               if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
-                       file_priv->filp->f_op = fops_get(dev->driver->fops);
-                       file_priv->filp->private_data = file_priv;
-               }
                mutex_unlock(&dev->struct_mutex);
                return (int)addr;
        }
index 702ec3abe85cc88eb74aa2e7dc99b5224c175dcf..fde860c7eba34b35b733ff7afef350f0c1b56527 100644 (file)
@@ -122,6 +122,9 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
 int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv);
 
+int exynos_drm_gem_mmap_buffer(struct file *filp,
+                                     struct vm_area_struct *vma);
+
 /* map user space allocated by malloc to pages. */
 int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv);
index 63bc5f92fbb320e6287fa106a8357c7eac503435..2dfa48c76f54644d1c7efd6fb6e52bedacc02e70 100644 (file)
@@ -868,7 +868,7 @@ static void mixer_wait_for_vblank(void *ctx)
         */
        if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
                                !atomic_read(&mixer_ctx->wait_vsync_event),
-                               DRM_HZ/20))
+                               HZ/20))
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
@@ -1019,7 +1019,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
                        atomic_set(&ctx->wait_vsync_event, 0);
-                       DRM_WAKEUP(&ctx->wait_vsync_queue);
+                       wake_up(&ctx->wait_vsync_queue);
                }
        }
 
@@ -1209,7 +1209,7 @@ static int mixer_probe(struct platform_device *pdev)
        drm_hdmi_ctx->ctx = (void *)ctx;
        ctx->vp_enabled = drv->is_vp_enabled;
        ctx->mxr_ver = drv->version;
-       DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
+       init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
        platform_set_drvdata(pdev, drm_hdmi_ctx);
index d5ef1a5793c8832e9a251fa817f7e19c246c06e6..de6f62a6ceb7a2d85ab67ba2eb64e8f688c05320 100644 (file)
@@ -326,7 +326,7 @@ int psbfb_sync(struct fb_info *info)
        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;
+       unsigned long _end = jiffies + HZ;
        int busy = 0;
        unsigned long flags;
 
index f88a1815d87c4e795492ead6ef1c4c07a4d31b89..0490ce36b53fd9237e754de7877f51f3aaffee97 100644 (file)
@@ -483,7 +483,7 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
 
        if (send_bytes > 16)
                return -1;
-       msg[0] = AUX_NATIVE_WRITE << 4;
+       msg[0] = DP_AUX_NATIVE_WRITE << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = send_bytes - 1;
@@ -493,9 +493,10 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
                ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        break;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -523,7 +524,7 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
        uint8_t ack;
        int ret;
 
-       msg[0] = AUX_NATIVE_READ << 4;
+       msg[0] = DP_AUX_NATIVE_READ << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = recv_bytes - 1;
@@ -538,12 +539,12 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
                        return -EPROTO;
                if (ret < 0)
                        return ret;
-               ack = reply[0];
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+               ack = reply[0] >> 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
                        memcpy(recv, reply + 1, ret - 1);
                        return ret - 1;
                }
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -569,12 +570,12 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[0] = AUX_I2C_READ << 4;
+               msg[0] = DP_AUX_I2C_READ << 4;
        else
-               msg[0] = AUX_I2C_WRITE << 4;
+               msg[0] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[0] |= AUX_I2C_MOT << 4;
+               msg[0] |= DP_AUX_I2C_MOT << 4;
 
        msg[1] = address >> 8;
        msg[2] = address;
@@ -606,16 +607,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return ret;
                }
 
-               switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        return -EREMOTEIO;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        udelay(100);
                        continue;
                default:
@@ -624,16 +625,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return -EREMOTEIO;
                }
 
-               switch (reply[0] & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ) {
                                *read_byte = reply[1];
                        }
                        return reply_bytes - 1;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        return -EREMOTEIO;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
                        udelay(100);
                        break;
@@ -677,7 +678,7 @@ cdv_intel_dp_i2c_init(struct gma_connector *connector,
        return ret;
 }
 
-void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
+static void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
        struct drm_display_mode *adjusted_mode)
 {
        adjusted_mode->hdisplay = fixed_mode->hdisplay;
index 24e8af3d22bfd34583d8b826b3fd75f7023002c7..386de2c9dc8649f449580a062d4d91c62fd3a733 100644 (file)
@@ -349,6 +349,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
        /* If we didn't get a handle then turn the cursor off */
        if (!handle) {
                temp = CURSOR_MODE_DISABLE;
+               mutex_lock(&dev->struct_mutex);
 
                if (gma_power_begin(dev, false)) {
                        REG_WRITE(control, temp);
@@ -365,6 +366,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
                        gma_crtc->cursor_obj = NULL;
                }
 
+               mutex_unlock(&dev->struct_mutex);
                return 0;
        }
 
@@ -374,9 +376,12 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
+       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj)
-               return -ENOENT;
+       if (!obj) {
+               ret = -ENOENT;
+               goto unlock;
+       }
 
        if (obj->size < width * height * 4) {
                dev_dbg(dev->dev, "Buffer is too small\n");
@@ -440,10 +445,13 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
        }
 
        gma_crtc->cursor_obj = obj;
+unlock:
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 
 unref_cursor:
        drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 }
 
index b59e6588c34327b9162c0346de826729633b20cc..5ad6a03e477eae63aa8cc635981887febca71ac1 100644 (file)
@@ -212,8 +212,8 @@ enum {
 #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 PSB_WATCHDOG_DELAY (HZ * 2)
+#define PSB_LID_DELAY (HZ / 10)
 
 #define MDFLD_PNW_B0 0x04
 #define MDFLD_PNW_C0 0x08
@@ -232,7 +232,7 @@ enum {
 #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 MDFLD_DSR_DELAY                (HZ / MDFLD_DSR_RR)
 
 #define PSB_PWR_STATE_ON               1
 #define PSB_PWR_STATE_OFF              2
@@ -769,7 +769,7 @@ extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
  *psb_irq.c
  */
 
-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t psb_irq_handler(int irq, void *arg);
 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);
index bde27fdb41bf9d9a7ab79f0e3545e5ae0f9c96a5..dc2c8eb030faeaf29f4bd7d32c87c803ab846e30 100644 (file)
@@ -250,11 +250,6 @@ extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
 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,
                                      const struct drm_display_mode *mode,
                                      struct drm_display_mode *adjusted_mode);
index ba4830342d3450593bbc1f49a5a6fded4419c510..f883f9e4c5240ee923cbaabb3c57b88472983431 100644 (file)
@@ -200,7 +200,7 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
                mid_pipe_event_handler(dev, 1);
 }
 
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t psb_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct drm_psb_private *dev_priv = dev->dev_private;
@@ -253,7 +253,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
        PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
        (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
+       rmb();
 
        if (!handled)
                return IRQ_NONE;
@@ -450,21 +450,6 @@ int psb_irq_disable_dpst(struct drm_device *dev)
        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->vblank.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
  */
index debb7f190c062a725e43e38c567dc815823b38f0..d0b45ffa112600b65beb932f8fb1b4e5802453af 100644 (file)
@@ -32,7 +32,7 @@ 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);
+irqreturn_t psb_irq_handler(int irq, void *arg);
 
 int psb_irq_enable_dpst(struct drm_device *dev);
 int psb_irq_disable_dpst(struct drm_device *dev);
index 249fdff305c63b50fd72c2f62a499eb2a0d3e576..aeace37415aac8ae62ab2aa53a3b927ae648fb6c 100644 (file)
@@ -1193,6 +1193,10 @@ static int i810_flip_bufs(struct drm_device *dev, void *data,
 
 int i810_driver_load(struct drm_device *dev, unsigned long flags)
 {
+       /* Our userspace depends upon the agp mapping support. */
+       if (!dev->agp)
+               return -EINVAL;
+
        pci_set_master(dev->pdev);
 
        return 0;
index d8180d22ceddb38965e3c6f59367d75a8421dff2..441ccf8f5bdc3a7d2ebad9b4724eff2044d2c34b 100644 (file)
@@ -57,7 +57,7 @@ static const struct file_operations i810_driver_fops = {
 
 static struct drm_driver driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
+           DRIVER_USE_AGP |
            DRIVER_HAVE_DMA,
        .dev_priv_size = sizeof(drm_i810_buf_priv_t),
        .load = i810_driver_load,
index 6199d0b5b958fb2610e83810e117ea89c5057e6e..73ed59eff139a88948c7766dcc0c999398f59254 100644 (file)
@@ -1,8 +1,10 @@
 config DRM_I915
        tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
        depends on DRM
-       depends on AGP
-       depends on AGP_INTEL
+       depends on X86 && PCI
+       depends on (AGP || AGP=n)
+       select INTEL_GTT
+       select AGP_INTEL if AGP
        # we need shmfs for the swappable backing store, and in particular
        # the shmem_readpage() which depends upon tmpfs
        select SHMEM
@@ -35,15 +37,14 @@ config DRM_I915
 config DRM_I915_KMS
        bool "Enable modesetting on intel by default"
        depends on DRM_I915
+       default y
        help
-         Choose this option if you want kernel modesetting enabled by default,
-         and you have a new enough userspace to support this. Running old
-         userspaces with this enabled will cause pain.  Note that this causes
-         the driver to bind to PCI devices, which precludes loading things
-         like intelfb.
+         Choose this option if you want kernel modesetting enabled by default.
+
+         If in doubt, say "Y".
 
 config DRM_I915_FBDEV
-       bool "Enable legacy fbdev support for the modesettting intel driver"
+       bool "Enable legacy fbdev support for the modesetting intel driver"
        depends on DRM_I915
        select DRM_KMS_FB_HELPER
        select FB_CFB_FILLRECT
@@ -55,9 +56,12 @@ config DRM_I915_FBDEV
          support. Note that this support also provide the linux console
          support on top of the intel modesetting driver.
 
+         If in doubt, say "Y".
+
 config DRM_I915_PRELIMINARY_HW_SUPPORT
        bool "Enable preliminary support for prerelease Intel hardware by default"
        depends on DRM_I915
+       default n
        help
          Choose this option if you have prerelease Intel hardware and want the
          i915 driver to support it by default.  You can enable such support at
@@ -65,3 +69,15 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
          option changes the default for that module option.
 
          If in doubt, say "N".
+
+config DRM_I915_UMS
+       bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
+       depends on DRM_I915
+       default n
+       help
+         Choose this option if you still need userspace modesetting.
+
+         Userspace modesetting is deprecated for quite some time now, so
+         enable this only if you have ancient versions of the DDX drivers.
+
+         If in doubt, say "N".
index 41838eaa799c5afcb7510bae31118099d4d848a3..da682cbcb8061dd33d8c67c901e476ffebeffc32 100644 (file)
@@ -4,7 +4,6 @@
 
 ccflags-y := -Iinclude/drm
 i915-y := i915_drv.o i915_dma.o i915_irq.o \
-         i915_debugfs.o \
          i915_gpu_error.o \
           i915_suspend.o \
          i915_gem.o \
@@ -55,6 +54,8 @@ i915-$(CONFIG_ACPI)   += intel_acpi.o
 
 i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o
 
+i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
+
 obj-$(CONFIG_DRM_I915)  += i915.o
 
 CFLAGS_i915_trace_points.o := -I$(src)
index c4a255be697921caade4bf3dd064217e82230763..954acb2c7021d8eb9a90fe1e49ea5bc806f1f344 100644 (file)
@@ -87,49 +87,6 @@ struct ns2501_priv {
  * when switching the resolution.
  */
 
-static void enable_dvo(struct intel_dvo_device *dvo)
-{
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-
-       DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);
-
-       ns->dvoc = I915_READ(DVO_C);
-       ns->pll_a = I915_READ(_DPLL_A);
-       ns->srcdim = I915_READ(DVOC_SRCDIM);
-       ns->fw_blc = I915_READ(FW_BLC);
-
-       I915_WRITE(DVOC, 0x10004084);
-       I915_WRITE(_DPLL_A, 0xd0820000);
-       I915_WRITE(DVOC_SRCDIM, 0x400300);      // 1024x768
-       I915_WRITE(FW_BLC, 0x1080304);
-
-       I915_WRITE(DVOC, 0x90004084);
-}
-
-/*
- * Restore the I915 registers modified by the above
- * trigger function.
- */
-static void restore_dvo(struct intel_dvo_device *dvo)
-{
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-
-       I915_WRITE(DVOC, ns->dvoc);
-       I915_WRITE(_DPLL_A, ns->pll_a);
-       I915_WRITE(DVOC_SRCDIM, ns->srcdim);
-       I915_WRITE(FW_BLC, ns->fw_blc);
-}
-
 /*
 ** Read a register from the ns2501.
 ** Returns true if successful, false otherwise.
@@ -300,7 +257,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                            struct drm_display_mode *adjusted_mode)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
 
        DRM_DEBUG_KMS
@@ -476,20 +433,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                        ns->reg_8_shadow |= NS2501_8_BPAS;
                }
                ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
-
-               if (!ok) {
-                       if (restore)
-                               restore_dvo(dvo);
-                       enable_dvo(dvo);
-                       restore = true;
-               }
-       } while (!ok);
-       /*
-        * Restore the old i915 registers before
-        * forcing the ns2501 on.
-        */
-       if (restore)
-               restore_dvo(dvo);
+       } while (!ok && retries--);
 }
 
 /* set the NS2501 power state */
@@ -510,7 +454,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
 static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
        unsigned char ch;
 
@@ -537,16 +481,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
                        ok &=
                            ns2501_writeb(dvo, 0x35,
                                          enable ? 0xff : 0x00);
-                       if (!ok) {
-                               if (restore)
-                                       restore_dvo(dvo);
-                               enable_dvo(dvo);
-                               restore = true;
-                       }
-               } while (!ok);
-
-               if (restore)
-                       restore_dvo(dvo);
+               } while (!ok && retries--);
        }
 }
 
index 6ed45a984230c6db3bb8cc4b8fbdc2eec9a661d1..b2b46c52294c6d4d9c2a20890fafaa4b122e7fa3 100644 (file)
@@ -40,8 +40,6 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
-#if defined(CONFIG_DEBUG_FS)
-
 enum {
        ACTIVE_LIST,
        INACTIVE_LIST,
@@ -406,16 +404,26 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
        seq_putc(m, '\n');
        list_for_each_entry_reverse(file, &dev->filelist, lhead) {
                struct file_stats stats;
+               struct task_struct *task;
 
                memset(&stats, 0, sizeof(stats));
                idr_for_each(&file->object_idr, per_file_stats, &stats);
+               /*
+                * Although we have a valid reference on file->pid, that does
+                * not guarantee that the task_struct who called get_pid() is
+                * still alive (e.g. get_pid(current) => fork() => exit()).
+                * Therefore, we need to protect this ->comm access using RCU.
+                */
+               rcu_read_lock();
+               task = pid_task(file->pid, PIDTYPE_PID);
                seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n",
-                          get_pid_task(file->pid, PIDTYPE_PID)->comm,
+                          task ? task->comm : "<unknown>",
                           stats.count,
                           stats.total,
                           stats.active,
                           stats.inactive,
                           stats.unbound);
+               rcu_read_unlock();
        }
 
        mutex_unlock(&dev->struct_mutex);
@@ -564,10 +572,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for_each_ring(ring, dev_priv, i)
                i915_ring_seqno_info(m, ring);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -585,6 +595,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8) {
                int i;
@@ -711,6 +722,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
                i915_ring_seqno_info(m, ring);
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -904,9 +916,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        crstanddelay = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
@@ -919,7 +933,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
+       int ret = 0;
+
+       intel_runtime_pm_get(dev_priv);
 
        flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
@@ -945,9 +961,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                /* RPSTAT1 is in the GT power well */
                ret = mutex_lock_interruptible(&dev->struct_mutex);
                if (ret)
-                       return ret;
+                       goto out;
 
-               gen6_gt_force_wake_get(dev_priv);
+               gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
                reqf = I915_READ(GEN6_RPNSWREQ);
                reqf &= ~GEN6_TURBO_DISABLE;
@@ -970,7 +986,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                        cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
                cagf *= GT_FREQUENCY_MULTIPLIER;
 
-               gen6_gt_force_wake_put(dev_priv);
+               gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
@@ -1018,23 +1034,24 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
                seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
 
-               val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1);
+               val = valleyview_rps_max_freq(dev_priv);
                seq_printf(m, "max GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
-               val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM);
+               val = valleyview_rps_min_freq(dev_priv);
                seq_printf(m, "min GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
                seq_printf(m, "current GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq,
-                                       (freq_sts >> 8) & 0xff));
+                          vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
                mutex_unlock(&dev_priv->rps.hw_lock);
        } else {
                seq_puts(m, "no P-state info available\n");
        }
 
-       return 0;
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static int i915_delayfreq_table(struct seq_file *m, void *unused)
@@ -1048,6 +1065,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -1055,6 +1073,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
                           (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
+       intel_runtime_pm_put(dev_priv);
+
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1076,12 +1096,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 1; i <= 32; i++) {
                inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
                seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1099,11 +1121,13 @@ static int ironlake_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        rgvmodectl = I915_READ(MEMMODECTL);
        rstdbyctl = I915_READ(RSTDBYCTL);
        crstandvid = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -1154,6 +1178,50 @@ static int ironlake_drpc_info(struct seq_file *m)
        return 0;
 }
 
+static int vlv_drpc_info(struct seq_file *m)
+{
+
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 rpmodectl1, rcctl1;
+       unsigned fw_rendercount = 0, fw_mediacount = 0;
+
+       rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
+       rcctl1 = I915_READ(GEN6_RC_CONTROL);
+
+       seq_printf(m, "Video Turbo Mode: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
+       seq_printf(m, "Turbo enabled: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_ENABLE));
+       seq_printf(m, "HW control enabled: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_ENABLE));
+       seq_printf(m, "SW control enabled: %s\n",
+                  yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) ==
+                         GEN6_RP_MEDIA_SW_MODE));
+       seq_printf(m, "RC6 Enabled: %s\n",
+                  yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE |
+                                       GEN6_RC_CTL_EI_MODE(1))));
+       seq_printf(m, "Render Power Well: %s\n",
+                       (I915_READ(VLV_GTLC_PW_STATUS) &
+                               VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down");
+       seq_printf(m, "Media Power Well: %s\n",
+                       (I915_READ(VLV_GTLC_PW_STATUS) &
+                               VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
+
+       spin_lock_irq(&dev_priv->uncore.lock);
+       fw_rendercount = dev_priv->uncore.fw_rendercount;
+       fw_mediacount = dev_priv->uncore.fw_mediacount;
+       spin_unlock_irq(&dev_priv->uncore.lock);
+
+       seq_printf(m, "Forcewake Render Count = %u\n", fw_rendercount);
+       seq_printf(m, "Forcewake Media Count = %u\n", fw_mediacount);
+
+
+       return 0;
+}
+
+
 static int gen6_drpc_info(struct seq_file *m)
 {
 
@@ -1167,6 +1235,7 @@ static int gen6_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        spin_lock_irq(&dev_priv->uncore.lock);
        forcewake_count = dev_priv->uncore.forcewake_count;
@@ -1192,6 +1261,8 @@ static int gen6_drpc_info(struct seq_file *m)
        sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
+       intel_runtime_pm_put(dev_priv);
+
        seq_printf(m, "Video Turbo Mode: %s\n",
                   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
        seq_printf(m, "HW control enabled: %s\n",
@@ -1256,7 +1327,9 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
 
-       if (IS_GEN6(dev) || IS_GEN7(dev))
+       if (IS_VALLEYVIEW(dev))
+               return vlv_drpc_info(m);
+       else if (IS_GEN6(dev) || IS_GEN7(dev))
                return gen6_drpc_info(m);
        else
                return ironlake_drpc_info(m);
@@ -1268,7 +1341,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       if (!I915_HAS_FBC(dev)) {
+       if (!HAS_FBC(dev)) {
                seq_puts(m, "FBC unsupported on this chipset\n");
                return 0;
        }
@@ -1330,7 +1403,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
                return 0;
        }
 
-       if (I915_READ(IPS_CTL) & IPS_ENABLE)
+       if (IS_BROADWELL(dev) || I915_READ(IPS_CTL) & IPS_ENABLE)
                seq_puts(m, "enabled\n");
        else
                seq_puts(m, "disabled\n");
@@ -1406,6 +1479,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
@@ -1422,6 +1496,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
                           ((ia_freq >> 8) & 0xff) * 100);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return 0;
@@ -1437,8 +1512,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+       intel_runtime_pm_put(dev_priv);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -1565,13 +1642,21 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned forcewake_count;
+       unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0;
 
        spin_lock_irq(&dev_priv->uncore.lock);
-       forcewake_count = dev_priv->uncore.forcewake_count;
+       if (IS_VALLEYVIEW(dev)) {
+               fw_rendercount = dev_priv->uncore.fw_rendercount;
+               fw_mediacount = dev_priv->uncore.fw_mediacount;
+       } else
+               forcewake_count = dev_priv->uncore.forcewake_count;
        spin_unlock_irq(&dev_priv->uncore.lock);
 
-       seq_printf(m, "forcewake count = %u\n", forcewake_count);
+       if (IS_VALLEYVIEW(dev)) {
+               seq_printf(m, "fw_rendercount = %u\n", fw_rendercount);
+               seq_printf(m, "fw_mediacount = %u\n", fw_mediacount);
+       } else
+               seq_printf(m, "forcewake count = %u\n", forcewake_count);
 
        return 0;
 }
@@ -1610,6 +1695,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
                   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1641,6 +1727,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
                seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
                           I915_READ(DISP_ARB_CTL));
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1701,16 +1788,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        int ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8)
                gen8_ppgtt_info(m, dev);
        else if (INTEL_INFO(dev)->gen >= 6)
                gen6_ppgtt_info(m, dev);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1735,28 +1825,28 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 
        seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
 
-       seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A));
-       seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B));
+       seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0)));
+       seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1)));
 
-       seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A));
-       seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B));
+       seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0)));
+       seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1)));
 
-       seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A));
-       seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B));
+       seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0)));
+       seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1)));
 
-       seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A));
-       seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B));
+       seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0)));
+       seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1)));
 
        seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE));
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0));
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1784,6 +1874,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
        u32 psrperf = 0;
        bool enabled = false;
 
+       intel_runtime_pm_get(dev_priv);
+
        seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
        seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
 
@@ -1796,6 +1888,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                        EDP_PSR_PERF_CNT_MASK;
        seq_printf(m, "Performance_Counter: %u\n", psrperf);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -1845,6 +1938,76 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
        return 0;
 }
 
+static const char *power_domain_str(enum intel_display_power_domain domain)
+{
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+               return "PIPE_A";
+       case POWER_DOMAIN_PIPE_B:
+               return "PIPE_B";
+       case POWER_DOMAIN_PIPE_C:
+               return "PIPE_C";
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+               return "PIPE_A_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+               return "PIPE_B_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+               return "PIPE_C_PANEL_FITTER";
+       case POWER_DOMAIN_TRANSCODER_A:
+               return "TRANSCODER_A";
+       case POWER_DOMAIN_TRANSCODER_B:
+               return "TRANSCODER_B";
+       case POWER_DOMAIN_TRANSCODER_C:
+               return "TRANSCODER_C";
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return "TRANSCODER_EDP";
+       case POWER_DOMAIN_VGA:
+               return "VGA";
+       case POWER_DOMAIN_AUDIO:
+               return "AUDIO";
+       case POWER_DOMAIN_INIT:
+               return "INIT";
+       default:
+               WARN_ON(1);
+               return "?";
+       }
+}
+
+static int i915_power_domain_info(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       int i;
+
+       mutex_lock(&power_domains->lock);
+
+       seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count");
+       for (i = 0; i < power_domains->power_well_count; i++) {
+               struct i915_power_well *power_well;
+               enum intel_display_power_domain power_domain;
+
+               power_well = &power_domains->power_wells[i];
+               seq_printf(m, "%-25s %d\n", power_well->name,
+                          power_well->count);
+
+               for (power_domain = 0; power_domain < POWER_DOMAIN_NUM;
+                    power_domain++) {
+                       if (!(BIT(power_domain) & power_well->domains))
+                               continue;
+
+                       seq_printf(m, "  %-23s %d\n",
+                                power_domain_str(power_domain),
+                                power_domains->domain_use_count[power_domain]);
+               }
+       }
+
+       mutex_unlock(&power_domains->lock);
+
+       return 0;
+}
+
 struct pipe_crc_info {
        const char *name;
        struct drm_device *dev;
@@ -1857,6 +2020,9 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
        struct drm_i915_private *dev_priv = info->dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
 
+       if (info->pipe >= INTEL_INFO(info->dev)->num_pipes)
+               return -ENODEV;
+
        spin_lock_irq(&pipe_crc->lock);
 
        if (pipe_crc->opened) {
@@ -2005,8 +2171,8 @@ static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor,
        info->dev = dev;
        ent = debugfs_create_file(info->name, S_IRUGO, root, info,
                                  &i915_pipe_crc_fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, info);
 }
@@ -2347,7 +2513,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
-       u32 val;
+       u32 val = 0; /* shut up gcc */
        int ret;
 
        if (pipe_crc->source == source)
@@ -2742,7 +2908,7 @@ i915_drop_caches_set(void *data, u64 val)
        struct i915_vma *vma, *x;
        int ret;
 
-       DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
+       DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
 
        /* No need to check and wait for gpu resets, only libdrm auto-restarts
         * on ioctls on -EAGAIN. */
@@ -2810,8 +2976,7 @@ i915_max_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.max_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2841,9 +3006,9 @@ i915_max_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go above the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.max_delay = val;
-               gen6_set_rps(dev, val);
+               valleyview_set_rps(dev, val);
        } else {
                do_div(val, GT_FREQUENCY_MULTIPLIER);
                dev_priv->rps.max_delay = val;
@@ -2876,8 +3041,7 @@ i915_min_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.min_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2907,7 +3071,7 @@ i915_min_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go below the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.min_delay = val;
                valleyview_set_rps(dev, val);
        } else {
@@ -2938,8 +3102,11 @@ i915_cache_sharing_get(void *data, u64 *val)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->dev->struct_mutex);
 
        *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -2960,6 +3127,7 @@ i915_cache_sharing_set(void *data, u64 val)
        if (val > 3)
                return -EINVAL;
 
+       intel_runtime_pm_get(dev_priv);
        DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
        /* Update the cache sharing policy here as well */
@@ -2968,6 +3136,7 @@ i915_cache_sharing_set(void *data, u64 val)
        snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
        I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -2983,7 +3152,8 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_get(dev_priv);
+       intel_runtime_pm_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        return 0;
 }
@@ -2996,7 +3166,8 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+       intel_runtime_pm_put(dev_priv);
 
        return 0;
 }
@@ -3016,8 +3187,8 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
                                  S_IRUSR,
                                  root, dev,
                                  &i915_forcewake_fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
 }
@@ -3034,8 +3205,8 @@ static int i915_debugfs_create(struct dentry *root,
                                  S_IRUGO | S_IWUSR,
                                  root, dev,
                                  fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, fops);
 }
@@ -3079,6 +3250,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_edp_psr_status", i915_edp_psr_status, 0},
        {"i915_energy_uJ", i915_energy_uJ, 0},
        {"i915_pc8_status", i915_pc8_status, 0},
+       {"i915_power_domain_info", i915_power_domain_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -3102,10 +3274,10 @@ static const struct i915_debugfs_files {
 void intel_display_crc_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
+       enum pipe pipe;
 
-       for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
-               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i];
+       for_each_pipe(pipe) {
+               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
 
                pipe_crc->opened = false;
                spin_lock_init(&pipe_crc->lock);
@@ -3164,5 +3336,3 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                drm_debugfs_remove_files(info_list, 1, minor);
        }
 }
-
-#endif /* CONFIG_DEBUG_FS */
index 5c648425c1e053616801b3e1e545791a5fe111c0..e177d021c44412e6a5ec497aed6fdc86dce3b847 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -791,7 +793,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
        if (ring->irq_get(ring)) {
-               DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, ring->irq_queue, 3 * HZ,
                            READ_BREADCRUMB(dev_priv) >= irq_nr);
                ring->irq_put(ring);
        } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
@@ -828,7 +830,7 @@ static int i915_irq_emit(struct drm_device *dev, void *data,
        result = i915_emit_irq(dev);
        mutex_unlock(&dev->struct_mutex);
 
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
@@ -1016,8 +1018,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("DRM_COPY_TO_USER failed\n");
+       if (copy_to_user(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user failed\n");
                return -EFAULT;
        }
 
@@ -1411,7 +1413,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
-#ifdef CONFIG_DRM_I915_FBDEV
+#if IS_ENABLED(CONFIG_FB)
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
        struct apertures_struct *ap;
@@ -1484,6 +1486,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                return -ENODEV;
        }
 
+       /* UMS needs agp support. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET) && !dev->agp)
+               return -EINVAL;
+
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
                return -ENOMEM;
@@ -1494,7 +1500,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->gpu_error.lock);
-       spin_lock_init(&dev_priv->backlight.lock);
+       spin_lock_init(&dev_priv->backlight_lock);
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
@@ -1639,8 +1645,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_gem_unload;
        }
 
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_init(dev);
+       intel_power_domains_init(dev);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = i915_load_modeset_init(dev);
@@ -1664,11 +1669,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_GEN5(dev))
                intel_gpu_ips_init(dev_priv);
 
+       intel_init_runtime_pm(dev_priv);
+
        return 0;
 
 out_power_well:
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_remove(dev);
+       intel_power_domains_remove(dev);
        drm_vblank_cleanup(dev);
 out_gem_unload:
        if (dev_priv->mm.inactive_shrinker.scan_objects)
@@ -1704,25 +1710,27 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       ret = i915_gem_suspend(dev);
+       if (ret) {
+               DRM_ERROR("failed to idle hardware: %d\n", ret);
+               return ret;
+       }
+
+       intel_fini_runtime_pm(dev_priv);
+
        intel_gpu_ips_teardown();
 
-       if (HAS_POWER_WELL(dev)) {
-               /* The i915.ko module is still not prepared to be loaded when
-                * the power well is not enabled, so just enable it in case
-                * we're going to unload/reload. */
-               intel_display_set_init_power(dev, true);
-               intel_power_domains_remove(dev);
-       }
+       /* The i915.ko module is still not prepared to be loaded when
+        * the power well is not enabled, so just enable it in case
+        * we're going to unload/reload. */
+       intel_display_set_init_power(dev, true);
+       intel_power_domains_remove(dev);
 
        i915_teardown_sysfs(dev);
 
        if (dev_priv->mm.inactive_shrinker.scan_objects)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
-       ret = i915_gem_suspend(dev);
-       if (ret)
-               DRM_ERROR("failed to idle hardware: %d\n", ret);
-
        io_mapping_free(dev_priv->gtt.mappable);
        arch_phys_wc_del(dev_priv->gtt.mtrr);
 
@@ -1777,7 +1785,6 @@ int i915_driver_unload(struct drm_device *dev)
 
        list_del(&dev_priv->gtt.base.global_link);
        WARN_ON(!list_empty(&dev_priv->vm_list));
-       drm_mm_takedown(&dev_priv->gtt.base.mm);
 
        drm_vblank_cleanup(dev);
 
@@ -1910,6 +1917,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 5b7b7e06cb3a09caec1cd7d5ab90401389df7a40..43245b3fd2a22134986699bd89cff74e39c5d045 100644 (file)
@@ -114,7 +114,7 @@ MODULE_PARM_DESC(enable_hangcheck,
                "(default: true)");
 
 int i915_enable_ppgtt __read_mostly = -1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
@@ -155,7 +155,6 @@ MODULE_PARM_DESC(prefault_disable,
                "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
 
 static struct drm_driver driver;
-extern int intel_agp_enabled;
 
 static const struct intel_device_info intel_i830_info = {
        .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
@@ -173,6 +172,7 @@ static const struct intel_device_info intel_i85x_info = {
        .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 
@@ -192,6 +192,7 @@ static const struct intel_device_info intel_i915gm_info = {
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 static const struct intel_device_info intel_i945g_info = {
@@ -204,6 +205,7 @@ static const struct intel_device_info intel_i945gm_info = {
        .has_hotplug = 1, .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 
@@ -265,6 +267,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
 static const struct intel_device_info intel_sandybridge_d_info = {
        .gen = 6, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING,
        .has_llc = 1,
 };
@@ -280,6 +283,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 #define GEN7_FEATURES  \
        .gen = 7, .num_pipes = 3, \
        .need_gfx_hws = 1, .has_hotplug = 1, \
+       .has_fbc = 1, \
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
        .has_llc = 1
 
@@ -292,7 +296,6 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        GEN7_FEATURES,
        .is_ivybridge = 1,
        .is_mobile = 1,
-       .has_fbc = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
@@ -307,6 +310,7 @@ static const struct intel_device_info intel_valleyview_m_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -315,6 +319,7 @@ static const struct intel_device_info intel_valleyview_d_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -332,7 +337,6 @@ static const struct intel_device_info intel_haswell_m_info = {
        .is_mobile = 1,
        .has_ddi = 1,
        .has_fpga_dbg = 1,
-       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 };
 
@@ -476,12 +480,12 @@ check_next:
 bool i915_semaphore_is_enabled(struct drm_device *dev)
 {
        if (INTEL_INFO(dev)->gen < 6)
-               return 0;
+               return false;
 
        /* Until we get further testing... */
        if (IS_GEN8(dev)) {
                WARN_ON(!i915_preliminary_hw_support);
-               return 0;
+               return false;
        }
 
        if (i915_semaphores >= 0)
@@ -493,7 +497,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
                return false;
 #endif
 
-       return 1;
+       return true;
 }
 
 static int i915_drm_freeze(struct drm_device *dev)
@@ -501,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* ignore lid events during suspend */
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -688,6 +694,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_DONE;
        mutex_unlock(&dev_priv->modeset_restore_lock);
+
+       intel_runtime_pm_put(dev_priv);
        return error;
 }
 
@@ -762,14 +770,14 @@ int i915_reset(struct drm_device *dev)
                DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
                dev_priv->gpu_error.stop_rings = 0;
                if (ret == -ENODEV) {
-                       DRM_ERROR("Reset not implemented, but ignoring "
-                                 "error for simulated gpu hangs\n");
+                       DRM_INFO("Reset not implemented, but ignoring "
+                                "error for simulated gpu hangs\n");
                        ret = 0;
                }
        }
 
        if (ret) {
-               DRM_ERROR("Failed to reset chip.\n");
+               DRM_ERROR("Failed to reset chip: %i\n", ret);
                mutex_unlock(&dev->struct_mutex);
                return ret;
        }
@@ -790,12 +798,9 @@ int i915_reset(struct drm_device *dev)
         */
        if (drm_core_check_feature(dev, DRIVER_MODESET) ||
                        !dev_priv->ums.mm_suspended) {
-               bool hw_contexts_disabled = dev_priv->hw_contexts_disabled;
                dev_priv->ums.mm_suspended = 0;
 
                ret = i915_gem_init_hw(dev);
-               if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled)
-                       DRM_ERROR("HW contexts didn't survive reset\n");
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("Failed hw init on reset %d\n", ret);
@@ -831,17 +836,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (PCI_FUNC(pdev->devfn))
                return -ENODEV;
 
-       /* We've managed to ship a kms-enabled ddx that shipped with an XvMC
-        * implementation for gen3 (and only gen3) that used legacy drm maps
-        * (gasp!) to share buffers between X and the client. Hence we need to
-        * keep around the fake agp stuff for gen3, even when kms is enabled. */
-       if (intel_info->gen != 3) {
-               driver.driver_features &=
-                       ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP);
-       } else if (!intel_agp_enabled) {
-               DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
-               return -ENODEV;
-       }
+       driver.driver_features &= ~(DRIVER_USE_AGP);
 
        return drm_get_pci_dev(pdev, ent, &driver);
 }
@@ -915,6 +910,41 @@ static int i915_pm_poweroff(struct device *dev)
        return i915_drm_freeze(drm_dev);
 }
 
+static int i915_runtime_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Suspending device\n");
+
+       i915_gem_release_all_mmaps(dev_priv);
+
+       del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
+       dev_priv->pm.suspended = true;
+       intel_opregion_notify_adapter(dev, PCI_D3cold);
+
+       return 0;
+}
+
+static int i915_runtime_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Resuming device\n");
+
+       intel_opregion_notify_adapter(dev, PCI_D0);
+       dev_priv->pm.suspended = false;
+
+       return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
        .suspend = i915_pm_suspend,
        .resume = i915_pm_resume,
@@ -922,6 +952,8 @@ static const struct dev_pm_ops i915_pm_ops = {
        .thaw = i915_pm_thaw,
        .poweroff = i915_pm_poweroff,
        .restore = i915_pm_resume,
+       .runtime_suspend = i915_runtime_suspend,
+       .runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
@@ -949,7 +981,7 @@ static struct drm_driver driver = {
         * deal with them for Intel hardware.
         */
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
+           DRIVER_USE_AGP |
            DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
            DRIVER_RENDER,
        .load = i915_driver_load,
@@ -1024,14 +1056,24 @@ static int __init i915_init(void)
                driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
-       if (!(driver.driver_features & DRIVER_MODESET))
+       if (!(driver.driver_features & DRIVER_MODESET)) {
                driver.get_vblank_timestamp = NULL;
+#ifndef CONFIG_DRM_I915_UMS
+               /* Silently fail loading to not upset userspace. */
+               return 0;
+#endif
+       }
 
        return drm_pci_init(&driver, &i915_pci_driver);
 }
 
 static void __exit i915_exit(void)
 {
+#ifndef CONFIG_DRM_I915_UMS
+       if (!(driver.driver_features & DRIVER_MODESET))
+               return; /* Never loaded a driver. */
+#endif
+
        drm_pci_exit(&driver, &i915_pci_driver);
 }
 
index 90fcccba17b00da4a91ea2556b53a81e877356f0..ff6f870d6621267c5840cd2c27daaa2a35979ae4 100644 (file)
@@ -89,6 +89,18 @@ enum port {
 };
 #define port_name(p) ((p) + 'A')
 
+#define I915_NUM_PHYS_VLV 1
+
+enum dpio_channel {
+       DPIO_CH0,
+       DPIO_CH1
+};
+
+enum dpio_phy {
+       DPIO_PHY0,
+       DPIO_PHY1
+};
+
 enum intel_display_power_domain {
        POWER_DOMAIN_PIPE_A,
        POWER_DOMAIN_PIPE_B,
@@ -101,6 +113,7 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
        POWER_DOMAIN_VGA,
+       POWER_DOMAIN_AUDIO,
        POWER_DOMAIN_INIT,
 
        POWER_DOMAIN_NUM,
@@ -310,7 +323,7 @@ struct drm_i915_error_state {
        u32 instps[I915_NUM_RINGS];
        u32 extra_instdone[I915_NUM_INSTDONE_REG];
        u32 seqno[I915_NUM_RINGS];
-       u64 bbaddr;
+       u64 bbaddr[I915_NUM_RINGS];
        u32 fault_reg[I915_NUM_RINGS];
        u32 done_reg;
        u32 faddr[I915_NUM_RINGS];
@@ -351,6 +364,7 @@ struct drm_i915_error_state {
        enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS];
 };
 
+struct intel_connector;
 struct intel_crtc_config;
 struct intel_crtc;
 struct intel_limit;
@@ -358,7 +372,7 @@ struct dpll;
 
 struct drm_i915_display_funcs {
        bool (*fbc_enabled)(struct drm_device *dev);
-       void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
+       void (*enable_fbc)(struct drm_crtc *crtc);
        void (*disable_fbc)(struct drm_device *dev);
        int (*get_display_clock_speed)(struct drm_device *dev);
        int (*get_fifo_size)(struct drm_device *dev, int plane);
@@ -413,11 +427,20 @@ struct drm_i915_display_funcs {
        /* render clock increase/decrease */
        /* display clock increase/decrease */
        /* pll clock increase/decrease */
+
+       int (*setup_backlight)(struct intel_connector *connector);
+       uint32_t (*get_backlight)(struct intel_connector *connector);
+       void (*set_backlight)(struct intel_connector *connector,
+                             uint32_t level);
+       void (*disable_backlight)(struct intel_connector *connector);
+       void (*enable_backlight)(struct intel_connector *connector);
 };
 
 struct intel_uncore_funcs {
-       void (*force_wake_get)(struct drm_i915_private *dev_priv);
-       void (*force_wake_put)(struct drm_i915_private *dev_priv);
+       void (*force_wake_get)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
+       void (*force_wake_put)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
 
        uint8_t  (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
        uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
@@ -442,6 +465,9 @@ struct intel_uncore {
        unsigned fifo_count;
        unsigned forcewake_count;
 
+       unsigned fw_rendercount;
+       unsigned fw_mediacount;
+
        struct delayed_work force_wake_work;
 };
 
@@ -669,7 +695,6 @@ struct i915_fbc {
                struct delayed_work work;
                struct drm_crtc *crtc;
                struct drm_framebuffer *fb;
-               int interval;
        } *fbc_work;
 
        enum no_fbc_reason {
@@ -708,7 +733,6 @@ enum intel_sbi_destination {
 #define QUIRK_PIPEA_FORCE (1<<0)
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
-#define QUIRK_NO_PCH_PWM_ENABLE (1<<3)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -761,8 +785,6 @@ struct i915_suspend_saved_registers {
        u32 saveBLC_PWM_CTL;
        u32 saveBLC_PWM_CTL2;
        u32 saveBLC_HIST_CTL_B;
-       u32 saveBLC_PWM_CTL_B;
-       u32 saveBLC_PWM_CTL2_B;
        u32 saveBLC_CPU_PWM_CTL;
        u32 saveBLC_CPU_PWM_CTL2;
        u32 saveFPB0;
@@ -932,21 +954,29 @@ struct intel_ilk_power_mgmt {
 
 /* Power well structure for haswell */
 struct i915_power_well {
+       const char *name;
+       bool always_on;
        /* power well enable/disable usage count */
        int count;
+       unsigned long domains;
+       void *data;
+       void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
+                   bool enable);
+       bool (*is_enabled)(struct drm_device *dev,
+                          struct i915_power_well *power_well);
 };
 
-#define I915_MAX_POWER_WELLS 1
-
 struct i915_power_domains {
        /*
         * Power wells needed for initialization at driver init and suspend
         * time are on. They are kept on until after the first modeset.
         */
        bool init_power_on;
+       int power_well_count;
 
        struct mutex lock;
-       struct i915_power_well power_wells[I915_MAX_POWER_WELLS];
+       int domain_use_count[POWER_DOMAIN_NUM];
+       struct i915_power_well *power_wells;
 };
 
 struct i915_dri1_state {
@@ -1077,34 +1107,30 @@ struct i915_gpu_error {
        unsigned long missed_irq_rings;
 
        /**
-        * State variable and reset counter controlling the reset flow
+        * State variable controlling the reset flow and count
         *
-        * Upper bits are for the reset counter.  This counter is used by the
-        * wait_seqno code to race-free noticed that a reset event happened and
-        * that it needs to restart the entire ioctl (since most likely the
-        * seqno it waited for won't ever signal anytime soon).
+        * This is a counter which gets incremented when reset is triggered,
+        * and again when reset has been handled. So odd values (lowest bit set)
+        * means that reset is in progress and even values that
+        * (reset_counter >> 1):th reset was successfully completed.
+        *
+        * If reset is not completed succesfully, the I915_WEDGE bit is
+        * set meaning that hardware is terminally sour and there is no
+        * recovery. All waiters on the reset_queue will be woken when
+        * that happens.
+        *
+        * This counter is used by the wait_seqno code to notice that reset
+        * event happened and it needs to restart the entire ioctl (since most
+        * likely the seqno it waited for won't ever signal anytime soon).
         *
         * This is important for lock-free wait paths, where no contended lock
         * naturally enforces the correct ordering between the bail-out of the
         * waiter and the gpu reset work code.
-        *
-        * Lowest bit controls the reset state machine: Set means a reset is in
-        * progress. This state will (presuming we don't have any bugs) decay
-        * into either unset (successful reset) or the special WEDGED value (hw
-        * terminally sour). All waiters on the reset_queue will be woken when
-        * that happens.
         */
        atomic_t reset_counter;
 
-       /**
-        * Special values/flags for reset_counter
-        *
-        * Note that the code relies on
-        *      I915_WEDGED & I915_RESET_IN_PROGRESS_FLAG
-        * being true.
-        */
 #define I915_RESET_IN_PROGRESS_FLAG    1
-#define I915_WEDGED                    0xffffffff
+#define I915_WEDGED                    (1 << 31)
 
        /**
         * Waitqueue to signal when the reset has completed. Used by clients
@@ -1158,6 +1184,11 @@ struct intel_vbt_data {
        int edp_bpp;
        struct edp_power_seq edp_pps;
 
+       struct {
+               u16 pwm_freq_hz;
+               bool active_low_pwm;
+       } backlight;
+
        /* MIPI DSI */
        struct {
                u16 panel_id;
@@ -1184,7 +1215,7 @@ struct intel_wm_level {
        uint32_t fbc_val;
 };
 
-struct hsw_wm_values {
+struct ilk_wm_values {
        uint32_t wm_pipe[3];
        uint32_t wm_lp[3];
        uint32_t wm_lp_spr[3];
@@ -1262,6 +1293,10 @@ struct i915_package_c8 {
        } regsave;
 };
 
+struct i915_runtime_pm {
+       bool suspended;
+};
+
 enum intel_pipe_crc_source {
        INTEL_PIPE_CRC_SOURCE_NONE,
        INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1366,15 +1401,9 @@ typedef struct drm_i915_private {
 
        /* overlay */
        struct intel_overlay *overlay;
-       unsigned int sprite_scaling_enabled;
 
-       /* backlight */
-       struct {
-               int level;
-               bool enabled;
-               spinlock_t lock; /* bl registers and the above bl fields */
-               struct backlight_device *device;
-       } backlight;
+       /* backlight registers and fields in struct intel_panel */
+       spinlock_t backlight_lock;
 
        /* LVDS info */
        bool no_aux_handshake;
@@ -1426,6 +1455,7 @@ typedef struct drm_i915_private {
        int num_shared_dpll;
        struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
        struct intel_ddi_plls ddi_plls;
+       int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -1470,7 +1500,6 @@ typedef struct drm_i915_private {
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
-       bool hw_contexts_disabled;
        uint32_t hw_context_size;
        struct list_head context_list;
 
@@ -1492,11 +1521,13 @@ typedef struct drm_i915_private {
                uint16_t cur_latency[5];
 
                /* current hardware state */
-               struct hsw_wm_values hw;
+               struct ilk_wm_values hw;
        } wm;
 
        struct i915_package_c8 pc8;
 
+       struct i915_runtime_pm pm;
+
        /* Old dri1 support infrastructure, beware the dragons ya fools entering
         * here! */
        struct i915_dri1_state dri1;
@@ -1813,15 +1844,15 @@ struct drm_i915_file_private {
 
 #define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
 #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
-#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 
 #define HAS_IPS(dev)           (IS_ULT(dev) || IS_BROADWELL(dev))
 
 #define HAS_DDI(dev)           (INTEL_INFO(dev)->has_ddi)
-#define HAS_POWER_WELL(dev)    (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)           (IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)    (IS_HASWELL(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK               0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
@@ -1911,7 +1942,6 @@ extern void intel_hpd_init(struct drm_device *dev);
 extern void intel_uncore_sanitize(struct drm_device *dev);
 extern void intel_uncore_early_sanitize(struct drm_device *dev);
 extern void intel_uncore_init(struct drm_device *dev);
-extern void intel_uncore_clear_errors(struct drm_device *dev);
 extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
 
@@ -1987,6 +2017,7 @@ void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
@@ -2063,12 +2094,17 @@ int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
 static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
 {
        return unlikely(atomic_read(&error->reset_counter)
-                       & I915_RESET_IN_PROGRESS_FLAG);
+                       & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED));
 }
 
 static inline bool i915_terminally_wedged(struct i915_gpu_error *error)
 {
-       return atomic_read(&error->reset_counter) == I915_WEDGED;
+       return atomic_read(&error->reset_counter) & I915_WEDGED;
+}
+
+static inline u32 i915_reset_count(struct i915_gpu_error *error)
+{
+       return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2;
 }
 
 void i915_gem_reset(struct drm_device *dev);
@@ -2180,7 +2216,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
 }
 
 /* i915_gem_context.c */
-void i915_gem_context_init(struct drm_device *dev);
+int __must_check i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct intel_ring_buffer *ring,
@@ -2398,6 +2434,8 @@ extern int intel_enable_rc6(const struct drm_device *dev);
 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
 int i915_reg_read_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file);
+int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file);
 
 /* overlay */
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@@ -2413,8 +2451,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
  * must be set to prevent GT core from power down and stale values being
  * returned.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
@@ -2429,6 +2467,8 @@ u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg);
@@ -2437,9 +2477,30 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
                   enum intel_sbi_destination destination);
 void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                     enum intel_sbi_destination destination);
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
+
+#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
+       (((reg) >= 0x2000 && (reg) < 0x4000) ||\
+       ((reg) >= 0x5000 && (reg) < 0x8000) ||\
+       ((reg) >= 0xB000 && (reg) < 0x12000) ||\
+       ((reg) >= 0x2E000 && (reg) < 0x30000))
+
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
+       (((reg) >= 0x12000 && (reg) < 0x14000) ||\
+       ((reg) >= 0x22000 && (reg) < 0x24000) ||\
+       ((reg) >= 0x30000 && (reg) < 0x40000))
+
+#define FORCEWAKE_RENDER       (1 << 0)
+#define FORCEWAKE_MEDIA                (1 << 1)
+#define FORCEWAKE_ALL          (FORCEWAKE_RENDER | FORCEWAKE_MEDIA)
 
-int vlv_gpu_freq(int ddr_freq, int val);
-int vlv_freq_opcode(int ddr_freq, int val);
 
 #define I915_READ8(reg)                dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
 #define I915_WRITE8(reg, val)  dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true)
index 76d3d1ab73c6965063eba62527594dce82dc41d4..32636a4703673d1ca952381a41b63c3732813208 100644 (file)
@@ -1015,9 +1015,11 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                        struct drm_i915_file_private *file_priv)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
+       const bool irq_test_in_progress =
+               ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
        struct timespec before, now;
        DEFINE_WAIT(wait);
-       long timeout_jiffies;
+       unsigned long timeout_expire;
        int ret;
 
        WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n");
@@ -1025,7 +1027,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
                return 0;
 
-       timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1;
+       timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
 
        if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
                gen6_rps_boost(dev_priv);
@@ -1035,8 +1037,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                                         msecs_to_jiffies(100));
        }
 
-       if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) &&
-           WARN_ON(!ring->irq_get(ring)))
+       if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
                return -ENODEV;
 
        /* Record current time in case interrupted by signal, or wedged */
@@ -1044,7 +1045,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        getrawmonotonic(&before);
        for (;;) {
                struct timer_list timer;
-               unsigned long expire;
 
                prepare_to_wait(&ring->irq_queue, &wait,
                                interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
@@ -1070,23 +1070,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                        break;
                }
 
-               if (timeout_jiffies <= 0) {
+               if (timeout && time_after_eq(jiffies, timeout_expire)) {
                        ret = -ETIME;
                        break;
                }
 
                timer.function = NULL;
                if (timeout || missed_irq(dev_priv, ring)) {
+                       unsigned long expire;
+
                        setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
-                       expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies);
+                       expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
                        mod_timer(&timer, expire);
                }
 
                io_schedule();
 
-               if (timeout)
-                       timeout_jiffies = expire - jiffies;
-
                if (timer.function) {
                        del_singleshot_timer_sync(&timer);
                        destroy_timer_on_stack(&timer);
@@ -1095,7 +1094,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        getrawmonotonic(&now);
        trace_i915_gem_request_wait_end(ring, seqno);
 
-       ring->irq_put(ring);
+       if (!irq_test_in_progress)
+               ring->irq_put(ring);
 
        finish_wait(&ring->irq_queue, &wait);
 
@@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        int ret = 0;
        bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
 
+       intel_runtime_pm_get(dev_priv);
+
        /* We don't use vmf->pgoff since that has the fake offset */
        page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
                PAGE_SHIFT;
@@ -1427,8 +1429,10 @@ out:
                /* If this -EIO is due to a gpu hang, give the reset code a
                 * chance to clean up the mess. Otherwise return the proper
                 * SIGBUS. */
-               if (i915_terminally_wedged(&dev_priv->gpu_error))
-                       return VM_FAULT_SIGBUS;
+               if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+                       ret = VM_FAULT_SIGBUS;
+                       break;
+               }
        case -EAGAIN:
                /*
                 * EAGAIN means the gpu is hung and we'll wait for the error
@@ -1443,15 +1447,38 @@ out:
                 * EBUSY is ok: this just means that another thread
                 * already did the job.
                 */
-               return VM_FAULT_NOPAGE;
+               ret = VM_FAULT_NOPAGE;
+               break;
        case -ENOMEM:
-               return VM_FAULT_OOM;
+               ret = VM_FAULT_OOM;
+               break;
        case -ENOSPC:
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        default:
                WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        }
+
+       intel_runtime_pm_put(dev_priv);
+       return ret;
+}
+
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+{
+       struct i915_vma *vma;
+
+       /*
+        * Only the global gtt is relevant for gtt memory mappings, so restrict
+        * list traversal to objects bound into the global address space. Note
+        * that the active list should be empty, but better safe than sorry.
+        */
+       WARN_ON(!list_empty(&dev_priv->gtt.base.active_list));
+       list_for_each_entry(vma, &dev_priv->gtt.base.active_list, mm_list)
+               i915_gem_release_mmap(vma->obj);
+       list_for_each_entry(vma, &dev_priv->gtt.base.inactive_list, mm_list)
+               i915_gem_release_mmap(vma->obj);
 }
 
 /**
@@ -2760,7 +2787,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->has_aliasing_ppgtt_mapping = 0;
        }
        i915_gem_gtt_finish_object(obj);
-       i915_gem_object_unpin_pages(obj);
 
        list_del(&vma->mm_list);
        /* Avoid an unnecessary call to unbind on rebind. */
@@ -2768,7 +2794,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->map_and_fenceable = true;
 
        drm_mm_remove_node(&vma->node);
-
        i915_gem_vma_destroy(vma);
 
        /* Since the unbound list is global, only move to that list if
@@ -2776,6 +2801,12 @@ int i915_vma_unbind(struct i915_vma *vma)
        if (list_empty(&obj->vma_list))
                list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 
+       /* And finally now the object is completely decoupled from this vma,
+        * we can drop its hold on the backing storage and allow it to be
+        * reaped by the shrinker.
+        */
+       i915_gem_object_unpin_pages(obj);
+
        return 0;
 }
 
@@ -4179,6 +4210,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct i915_vma *vma, *next;
 
+       intel_runtime_pm_get(dev_priv);
+
        trace_i915_gem_object_destroy(obj);
 
        if (obj->phys_obj)
@@ -4223,6 +4256,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
        kfree(obj->bit_17);
        i915_gem_object_free(obj);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
@@ -4479,7 +4514,13 @@ i915_gem_init_hw(struct drm_device *dev)
         * XXX: There was some w/a described somewhere suggesting loading
         * contexts before PPGTT.
         */
-       i915_gem_context_init(dev);
+       ret = i915_gem_context_init(dev);
+       if (ret) {
+               i915_gem_cleanup_ringbuffer(dev);
+               DRM_ERROR("Context initialization failed %d\n", ret);
+               return ret;
+       }
+
        if (dev_priv->mm.aliasing_ppgtt) {
                ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
                if (ret) {
index b0f42b9ca037ed472e1a0dd4cd663df6ffd70f06..e08acaba540269736777a7f7758a88d97f2aa4b6 100644 (file)
@@ -247,36 +247,34 @@ err_destroy:
        return ret;
 }
 
-void i915_gem_context_init(struct drm_device *dev)
+int i915_gem_context_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
-       if (!HAS_HW_CONTEXTS(dev)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
-               return;
-       }
+       if (!HAS_HW_CONTEXTS(dev))
+               return 0;
 
        /* If called from reset, or thaw... we've been here already */
-       if (dev_priv->hw_contexts_disabled ||
-           dev_priv->ring[RCS].default_context)
-               return;
+       if (dev_priv->ring[RCS].default_context)
+               return 0;
 
        dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
 
        if (dev_priv->hw_context_size > (1<<20)) {
-               dev_priv->hw_contexts_disabled = true;
                DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
-               return;
+               return -E2BIG;
        }
 
-       if (create_default_context(dev_priv)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
-               return;
+       ret = create_default_context(dev_priv);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n",
+                                ret);
+               return ret;
        }
 
        DRM_DEBUG_DRIVER("HW context support initialized\n");
+       return 0;
 }
 
 void i915_gem_context_fini(struct drm_device *dev)
@@ -284,7 +282,7 @@ void i915_gem_context_fini(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return;
 
        /* The only known way to stop the gpu from accessing the hw context is
@@ -327,16 +325,16 @@ i915_gem_context_get_hang_stats(struct drm_device *dev,
                                struct drm_file *file,
                                u32 id)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
 
        if (id == DEFAULT_CONTEXT_ID)
                return &file_priv->hang_stats;
 
-       ctx = NULL;
-       if (!dev_priv->hw_contexts_disabled)
-               ctx = i915_gem_context_get(file->driver_priv, id);
+       if (!HAS_HW_CONTEXTS(dev))
+               return ERR_PTR(-ENOENT);
+
+       ctx = i915_gem_context_get(file->driver_priv, id);
        if (ctx == NULL)
                return ERR_PTR(-ENOENT);
 
@@ -502,8 +500,6 @@ static int do_switch(struct i915_hw_context *to)
  * @ring: ring for which we'll execute the context switch
  * @file_priv: file_priv associated with the context, may be NULL
  * @id: context id number
- * @seqno: sequence number by which the new context will be switched to
- * @flags:
  *
  * The context life cycle is simple. The context refcount is incremented and
  * decremented by 1 and create and destroy. If the context is in use by the GPU,
@@ -517,7 +513,7 @@ int i915_switch_context(struct intel_ring_buffer *ring,
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct i915_hw_context *to;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(ring->dev))
                return 0;
 
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
@@ -542,7 +538,6 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_context_create *args = data;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
@@ -551,7 +546,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        if (!(dev->driver->driver_features & DRIVER_GEM))
                return -ENODEV;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return -ENODEV;
 
        ret = i915_mutex_lock_interruptible(dev);
index a3ba9a8cd68794bbfd163c9236c91c7be9d15965..8d795626a25e2de40bf70f872c4495fb72ebb732 100644 (file)
@@ -46,7 +46,7 @@ struct eb_vmas {
 };
 
 static struct eb_vmas *
-eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm)
+eb_create(struct drm_i915_gem_execbuffer2 *args)
 {
        struct eb_vmas *eb = NULL;
 
@@ -344,7 +344,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
        target_i915_obj = target_vma->obj;
        target_obj = &target_vma->obj->base;
 
-       target_offset = i915_gem_obj_ggtt_offset(target_i915_obj);
+       target_offset = target_vma->node.start;
 
        /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
         * pipe_control writes because the gpu doesn't properly redirect them
@@ -491,8 +491,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct eb_vmas *eb,
-                            struct i915_address_space *vm)
+i915_gem_execbuffer_relocate(struct eb_vmas *eb)
 {
        struct i915_vma *vma;
        int ret = 0;
@@ -901,6 +900,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
        return 0;
 }
 
+static int
+i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+                         const u32 ctx_id)
+{
+       struct i915_ctx_hang_stats *hs;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
+       if (IS_ERR(hs))
+               return PTR_ERR(hs);
+
+       if (hs->banned) {
+               DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                                   struct intel_ring_buffer *ring)
@@ -980,8 +997,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *batch_obj;
        struct drm_clip_rect *cliprects = NULL;
        struct intel_ring_buffer *ring;
-       struct i915_ctx_hang_stats *hs;
-       u32 ctx_id = i915_execbuffer2_get_context_id(*args);
+       const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
        u32 exec_start, exec_len;
        u32 mask, flags;
        int ret, mode, i;
@@ -1108,6 +1124,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
        }
 
+       intel_runtime_pm_get(dev_priv);
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                goto pre_mutex_err;
@@ -1118,7 +1136,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                goto pre_mutex_err;
        }
 
-       eb = eb_create(args, vm);
+       ret = i915_gem_validate_context(dev, file, ctx_id);
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
+               goto pre_mutex_err;
+       }
+
+       eb = eb_create(args);
        if (eb == NULL) {
                mutex_unlock(&dev->struct_mutex);
                ret = -ENOMEM;
@@ -1141,7 +1165,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
        /* The objects are in their final locations, apply the relocations. */
        if (need_relocs)
-               ret = i915_gem_execbuffer_relocate(eb, vm);
+               ret = i915_gem_execbuffer_relocate(eb);
        if (ret) {
                if (ret == -EFAULT) {
                        ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
@@ -1170,17 +1194,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        if (ret)
                goto err;
 
-       hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
-       if (IS_ERR(hs)) {
-               ret = PTR_ERR(hs);
-               goto err;
-       }
-
-       if (hs->banned) {
-               ret = -EIO;
-               goto err;
-       }
-
        ret = i915_switch_context(ring, file, ctx_id);
        if (ret)
                goto err;
@@ -1242,6 +1255,10 @@ err:
 
 pre_mutex_err:
        kfree(cliprects);
+
+       /* intel_gpu_busy should also get a ref, so it will free when the device
+        * is really idle. */
+       intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
index c79dd2b1f70ecc2af6d0fb67a3c3289672eba7f9..6c3a6e60aeac1eba0a7b2339683a201e1e1a2bbd 100644 (file)
@@ -240,10 +240,16 @@ static int gen8_ppgtt_enable(struct drm_device *dev)
                for_each_ring(ring, dev_priv, j) {
                        ret = gen8_write_pdp(ring, i, addr);
                        if (ret)
-                               return ret;
+                               goto err_out;
                }
        }
        return 0;
+
+err_out:
+       for_each_ring(ring, dev_priv, j)
+               I915_WRITE(RING_MODE_GEN7(ring),
+                          _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE));
+       return ret;
 }
 
 static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
@@ -293,23 +299,23 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
        unsigned act_pte = first_entry % GEN8_PTES_PER_PAGE;
        struct sg_page_iter sg_iter;
 
-       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
+       pt_vaddr = NULL;
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
-               dma_addr_t page_addr;
+               if (pt_vaddr == NULL)
+                       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
 
-               page_addr = sg_dma_address(sg_iter.sg) +
-                               (sg_iter.sg_pgoffset << PAGE_SHIFT);
-               pt_vaddr[act_pte] = gen8_pte_encode(page_addr, cache_level,
-                                                   true);
+               pt_vaddr[act_pte] =
+                       gen8_pte_encode(sg_page_iter_dma_address(&sg_iter),
+                                       cache_level, true);
                if (++act_pte == GEN8_PTES_PER_PAGE) {
                        kunmap_atomic(pt_vaddr);
+                       pt_vaddr = NULL;
                        act_pt++;
-                       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
                        act_pte = 0;
-
                }
        }
-       kunmap_atomic(pt_vaddr);
+       if (pt_vaddr)
+               kunmap_atomic(pt_vaddr);
 }
 
 static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
@@ -318,6 +324,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                container_of(vm, struct i915_hw_ppgtt, base);
        int i, j;
 
+       drm_mm_takedown(&vm->mm);
+
        for (i = 0; i < ppgtt->num_pd_pages ; i++) {
                if (ppgtt->pd_dma_addr[i]) {
                        pci_unmap_page(ppgtt->base.dev->pdev,
@@ -381,6 +389,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
        ppgtt->base.clear_range = gen8_ppgtt_clear_range;
        ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen8_ppgtt_cleanup;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
 
        BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
 
@@ -573,21 +583,23 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
        unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        struct sg_page_iter sg_iter;
 
-       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
+       pt_vaddr = NULL;
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
-               dma_addr_t page_addr;
+               if (pt_vaddr == NULL)
+                       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
 
-               page_addr = sg_page_iter_dma_address(&sg_iter);
-               pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
+               pt_vaddr[act_pte] =
+                       vm->pte_encode(sg_page_iter_dma_address(&sg_iter),
+                                      cache_level, true);
                if (++act_pte == I915_PPGTT_PT_ENTRIES) {
                        kunmap_atomic(pt_vaddr);
+                       pt_vaddr = NULL;
                        act_pt++;
-                       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
                        act_pte = 0;
-
                }
        }
-       kunmap_atomic(pt_vaddr);
+       if (pt_vaddr)
+               kunmap_atomic(pt_vaddr);
 }
 
 static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
@@ -632,6 +644,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen6_ppgtt_cleanup;
        ppgtt->base.scratch = dev_priv->gtt.base.scratch;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
        ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
                                  GFP_KERNEL);
        if (!ppgtt->pt_pages)
@@ -906,14 +920,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
                WARN_ON(readq(&gtt_entries[i-1])
                        != gen8_pte_encode(addr, level, true));
 
-#if 0 /* TODO: Still needed on GEN8? */
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
         * have finished.
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-#endif
 }
 
 /*
@@ -1126,7 +1138,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
                if (ret)
                        DRM_DEBUG_KMS("Reservation failed\n");
                obj->has_global_gtt_mapping = 1;
-               list_add(&vma->vma_link, &obj->vma_list);
        }
 
        dev_priv->gtt.base.start = start;
@@ -1402,6 +1413,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
 {
 
        struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
+
+       drm_mm_takedown(&vm->mm);
        iounmap(gtt->gsm);
        teardown_scratch_page(vm->dev);
 }
@@ -1427,6 +1440,9 @@ static int i915_gmch_probe(struct drm_device *dev,
        dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
        dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
 
+       if (unlikely(dev_priv->gtt.do_idle_maps))
+               DRM_INFO("applying Ironlake quirks for intel_iommu\n");
+
        return 0;
 }
 
index d284d892ed9491e8f2a618e22576673e06887f74..fed87ec17211941f26c83a5dd2cdd558da45e9f2 100644 (file)
@@ -420,6 +420,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 
        list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
        list_add_tail(&vma->mm_list, &ggtt->inactive_list);
+       i915_gem_object_pin_pages(obj);
 
        return obj;
 
index 79dcb8f896c6f34363e6bd62e90f1773bfcf8f0a..a707cca692e442f37f9b1db1b91e14bce388a109 100644 (file)
@@ -247,12 +247,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
        err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
        err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
        err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
-       if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
-               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
-       if (INTEL_INFO(dev)->gen >= 4)
+       if (INTEL_INFO(dev)->gen >= 4) {
+               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr[ring]);
                err_printf(m, "  BB_STATE: 0x%08x\n", error->bbstate[ring]);
-       if (INTEL_INFO(dev)->gen >= 4)
                err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+       }
        err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
        err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
        if (INTEL_INFO(dev)->gen >= 6) {
@@ -725,8 +724,9 @@ static void i915_record_ring_state(struct drm_device *dev,
                error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
                error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
                error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-               if (ring->id == RCS)
-                       error->bbaddr = I915_READ64(BB_ADDR);
+               error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
+               if (INTEL_INFO(dev)->gen >= 8)
+                       error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
                error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
        } else {
                error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
index 5d1dedc02f159c8b7a21d23a940df9c5bf0c2bd2..17d8fcb1b6f7ac113b4c0c035088979b1c8083b4 100644 (file)
@@ -62,7 +62,7 @@ static const u32 hpd_mask_i915[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
 };
 
-static const u32 hpd_status_gen4[] = {
+static const u32 hpd_status_g4x[] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
@@ -600,7 +600,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
         * Cook up a vblank counter by also checking the pixel
         * counter against vblank start.
         */
-       return ((high1 << 8) | low) + (pixel >= vbl_start);
+       return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
 }
 
 static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
@@ -621,36 +621,15 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 #define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
 #define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
 
-static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
+static bool ilk_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t status;
-       int reg;
 
-       if (IS_VALLEYVIEW(dev)) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = VLV_ISR;
-       } else if (IS_GEN2(dev)) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = ISR;
-       } else if (INTEL_INFO(dev)->gen < 5) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = ISR;
-       } else if (INTEL_INFO(dev)->gen < 7) {
+       if (INTEL_INFO(dev)->gen < 7) {
                status = pipe == PIPE_A ?
                        DE_PIPEA_VBLANK :
                        DE_PIPEB_VBLANK;
-
-               reg = DEISR;
        } else {
                switch (pipe) {
                default:
@@ -664,18 +643,14 @@ static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
                        status = DE_PIPEC_VBLANK_IVB;
                        break;
                }
-
-               reg = DEISR;
        }
 
-       if (IS_GEN2(dev))
-               return __raw_i915_read16(dev_priv, reg) & status;
-       else
-               return __raw_i915_read32(dev_priv, reg) & status;
+       return __raw_i915_read32(dev_priv, DEISR) & status;
 }
 
 static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
-                            int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+                                   unsigned int flags, int *vpos, int *hpos,
+                                   ktime_t *stime, ktime_t *etime)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
@@ -698,6 +673,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
        vbl_start = mode->crtc_vblank_start;
        vbl_end = mode->crtc_vblank_end;
 
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               vbl_start = DIV_ROUND_UP(vbl_start, 2);
+               vbl_end /= 2;
+               vtotal /= 2;
+       }
+
        ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
 
        /*
@@ -722,17 +703,42 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
                else
                        position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
 
-               /*
-                * The scanline counter increments at the leading edge
-                * of hsync, ie. it completely misses the active portion
-                * of the line. Fix up the counter at both edges of vblank
-                * to get a more accurate picture whether we're in vblank
-                * or not.
-                */
-               in_vbl = intel_pipe_in_vblank_locked(dev, pipe);
-               if ((in_vbl && position == vbl_start - 1) ||
-                   (!in_vbl && position == vbl_end - 1))
-                       position = (position + 1) % vtotal;
+               if (HAS_PCH_SPLIT(dev)) {
+                       /*
+                        * The scanline counter increments at the leading edge
+                        * of hsync, ie. it completely misses the active portion
+                        * of the line. Fix up the counter at both edges of vblank
+                        * to get a more accurate picture whether we're in vblank
+                        * or not.
+                        */
+                       in_vbl = ilk_pipe_in_vblank_locked(dev, pipe);
+                       if ((in_vbl && position == vbl_start - 1) ||
+                           (!in_vbl && position == vbl_end - 1))
+                               position = (position + 1) % vtotal;
+               } else {
+                       /*
+                        * ISR vblank status bits don't work the way we'd want
+                        * them to work on non-PCH platforms (for
+                        * ilk_pipe_in_vblank_locked()), and there doesn't
+                        * appear any other way to determine if we're currently
+                        * in vblank.
+                        *
+                        * Instead let's assume that we're already in vblank if
+                        * we got called from the vblank interrupt and the
+                        * scanline counter value indicates that we're on the
+                        * line just prior to vblank start. This should result
+                        * in the correct answer, unless the vblank interrupt
+                        * delivery really got delayed for almost exactly one
+                        * full frame/field.
+                        */
+                       if (flags & DRM_CALLED_FROM_VBLIRQ &&
+                           position == vbl_start - 1) {
+                               position = (position + 1) % vtotal;
+
+                               /* Signal this correction as "applied". */
+                               ret |= 0x8;
+                       }
+               }
        } else {
                /* Have access to pixelcount since start of frame.
                 * We can split this into vertical and horizontal
@@ -809,7 +815,8 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
                                                     vblank_time, flags,
-                                                    crtc);
+                                                    crtc,
+                                                    &to_intel_crtc(crtc)->config.adjusted_mode);
 }
 
 static bool intel_hpd_irq_event(struct drm_device *dev,
@@ -1015,10 +1022,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
        /* sysfs frequency interfaces may have snuck in while servicing the
         * interrupt
         */
-       if (new_delay < (int)dev_priv->rps.min_delay)
-               new_delay = dev_priv->rps.min_delay;
-       if (new_delay > (int)dev_priv->rps.max_delay)
-               new_delay = dev_priv->rps.max_delay;
+       new_delay = clamp_t(int, new_delay,
+                           dev_priv->rps.min_delay, dev_priv->rps.max_delay);
        dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
 
        if (IS_VALLEYVIEW(dev_priv->dev))
@@ -1235,9 +1240,10 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
        spin_lock(&dev_priv->irq_lock);
        for (i = 1; i < HPD_NUM_PINS; i++) {
 
-               WARN(((hpd[i] & hotplug_trigger) &&
-                     dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED),
-                    "Received HPD interrupt although disabled\n");
+               WARN_ONCE(hpd[i] & hotplug_trigger &&
+                         dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED,
+                         "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
+                         hotplug_trigger, i, hpd[i]);
 
                if (!(hpd[i] & hotplug_trigger) ||
                    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
@@ -1474,6 +1480,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 
                        intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
 
+                       if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+                               dp_aux_irq_handler(dev);
+
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
                }
@@ -1993,7 +2002,7 @@ static void i915_error_work_func(struct work_struct *work)
                        kobject_uevent_env(&dev->primary->kdev->kobj,
                                           KOBJ_CHANGE, reset_done_event);
                } else {
-                       atomic_set(&error->reset_counter, I915_WEDGED);
+                       atomic_set_mask(I915_WEDGED, &error->reset_counter);
                }
 
                /*
@@ -2713,6 +2722,8 @@ static void gen8_irq_preinstall(struct drm_device *dev)
 #undef GEN8_IRQ_INIT_NDX
 
        POSTING_READ(GEN8_PCU_IIR);
+
+       ibx_irq_preinstall(dev);
 }
 
 static void ibx_hpd_irq_setup(struct drm_device *dev)
@@ -3138,10 +3149,10 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
  * Returns true when a page flip has completed.
  */
 static bool i8xx_handle_vblank(struct drm_device *dev,
-                              int pipe, u16 iir)
+                              int plane, int pipe, u32 iir)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
+       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
 
        if (!drm_handle_vblank(dev, pipe))
                return false;
@@ -3149,7 +3160,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
        if ((iir & flip_pending) == 0)
                return false;
 
-       intel_prepare_page_flip(dev, pipe);
+       intel_prepare_page_flip(dev, plane);
 
        /* We detect FlipDone by looking for the change in PendingFlip from '1'
         * to '0' on the following vblank, i.e. IIR has the Pendingflip
@@ -3218,9 +3229,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                        notify_ring(dev, &dev_priv->ring[RCS]);
 
                for_each_pipe(pipe) {
+                       int plane = pipe;
+                       if (HAS_FBC(dev))
+                               plane = !plane;
+
                        if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
-                           i8xx_handle_vblank(dev, pipe, iir))
-                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
+                           i8xx_handle_vblank(dev, plane, pipe, iir))
+                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
 
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                i9xx_pipe_crc_irq_handler(dev, pipe);
@@ -3416,7 +3431,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
                for_each_pipe(pipe) {
                        int plane = pipe;
-                       if (IS_MOBILE(dev))
+                       if (HAS_FBC(dev))
                                plane = !plane;
 
                        if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
@@ -3653,7 +3668,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                                  hotplug_status);
 
                        intel_hpd_irq_handler(dev, hotplug_trigger,
-                                             IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915);
+                                             IS_G4X(dev) ? hpd_status_g4x : hpd_status_i915);
+
+                       if (IS_G4X(dev) &&
+                           (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X))
+                               dp_aux_irq_handler(dev);
 
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
@@ -3891,8 +3910,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
        dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
        dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
 
-       ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
-       ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
+       ironlake_disable_display_irq(dev_priv, 0xffffffff);
+       ibx_disable_display_interrupt(dev_priv, 0xffffffff);
        ilk_disable_gt_irq(dev_priv, 0xffffffff);
        snb_disable_pm_irq(dev_priv, 0xffffffff);
 
@@ -3906,34 +3925,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
-       uint32_t val, expected;
+       uint32_t val;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
        val = I915_READ(DEIMR);
-       expected = ~DE_PCH_EVENT_IVB;
-       WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
 
-       val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
-       expected = ~SDE_HOTPLUG_MASK_CPT;
-       WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
-            val, expected);
+       val = I915_READ(SDEIMR);
+       WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
 
        val = I915_READ(GTIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
 
        val = I915_READ(GEN6_PMIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
-            expected);
+       WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
 
        dev_priv->pc8.irqs_disabled = false;
 
        ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
-       ibx_enable_display_interrupt(dev_priv,
-                                    ~dev_priv->pc8.regsave.sdeimr &
-                                    ~SDE_HOTPLUG_MASK_CPT);
+       ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
        ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
        snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
        I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
index ee2742122a02561f910b6d9d5383418794234eff..76126e0ae609023e4644c6aa336553a8815c7d6b 100644 (file)
 #define   MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
 #define   MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
 #define   MI_INVALIDATE_ISP    (1 << 5) /* invalidate indirect state pointers */
+#define MI_REPORT_HEAD         MI_INSTR(0x07, 0)
+#define MI_ARB_ON_OFF          MI_INSTR(0x08, 0)
+#define   MI_ARB_ENABLE                        (1<<0)
+#define   MI_ARB_DISABLE               (0<<0)
 #define MI_BATCH_BUFFER_END    MI_INSTR(0x0a, 0)
 #define MI_SUSPEND_FLUSH       MI_INSTR(0x0b, 0)
 #define   MI_SUSPEND_FLUSH_EN  (1<<0)
-#define MI_REPORT_HEAD         MI_INSTR(0x07, 0)
 #define MI_OVERLAY_FLIP                MI_INSTR(0x11, 0)
 #define   MI_OVERLAY_CONTINUE  (0x0<<21)
 #define   MI_OVERLAY_ON                (0x1<<21)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
-#define MI_ARB_ON_OFF          MI_INSTR(0x08, 0)
-#define   MI_ARB_ENABLE                        (1<<0)
-#define   MI_ARB_DISABLE               (0<<0)
-
+#define MI_SEMAPHORE_MBOX      MI_INSTR(0x16, 1) /* gen6+ */
+#define   MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
+#define   MI_SEMAPHORE_UPDATE      (1<<21)
+#define   MI_SEMAPHORE_COMPARE     (1<<20)
+#define   MI_SEMAPHORE_REGISTER            (1<<18)
+#define   MI_SEMAPHORE_SYNC_VR     (0<<16) /* RCS  wait for VCS  (RVSYNC) */
+#define   MI_SEMAPHORE_SYNC_VER            (1<<16) /* RCS  wait for VECS (RVESYNC) */
+#define   MI_SEMAPHORE_SYNC_BR     (2<<16) /* RCS  wait for BCS  (RBSYNC) */
+#define   MI_SEMAPHORE_SYNC_BV     (0<<16) /* VCS  wait for BCS  (VBSYNC) */
+#define   MI_SEMAPHORE_SYNC_VEV            (1<<16) /* VCS  wait for VECS (VVESYNC) */
+#define   MI_SEMAPHORE_SYNC_RV     (2<<16) /* VCS  wait for RCS  (VRSYNC) */
+#define   MI_SEMAPHORE_SYNC_RB     (0<<16) /* BCS  wait for RCS  (BRSYNC) */
+#define   MI_SEMAPHORE_SYNC_VEB            (1<<16) /* BCS  wait for VECS (BVESYNC) */
+#define   MI_SEMAPHORE_SYNC_VB     (2<<16) /* BCS  wait for VCS  (BVSYNC) */
+#define   MI_SEMAPHORE_SYNC_BVE            (0<<16) /* VECS wait for BCS  (VEBSYNC) */
+#define   MI_SEMAPHORE_SYNC_VVE            (1<<16) /* VECS wait for VCS  (VEVSYNC) */
+#define   MI_SEMAPHORE_SYNC_RVE            (2<<16) /* VECS wait for RCS  (VERSYNC) */
+#define   MI_SEMAPHORE_SYNC_INVALID  (3<<16)
 #define MI_SET_CONTEXT         MI_INSTR(0x18, 0)
 #define   MI_MM_SPACE_GTT              (1<<8)
 #define   MI_MM_SPACE_PHYSICAL         (0<<8)
  */
 #define MI_LOAD_REGISTER_IMM(x)        MI_INSTR(0x22, 2*x-1)
 #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
-#define  MI_SRM_LRM_GLOBAL_GTT         (1<<22)
+#define   MI_SRM_LRM_GLOBAL_GTT                (1<<22)
 #define MI_FLUSH_DW            MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX      (1<<21)
 #define   MI_INVALIDATE_TLB            (1<<18)
 #define MI_BATCH_BUFFER                MI_INSTR(0x30, 1)
 #define   MI_BATCH_NON_SECURE          (1)
 /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */
-#define   MI_BATCH_NON_SECURE_I965     (1<<8)
+#define   MI_BATCH_NON_SECURE_I965     (1<<8)
 #define   MI_BATCH_PPGTT_HSW           (1<<8)
-#define   MI_BATCH_NON_SECURE_HSW      (1<<13)
+#define   MI_BATCH_NON_SECURE_HSW      (1<<13)
 #define MI_BATCH_BUFFER_START  MI_INSTR(0x31, 0)
 #define   MI_BATCH_GTT             (2<<6) /* aliased with (1<<7) on gen4 */
 #define MI_BATCH_BUFFER_START_GEN8     MI_INSTR(0x31, 1)
-#define MI_SEMAPHORE_MBOX      MI_INSTR(0x16, 1) /* gen6+ */
-#define  MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
-#define  MI_SEMAPHORE_UPDATE       (1<<21)
-#define  MI_SEMAPHORE_COMPARE      (1<<20)
-#define  MI_SEMAPHORE_REGISTER     (1<<18)
-#define  MI_SEMAPHORE_SYNC_VR      (0<<16) /* RCS  wait for VCS  (RVSYNC) */
-#define  MI_SEMAPHORE_SYNC_VER     (1<<16) /* RCS  wait for VECS (RVESYNC) */
-#define  MI_SEMAPHORE_SYNC_BR      (2<<16) /* RCS  wait for BCS  (RBSYNC) */
-#define  MI_SEMAPHORE_SYNC_BV      (0<<16) /* VCS  wait for BCS  (VBSYNC) */
-#define  MI_SEMAPHORE_SYNC_VEV     (1<<16) /* VCS  wait for VECS (VVESYNC) */
-#define  MI_SEMAPHORE_SYNC_RV      (2<<16) /* VCS  wait for RCS  (VRSYNC) */
-#define  MI_SEMAPHORE_SYNC_RB      (0<<16) /* BCS  wait for RCS  (BRSYNC) */
-#define  MI_SEMAPHORE_SYNC_VEB     (1<<16) /* BCS  wait for VECS (BVESYNC) */
-#define  MI_SEMAPHORE_SYNC_VB      (2<<16) /* BCS  wait for VCS  (BVSYNC) */
-#define  MI_SEMAPHORE_SYNC_BVE     (0<<16) /* VECS wait for BCS  (VEBSYNC) */
-#define  MI_SEMAPHORE_SYNC_VVE     (1<<16) /* VECS wait for VCS  (VEVSYNC) */
-#define  MI_SEMAPHORE_SYNC_RVE     (2<<16) /* VECS wait for RCS  (VERSYNC) */
-#define  MI_SEMAPHORE_SYNC_INVALID  (3<<16)
+
 
 #define MI_PREDICATE_RESULT_2  (0x2214)
 #define  LOWER_SLICE_ENABLED   (1<<0)
 #define   IOSF_BYTE_ENABLES_SHIFT              4
 #define   IOSF_BAR_SHIFT                       1
 #define   IOSF_SB_BUSY                         (1<<0)
+#define   IOSF_PORT_BUNIT                      0x3
 #define   IOSF_PORT_PUNIT                      0x4
 #define   IOSF_PORT_NC                         0x11
 #define   IOSF_PORT_DPIO                       0x12
 #define   IOSF_PORT_CCK                                0x14
 #define   IOSF_PORT_CCU                                0xA9
 #define   IOSF_PORT_GPS_CORE                   0x48
+#define   IOSF_PORT_FLISDSI                    0x1B
 #define VLV_IOSF_DATA                          (VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR                          (VLV_DISPLAY_BASE + 0x2108)
 
+/* See configdb bunit SB addr map */
+#define BUNIT_REG_BISOC                                0x11
+
 #define PUNIT_OPCODE_REG_READ                  6
 #define PUNIT_OPCODE_REG_WRITE                 7
 
+#define PUNIT_REG_DSPFREQ                      0x36
+#define   DSPFREQSTAT_SHIFT                    30
+#define   DSPFREQSTAT_MASK                     (0x3 << DSPFREQSTAT_SHIFT)
+#define   DSPFREQGUAR_SHIFT                    14
+#define   DSPFREQGUAR_MASK                     (0x3 << DSPFREQGUAR_SHIFT)
 #define PUNIT_REG_PWRGT_CTRL                   0x60
 #define PUNIT_REG_PWRGT_STATUS                 0x61
 #define          PUNIT_CLK_GATE                        1
 #define  DSI_PLL_N1_DIV_MASK                   (3 << 16)
 #define  DSI_PLL_M1_DIV_SHIFT                  0
 #define  DSI_PLL_M1_DIV_MASK                   (0x1ff << 0)
+#define CCK_DISPLAY_CLOCK_CONTROL              0x6b
 
 /*
  * DPIO - a special bus for various display related registers to hide behind
 #define  DPIO_SFR_BYPASS               (1<<1)
 #define  DPIO_CMNRST                   (1<<0)
 
-#define _DPIO_TX3_SWING_CTL4_A         0x690
-#define _DPIO_TX3_SWING_CTL4_B         0x2a90
-#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \
-                                       _DPIO_TX3_SWING_CTL4_B)
+#define DPIO_PHY(pipe)                 ((pipe) >> 1)
+#define DPIO_PHY_IOSF_PORT(phy)                (dev_priv->dpio_phy_iosf_port[phy])
 
 /*
  * Per pipe/PLL DPIO regs
  */
-#define _DPIO_DIV_A                    0x800c
+#define _VLV_PLL_DW3_CH0               0x800c
 #define   DPIO_POST_DIV_SHIFT          (28) /* 3 bits */
 #define   DPIO_POST_DIV_DAC            0
 #define   DPIO_POST_DIV_HDMIDP         1 /* DAC 225-400M rate */
 #define   DPIO_ENABLE_CALIBRATION      (1<<11)
 #define   DPIO_M1DIV_SHIFT             (8) /* 3 bits */
 #define   DPIO_M2DIV_MASK              0xff
-#define _DPIO_DIV_B                    0x802c
-#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B)
+#define _VLV_PLL_DW3_CH1               0x802c
+#define VLV_PLL_DW3(ch) _PIPE(ch, _VLV_PLL_DW3_CH0, _VLV_PLL_DW3_CH1)
 
-#define _DPIO_REFSFR_A                 0x8014
+#define _VLV_PLL_DW5_CH0               0x8014
 #define   DPIO_REFSEL_OVERRIDE         27
 #define   DPIO_PLL_MODESEL_SHIFT       24 /* 3 bits */
 #define   DPIO_BIAS_CURRENT_CTL_SHIFT  21 /* 3 bits, always 0x7 */
 #define   DPIO_PLL_REFCLK_SEL_MASK     3
 #define   DPIO_DRIVER_CTL_SHIFT                12 /* always set to 0x8 */
 #define   DPIO_CLK_BIAS_CTL_SHIFT      8 /* always set to 0x5 */
-#define _DPIO_REFSFR_B                 0x8034
-#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B)
+#define _VLV_PLL_DW5_CH1               0x8034
+#define VLV_PLL_DW5(ch) _PIPE(ch, _VLV_PLL_DW5_CH0, _VLV_PLL_DW5_CH1)
 
-#define _DPIO_CORE_CLK_A               0x801c
-#define _DPIO_CORE_CLK_B               0x803c
-#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
+#define _VLV_PLL_DW7_CH0               0x801c
+#define _VLV_PLL_DW7_CH1               0x803c
+#define VLV_PLL_DW7(ch) _PIPE(ch, _VLV_PLL_DW7_CH0, _VLV_PLL_DW7_CH1)
 
-#define _DPIO_IREF_CTL_A               0x8040
-#define _DPIO_IREF_CTL_B               0x8060
-#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
+#define _VLV_PLL_DW8_CH0               0x8040
+#define _VLV_PLL_DW8_CH1               0x8060
+#define VLV_PLL_DW8(ch) _PIPE(ch, _VLV_PLL_DW8_CH0, _VLV_PLL_DW8_CH1)
 
-#define DPIO_IREF_BCAST                        0xc044
-#define _DPIO_IREF_A                   0x8044
-#define _DPIO_IREF_B                   0x8064
-#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
+#define VLV_PLL_DW9_BCAST              0xc044
+#define _VLV_PLL_DW9_CH0               0x8044
+#define _VLV_PLL_DW9_CH1               0x8064
+#define VLV_PLL_DW9(ch) _PIPE(ch, _VLV_PLL_DW9_CH0, _VLV_PLL_DW9_CH1)
 
-#define _DPIO_PLL_CML_A                        0x804c
-#define _DPIO_PLL_CML_B                        0x806c
-#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
+#define _VLV_PLL_DW10_CH0              0x8048
+#define _VLV_PLL_DW10_CH1              0x8068
+#define VLV_PLL_DW10(ch) _PIPE(ch, _VLV_PLL_DW10_CH0, _VLV_PLL_DW10_CH1)
 
-#define _DPIO_LPF_COEFF_A              0x8048
-#define _DPIO_LPF_COEFF_B              0x8068
-#define DPIO_LPF_COEFF(pipe) _PIPE(pipe, _DPIO_LPF_COEFF_A, _DPIO_LPF_COEFF_B)
+#define _VLV_PLL_DW11_CH0              0x804c
+#define _VLV_PLL_DW11_CH1              0x806c
+#define VLV_PLL_DW11(ch) _PIPE(ch, _VLV_PLL_DW11_CH0, _VLV_PLL_DW11_CH1)
 
-#define DPIO_CALIBRATION               0x80ac
+/* Spec for ref block start counts at DW10 */
+#define VLV_REF_DW13                   0x80ac
 
-#define DPIO_FASTCLK_DISABLE           0x8100
+#define VLV_CMN_DW0                    0x8100
 
 /*
  * Per DDI channel DPIO regs
  */
 
-#define _DPIO_PCS_TX_0                 0x8200
-#define _DPIO_PCS_TX_1                 0x8400
+#define _VLV_PCS_DW0_CH0               0x8200
+#define _VLV_PCS_DW0_CH1               0x8400
 #define   DPIO_PCS_TX_LANE2_RESET      (1<<16)
 #define   DPIO_PCS_TX_LANE1_RESET      (1<<7)
-#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
+#define VLV_PCS_DW0(ch) _PORT(ch, _VLV_PCS_DW0_CH0, _VLV_PCS_DW0_CH1)
 
-#define _DPIO_PCS_CLK_0                        0x8204
-#define _DPIO_PCS_CLK_1                        0x8404
+#define _VLV_PCS_DW1_CH0               0x8204
+#define _VLV_PCS_DW1_CH1               0x8404
 #define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN        (1<<22)
 #define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
 #define   DPIO_PCS_CLK_DATAWIDTH_SHIFT (6)
 #define   DPIO_PCS_CLK_SOFT_RESET      (1<<5)
-#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
-
-#define _DPIO_PCS_CTL_OVR1_A           0x8224
-#define _DPIO_PCS_CTL_OVR1_B           0x8424
-#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \
-                                      _DPIO_PCS_CTL_OVR1_B)
-
-#define _DPIO_PCS_STAGGER0_A           0x822c
-#define _DPIO_PCS_STAGGER0_B           0x842c
-#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \
-                                     _DPIO_PCS_STAGGER0_B)
-
-#define _DPIO_PCS_STAGGER1_A           0x8230
-#define _DPIO_PCS_STAGGER1_B           0x8430
-#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \
-                                     _DPIO_PCS_STAGGER1_B)
-
-#define _DPIO_PCS_CLOCKBUF0_A          0x8238
-#define _DPIO_PCS_CLOCKBUF0_B          0x8438
-#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \
-                                      _DPIO_PCS_CLOCKBUF0_B)
-
-#define _DPIO_PCS_CLOCKBUF8_A          0x825c
-#define _DPIO_PCS_CLOCKBUF8_B          0x845c
-#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \
-                                      _DPIO_PCS_CLOCKBUF8_B)
-
-#define _DPIO_TX_SWING_CTL2_A          0x8288
-#define _DPIO_TX_SWING_CTL2_B          0x8488
-#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \
-                                      _DPIO_TX_SWING_CTL2_B)
-
-#define _DPIO_TX_SWING_CTL3_A          0x828c
-#define _DPIO_TX_SWING_CTL3_B          0x848c
-#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \
-                                      _DPIO_TX_SWING_CTL3_B)
-
-#define _DPIO_TX_SWING_CTL4_A          0x8290
-#define _DPIO_TX_SWING_CTL4_B          0x8490
-#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \
-                                      _DPIO_TX_SWING_CTL4_B)
-
-#define _DPIO_TX_OCALINIT_0            0x8294
-#define _DPIO_TX_OCALINIT_1            0x8494
+#define VLV_PCS_DW1(ch) _PORT(ch, _VLV_PCS_DW1_CH0, _VLV_PCS_DW1_CH1)
+
+#define _VLV_PCS_DW8_CH0               0x8220
+#define _VLV_PCS_DW8_CH1               0x8420
+#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1)
+
+#define _VLV_PCS01_DW8_CH0             0x0220
+#define _VLV_PCS23_DW8_CH0             0x0420
+#define _VLV_PCS01_DW8_CH1             0x2620
+#define _VLV_PCS23_DW8_CH1             0x2820
+#define VLV_PCS01_DW8(port) _PORT(port, _VLV_PCS01_DW8_CH0, _VLV_PCS01_DW8_CH1)
+#define VLV_PCS23_DW8(port) _PORT(port, _VLV_PCS23_DW8_CH0, _VLV_PCS23_DW8_CH1)
+
+#define _VLV_PCS_DW9_CH0               0x8224
+#define _VLV_PCS_DW9_CH1               0x8424
+#define        VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1)
+
+#define _VLV_PCS_DW11_CH0              0x822c
+#define _VLV_PCS_DW11_CH1              0x842c
+#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1)
+
+#define _VLV_PCS_DW12_CH0              0x8230
+#define _VLV_PCS_DW12_CH1              0x8430
+#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1)
+
+#define _VLV_PCS_DW14_CH0              0x8238
+#define _VLV_PCS_DW14_CH1              0x8438
+#define        VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1)
+
+#define _VLV_PCS_DW23_CH0              0x825c
+#define _VLV_PCS_DW23_CH1              0x845c
+#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1)
+
+#define _VLV_TX_DW2_CH0                        0x8288
+#define _VLV_TX_DW2_CH1                        0x8488
+#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
+
+#define _VLV_TX_DW3_CH0                        0x828c
+#define _VLV_TX_DW3_CH1                        0x848c
+#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1)
+
+#define _VLV_TX_DW4_CH0                        0x8290
+#define _VLV_TX_DW4_CH1                        0x8490
+#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1)
+
+#define _VLV_TX3_DW4_CH0               0x690
+#define _VLV_TX3_DW4_CH1               0x2a90
+#define VLV_TX3_DW4(ch) _PORT(ch, _VLV_TX3_DW4_CH0, _VLV_TX3_DW4_CH1)
+
+#define _VLV_TX_DW5_CH0                        0x8294
+#define _VLV_TX_DW5_CH1                        0x8494
 #define   DPIO_TX_OCALINIT_EN          (1<<31)
-#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \
-                                    _DPIO_TX_OCALINIT_1)
-
-#define _DPIO_TX_CTL_0                 0x82ac
-#define _DPIO_TX_CTL_1                 0x84ac
-#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
-
-#define _DPIO_TX_LANE_0                        0x82b8
-#define _DPIO_TX_LANE_1                        0x84b8
-#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
-
-#define _DPIO_DATA_CHANNEL1            0x8220
-#define _DPIO_DATA_CHANNEL2            0x8420
-#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
-
-#define _DPIO_PORT0_PCS0               0x0220
-#define _DPIO_PORT0_PCS1               0x0420
-#define _DPIO_PORT1_PCS2               0x2620
-#define _DPIO_PORT1_PCS3               0x2820
-#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2)
-#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3)
-#define DPIO_DATA_CHANNEL1              0x8220
-#define DPIO_DATA_CHANNEL2              0x8420
+#define VLV_TX_DW5(ch) _PORT(ch, _VLV_TX_DW5_CH0, _VLV_TX_DW5_CH1)
+
+#define _VLV_TX_DW11_CH0               0x82ac
+#define _VLV_TX_DW11_CH1               0x84ac
+#define VLV_TX_DW11(ch) _PORT(ch, _VLV_TX_DW11_CH0, _VLV_TX_DW11_CH1)
+
+#define _VLV_TX_DW14_CH0               0x82b8
+#define _VLV_TX_DW14_CH1               0x84b8
+#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1)
 
 /*
  * Fence registers
 #define HWSTAM         0x02098
 #define DMA_FADD_I8XX  0x020d0
 #define RING_BBSTATE(base)     ((base)+0x110)
+#define RING_BBADDR(base)      ((base)+0x140)
+#define RING_BBADDR_UDW(base)  ((base)+0x168) /* gen8+ */
 
 #define ERROR_GEN6     0x040a0
 #define GEN7_ERR_INT   0x44040
 #define   CM0_COLOR_EVICT_DISABLE (1<<3)
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
-#define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
 #define GFX_FLSH_CNTL_GEN6     0x101008
 #define   GFX_FLSH_CNTL_EN     (1<<0)
 
 #define GEN7_FF_THREAD_MODE            0x20a0
 #define   GEN7_FF_SCHED_MASK           0x0077070
+#define   GEN8_FF_DS_REF_CNT_FFME      (1 << 19)
 #define   GEN7_FF_TS_SCHED_HS1         (0x5<<16)
 #define   GEN7_FF_TS_SCHED_HS0         (0x3<<16)
 #define   GEN7_FF_TS_SCHED_LOAD_BALANCE        (0x1<<16)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
 #define   FBC_CTL_C3_IDLE      (1<<13)
 #define   FBC_CTL_STRIDE_SHIFT (5)
-#define   FBC_CTL_FENCENO      (1<<0)
+#define   FBC_CTL_FENCENO_SHIFT        (0)
 #define FBC_COMMAND            0x0320c
 #define   FBC_CMD_COMPRESS     (1<<0)
 #define FBC_STATUS             0x03210
 #define   FBC_STAT_COMPRESSING (1<<31)
 #define   FBC_STAT_COMPRESSED  (1<<30)
 #define   FBC_STAT_MODIFIED    (1<<29)
-#define   FBC_STAT_CURRENT_LINE        (1<<0)
+#define   FBC_STAT_CURRENT_LINE_SHIFT  (0)
 #define FBC_CONTROL2           0x03214
 #define   FBC_CTL_FENCE_DBL    (0<<4)
 #define   FBC_CTL_IDLE_IMM     (0<<2)
 #define   CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
 #define   CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
+#define   DP_AUX_CHANNEL_D_INT_STATUS_G4X      (1 << 6)
+#define   DP_AUX_CHANNEL_C_INT_STATUS_G4X      (1 << 5)
+#define   DP_AUX_CHANNEL_B_INT_STATUS_G4X      (1 << 4)
+#define   DP_AUX_CHANNEL_MASK_INT_STATUS_G4X   (1 << 4)
 /* SDVO is different across gen3/4 */
 #define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
 #define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
 /* the unit of memory self-refresh latency time is 0.5us */
 #define  ILK_SRLT_MASK         0x3f
 
-/* define the fifo size on Ironlake */
-#define ILK_DISPLAY_FIFO       128
-#define ILK_DISPLAY_MAXWM      64
-#define ILK_DISPLAY_DFTWM      8
-#define ILK_CURSOR_FIFO                32
-#define ILK_CURSOR_MAXWM       16
-#define ILK_CURSOR_DFTWM       8
-
-#define ILK_DISPLAY_SR_FIFO    512
-#define ILK_DISPLAY_MAX_SRWM   0x1ff
-#define ILK_DISPLAY_DFT_SRWM   0x3f
-#define ILK_CURSOR_SR_FIFO     64
-#define ILK_CURSOR_MAX_SRWM    0x3f
-#define ILK_CURSOR_DFT_SRWM    8
-
-#define ILK_FIFO_LINE_SIZE     64
-
-/* define the WM info on Sandybridge */
-#define SNB_DISPLAY_FIFO       128
-#define SNB_DISPLAY_MAXWM      0x7f    /* bit 16:22 */
-#define SNB_DISPLAY_DFTWM      8
-#define SNB_CURSOR_FIFO                32
-#define SNB_CURSOR_MAXWM       0x1f    /* bit 4:0 */
-#define SNB_CURSOR_DFTWM       8
-
-#define SNB_DISPLAY_SR_FIFO    512
-#define SNB_DISPLAY_MAX_SRWM   0x1ff   /* bit 16:8 */
-#define SNB_DISPLAY_DFT_SRWM   0x3f
-#define SNB_CURSOR_SR_FIFO     64
-#define SNB_CURSOR_MAX_SRWM    0x3f    /* bit 5:0 */
-#define SNB_CURSOR_DFT_SRWM    8
-
-#define SNB_FBC_MAX_SRWM       0xf     /* bit 23:20 */
-
-#define SNB_FIFO_LINE_SIZE     64
-
 
 /* the address where we get all kinds of latency value */
 #define SSKPD                  0x5d10
 
 #define _SPACNTR               (VLV_DISPLAY_BASE + 0x72180)
 #define   SP_ENABLE                    (1<<31)
-#define   SP_GEAMMA_ENABLE             (1<<30)
+#define   SP_GAMMA_ENABLE              (1<<30)
 #define   SP_PIXFORMAT_MASK            (0xf<<26)
 #define   SP_FORMAT_YUV422             (0<<26)
 #define   SP_FORMAT_BGR565             (5<<26)
 #define DISP_ARB_CTL   0x45000
 #define  DISP_TILE_SURFACE_SWIZZLING   (1<<13)
 #define  DISP_FBC_WM_DIS               (1<<15)
+#define DISP_ARB_CTL2  0x45004
+#define  DISP_DATA_PARTITION_5_6       (1<<6)
 #define GEN7_MSG_CTL   0x45010
 #define  WAIT_FOR_PCH_RESET_ACK                (1<<1)
 #define  WAIT_FOR_PCH_FLR_ACK          (1<<0)
 #define GEN7_L3SQCREG4                         0xb034
 #define  L3SQ_URB_READ_CAM_MATCH_DISABLE       (1<<27)
 
+/* GEN8 chicken */
+#define HDC_CHICKEN0                           0x7300
+#define  HDC_FORCE_NON_COHERENT                        (1<<4)
+
 /* WaCatErrorRejectionIssue */
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG         0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB      (1<<11)
 #define  FORCEWAKE_ACK                         0x130090
 #define  VLV_GTLC_WAKE_CTRL                    0x130090
 #define  VLV_GTLC_PW_STATUS                    0x130094
+#define VLV_GTLC_PW_RENDER_STATUS_MASK         0x80
+#define VLV_GTLC_PW_MEDIA_STATUS_MASK          0x20
 #define  FORCEWAKE_MT                          0xa188 /* multi-threaded */
 #define   FORCEWAKE_KERNEL                     0x1
 #define   FORCEWAKE_USER                       0x2
 #define    FORCEWAKE_MT_ENABLE                 (1<<5)
 
 #define  GTFIFODBG                             0x120000
-#define    GT_FIFO_CPU_ERROR_MASK              7
+#define    GT_FIFO_SBDROPERR                   (1<<6)
+#define    GT_FIFO_BLOBDROPERR                 (1<<5)
+#define    GT_FIFO_SB_READ_ABORTERR            (1<<4)
+#define    GT_FIFO_DROPERR                     (1<<3)
 #define    GT_FIFO_OVFERR                      (1<<2)
 #define    GT_FIFO_IAWRERR                     (1<<1)
 #define    GT_FIFO_IARDERR                     (1<<0)
 
-#define  GT_FIFO_FREE_ENTRIES                  0x120008
+#define  GTFIFOCTL                             0x120008
+#define    GT_FIFO_FREE_ENTRIES_MASK           0x7f
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
 #define  HSW_IDICR                             0x9008
 #define   GEN6_RC_CTL_RC6_ENABLE               (1<<18)
 #define   GEN6_RC_CTL_RC1e_ENABLE              (1<<20)
 #define   GEN6_RC_CTL_RC7_ENABLE               (1<<22)
+#define   VLV_RC_CTL_CTX_RST_PARALLEL          (1<<24)
 #define   GEN7_RC_CTL_TO_MODE                  (1<<28)
 #define   GEN6_RC_CTL_EI_MODE(x)               ((x)<<27)
 #define   GEN6_RC_CTL_HW_ENABLE                        (1<<31)
index 98790c7cccb1ab0902662e4cc541de9966f2058c..8150fdc08d497122c49959b9bbfaf0090259c7df 100644 (file)
@@ -192,7 +192,6 @@ static void i915_restore_vga(struct drm_device *dev)
 static void i915_save_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long flags;
 
        /* Display arbitration control */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -203,46 +202,27 @@ static void i915_save_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_save_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
        /* LVDS state */
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
-               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
                if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
 
-               dev_priv->regfile.saveBLC_PWM_CTL =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
                dev_priv->regfile.saveBLC_HIST_CTL =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL_B =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_B));
                dev_priv->regfile.saveBLC_HIST_CTL_B =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_B));
-               dev_priv->regfile.saveBLC_PWM_CTL2_B =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_B));
        } else {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
                dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
-               if (INTEL_INFO(dev)->gen >= 4)
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
                if (IS_MOBILE(dev) && !IS_I830(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(LVDS);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
                dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
@@ -257,7 +237,7 @@ static void i915_save_display(struct drm_device *dev)
        }
 
        /* Only regfile.save FBC state on the platform that supports FBC */
-       if (I915_HAS_FBC(dev)) {
+       if (HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
                } else if (IS_GM45(dev)) {
@@ -278,7 +258,6 @@ static void i915_restore_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 mask = 0xffffffff;
-       unsigned long flags;
 
        /* Display arbitration */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -287,12 +266,6 @@ static void i915_restore_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_restore_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       /* LVDS state */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-               I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                mask = ~LVDS_PORT_EN;
 
@@ -305,13 +278,6 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
 
        if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
-               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
-                * otherwise we get blank eDP screen after S3 on some machines
-                */
-               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
-               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
                I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
                I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
@@ -319,21 +285,12 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(RSTDBYCTL,
                           dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
        } else if (IS_VALLEYVIEW(dev)) {
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
        } else {
                I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
-               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
                I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
@@ -341,11 +298,9 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        /* only restore FBC info on the platform that supports FBC*/
        intel_disable_fbc(dev);
-       if (I915_HAS_FBC(dev)) {
+       if (HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
                } else if (IS_GM45(dev)) {
index cef38fd320a7c5c53c687ca5b67b0d1d3192d615..33bcae314bf86ea5f7a2deafb80625d0382634af 100644 (file)
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u64 raw_time; /* 32b value may overflow during fixed point math */
        u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+       u32 ret;
 
        if (!intel_enable_rc6(dev))
                return 0;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* On VLV, residency time is in CZ units rather than 1.28us */
        if (IS_VALLEYVIEW(dev)) {
                u32 clkctl2;
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
                        CLK_CTL2_CZCOUNT_30NS_SHIFT;
                if (!clkctl2) {
                        WARN(!clkctl2, "bogus CZ count value");
-                       return 0;
+                       ret = 0;
+                       goto out;
                }
                units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
                if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        }
 
        raw_time = I915_READ(reg) * units;
-       return DIV_ROUND_UP_ULL(raw_time, div);
+       ret = DIV_ROUND_UP_ULL(raw_time, div);
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static ssize_t
@@ -183,13 +191,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        int slice = (int)(uintptr_t)attr->private;
        int ret;
 
+       if (!HAS_HW_CONTEXTS(drm_dev))
+               return -ENXIO;
+
        ret = l3_access_valid(drm_dev, offset);
        if (ret)
                return ret;
 
-       if (dev_priv->hw_contexts_disabled)
-               return -ENXIO;
-
        ret = i915_mutex_lock_interruptible(drm_dev);
        if (ret)
                return ret;
@@ -259,7 +267,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
        if (IS_VALLEYVIEW(dev_priv->dev)) {
                u32 freq;
                freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-               ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
+               ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
        } else {
                ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
        }
@@ -276,8 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n",
-                       vlv_gpu_freq(dev_priv->mem_freq,
-                                    dev_priv->rps.rpe_delay));
+                       vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -291,7 +298,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -318,7 +325,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev_priv->dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -342,15 +349,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
                DRM_DEBUG("User requested overclocking to %d\n",
                          val * GT_FREQUENCY_MULTIPLIER);
 
+       dev_priv->rps.max_delay = val;
+
        if (dev_priv->rps.cur_delay > val) {
-               if (IS_VALLEYVIEW(dev_priv->dev))
-                       valleyview_set_rps(dev_priv->dev, val);
+               if (IS_VALLEYVIEW(dev))
+                       valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.max_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -367,7 +374,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -394,7 +401,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -411,15 +418,15 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
                return -EINVAL;
        }
 
+       dev_priv->rps.min_delay = val;
+
        if (dev_priv->rps.cur_delay < val) {
                if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.min_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -449,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        if (attr == &dev_attr_gt_RP0_freq_mhz) {
index 967da4772c449a2be05d16bce648fff9bd19a63e..caa18e855815eaf04a39ecb6eedcc572cf4d6290 100644 (file)
@@ -270,6 +270,18 @@ void i915_save_display_reg(struct drm_device *dev)
        }
        /* FIXME: regfile.save TV & SDVO state */
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
+               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
+       } else {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+               if (INTEL_INFO(dev)->gen >= 4)
+                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+       }
+
        return;
 }
 
@@ -280,6 +292,21 @@ void i915_restore_display_reg(struct drm_device *dev)
        int dpll_b_reg, fpb0_reg, fpb1_reg;
        int i;
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
+               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
+                * otherwise we get blank eDP screen after S3 on some machines
+                */
+               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
+       } else {
+               if (INTEL_INFO(dev)->gen >= 4)
+                       I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
+       }
+
        /* Display port ratios (must be done before clock is set) */
        if (SUPPORTS_INTEGRATED_DP(dev)) {
                I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
index e4fba39631a5ae2cd5901f85c73738406ef7cdc9..f22041973f3a0a426e29424cb60ba68e042c3ed8 100644 (file)
@@ -281,6 +281,34 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
        }
 }
 
+static void
+parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+{
+       const struct bdb_lfp_backlight_data *backlight_data;
+       const struct bdb_lfp_backlight_data_entry *entry;
+
+       backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+       if (!backlight_data)
+               return;
+
+       if (backlight_data->entry_size != sizeof(backlight_data->data[0])) {
+               DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n",
+                             backlight_data->entry_size);
+               return;
+       }
+
+       entry = &backlight_data->data[panel_type];
+
+       dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
+       dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+       DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
+                     "active %s, min brightness %u, level %u\n",
+                     dev_priv->vbt.backlight.pwm_freq_hz,
+                     dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
+                     entry->min_brightness,
+                     backlight_data->level[panel_type]);
+}
+
 /* Try to find sdvo panel data */
 static void
 parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
@@ -327,12 +355,12 @@ static int intel_bios_ssc_frequency(struct drm_device *dev,
 {
        switch (INTEL_INFO(dev)->gen) {
        case 2:
-               return alternate ? 66 : 48;
+               return alternate ? 66667 : 48000;
        case 3:
        case 4:
-               return alternate ? 100 : 96;
+               return alternate ? 100000 : 96000;
        default:
-               return alternate ? 100 : 120;
+               return alternate ? 100000 : 120000;
        }
 }
 
@@ -796,7 +824,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
         */
        dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
                        !HAS_PCH_SPLIT(dev));
-       DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
+       DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
 
        for (port = PORT_A; port < I915_MAX_PORTS; port++) {
                struct ddi_vbt_port_info *info =
@@ -894,6 +922,7 @@ intel_parse_bios(struct drm_device *dev)
        parse_general_features(dev_priv, bdb);
        parse_general_definitions(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
+       parse_lfp_backlight(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
        parse_sdvo_device_mapping(dev_priv, bdb);
        parse_device_mapping(dev_priv, bdb);
index f580a2b0ddd30f5d4338c7ab61414b6fe8bc62fc..282de5e9f39dee6566bb6d220f378864df86e8b9 100644 (file)
@@ -39,7 +39,7 @@ struct vbt_header {
        u8 reserved0;
        u32 bdb_offset;                 /**< from beginning of VBT */
        u32 aim_offset[4];              /**< from beginning of VBT */
-} __attribute__((packed));
+} __packed;
 
 struct bdb_header {
        u8 signature[16];               /**< Always 'BIOS_DATA_BLOCK' */
@@ -65,7 +65,7 @@ struct vbios_data {
        u8 rsvd4; /* popup memory size */
        u8 resize_pci_bios;
        u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
+} __packed;
 
 /*
  * There are several types of BIOS data blocks (BDBs), each block has
@@ -142,7 +142,7 @@ struct bdb_general_features {
        u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
        u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
        u8 rsvd11:3; /* finish byte */
-} __attribute__((packed));
+} __packed;
 
 /* pre-915 */
 #define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
@@ -225,7 +225,7 @@ struct old_child_dev_config {
        u8  dvo2_wiring;
        u16 extended_type;
        u8  dvo_function;
-} __attribute__((packed));
+} __packed;
 
 /* This one contains field offsets that are known to be common for all BDB
  * versions. Notice that the meaning of the contents contents may still change,
@@ -238,7 +238,7 @@ struct common_child_dev_config {
        u8 not_common2[2];
        u8 ddc_pin;
        u16 edid_ptr;
-} __attribute__((packed));
+} __packed;
 
 /* This field changes depending on the BDB version, so the most reliable way to
  * read it is by checking the BDB version and reading the raw pointer. */
@@ -279,7 +279,7 @@ struct bdb_general_definitions {
         *           sizeof(child_device_config);
         */
        union child_device_config devices[0];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_options {
        u8 panel_type;
@@ -293,7 +293,7 @@ struct bdb_lvds_options {
        u8 lvds_edid:1;
        u8 rsvd2:1;
        u8 rsvd4;
-} __attribute__((packed));
+} __packed;
 
 /* LFP pointer table contains entries to the struct below */
 struct bdb_lvds_lfp_data_ptr {
@@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr {
        u8 dvo_table_size;
        u16 panel_pnp_id_offset;
        u8 pnp_table_size;
-} __attribute__((packed));
+} __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));
+} __packed;
 
 /* LFP data has 3 blocks per entry */
 struct lvds_fp_timing {
@@ -325,7 +325,7 @@ struct lvds_fp_timing {
        u32 pfit_reg;
        u32 pfit_reg_val;
        u16 terminator;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_dvo_timing {
        u16 clock;              /**< In 10khz */
@@ -353,7 +353,7 @@ struct lvds_dvo_timing {
        u8 vsync_positive:1;
        u8 hsync_positive:1;
        u8 rsvd2:1;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_pnp_id {
        u16 mfg_name;
@@ -361,17 +361,33 @@ struct lvds_pnp_id {
        u32 serial;
        u8 mfg_week;
        u8 mfg_year;
-} __attribute__((packed));
+} __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));
+} __packed;
 
 struct bdb_lvds_lfp_data {
        struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
+} __packed;
+
+struct bdb_lfp_backlight_data_entry {
+       u8 type:2;
+       u8 active_low_pwm:1;
+       u8 obsolete1:5;
+       u16 pwm_freq_hz;
+       u8 min_brightness;
+       u8 obsolete2;
+       u8 obsolete3;
+} __packed;
+
+struct bdb_lfp_backlight_data {
+       u8 entry_size;
+       struct bdb_lfp_backlight_data_entry data[16];
+       u8 level[16];
+} __packed;
 
 struct aimdb_header {
        char signature[16];
@@ -379,12 +395,12 @@ struct aimdb_header {
        u16 aimdb_version;
        u16 aimdb_header_size;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_block {
        u8 aimdb_id;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_panel_data {
        u16 fp_timing_offset;
@@ -395,12 +411,12 @@ struct vch_panel_data {
        u8 text_fitting_size;
        u16 graphics_fitting_offset;
        u8 graphics_fitting_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_bdb_22 {
        struct aimdb_block aimdb_block;
        struct vch_panel_data panels[16];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_sdvo_lvds_options {
        u8 panel_backlight;
@@ -416,7 +432,7 @@ struct bdb_sdvo_lvds_options {
        u8 panel_misc_bits_2;
        u8 panel_misc_bits_3;
        u8 panel_misc_bits_4;
-} __attribute__((packed));
+} __packed;
 
 
 #define BDB_DRIVER_FEATURE_NO_LVDS             0
@@ -462,7 +478,7 @@ struct bdb_driver_features {
 
        u8 hdmi_termination;
        u8 custom_vbt_version;
-} __attribute__((packed));
+} __packed;
 
 #define EDP_18BPP      0
 #define EDP_24BPP      1
@@ -487,14 +503,14 @@ struct edp_power_seq {
        u16 t9;
        u16 t10;
        u16 t11_t12;
-} __attribute__ ((packed));
+} __packed;
 
 struct edp_link_params {
        u8 rate:4;
        u8 lanes:4;
        u8 preemphasis:4;
        u8 vswing:4;
-} __attribute__ ((packed));
+} __packed;
 
 struct bdb_edp {
        struct edp_power_seq power_seqs[16];
@@ -505,7 +521,7 @@ struct bdb_edp {
        /* ith bit indicates enabled/disabled for (i+1)th panel */
        u16 edp_s3d_feature;
        u16 edp_t3_optimization;
-} __attribute__ ((packed));
+} __packed;
 
 void intel_setup_bios(struct drm_device *dev);
 int intel_parse_bios(struct drm_device *dev);
@@ -733,6 +749,6 @@ struct bdb_mipi {
        u32 hl_switch_cnt;
        u32 lp_byte_clk;
        u32 clk_lane_switch_cnt;
-} __attribute__((packed));
+} __packed;
 
 #endif /* _I830_BIOS_H_ */
index b5b1b9b23adf1b24559e7ffdce658ba37e6bbbab..e2e39e65f10954b8076b3ed01b565f0cb173bb0d 100644 (file)
@@ -222,8 +222,9 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_crt_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_crt_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct drm_device *dev = connector->dev;
 
index 526c8ded16b03bc334846609a47e2d0bfc07c58c..e06b9e017d6ba918b87557de301df47076852434 100644 (file)
@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
 };
 
 static const u32 bdw_ddi_translations_edp[] = {
-       0x00FFFFFF, 0x00000012,         /* DP parameters */
+       0x00FFFFFF, 0x00000012,         /* eDP parameters */
        0x00EBAFFF, 0x00020011,
        0x00C71FFF, 0x0006000F,
        0x00FFFFFF, 0x00020011,
@@ -696,25 +696,25 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
        *n2_out = best.n2;
        *p_out = best.p;
        *r2_out = best.r2;
-
-       DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
-                     clock, *p_out, *n2_out, *r2_out);
 }
 
-bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
+/*
+ * Tries to find a PLL for the CRTC. If it finds, it increases the refcount and
+ * stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to
+ * steal the selected PLL. You need to call intel_ddi_pll_enable to actually
+ * enable the PLL.
+ */
+bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_crtc *crtc = &intel_crtc->base;
        struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
        int type = intel_encoder->type;
        enum pipe pipe = intel_crtc->pipe;
-       uint32_t reg, val;
        int clock = intel_crtc->config.port_clock;
 
-       /* TODO: reuse PLLs when possible (compare values) */
-
        intel_ddi_put_crtc_pll(crtc);
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
@@ -736,66 +736,145 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
                        return false;
                }
 
-               /* We don't need to turn any PLL on because we'll use LCPLL. */
-               return true;
-
        } else if (type == INTEL_OUTPUT_HDMI) {
+               uint32_t reg, val;
                unsigned p, n2, r2;
 
-               if (plls->wrpll1_refcount == 0) {
+               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+                     WRPLL_DIVIDER_POST(p);
+
+               if (val == I915_READ(WRPLL_CTL1)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL1;
+               } else if (val == I915_READ(WRPLL_CTL2)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL2;
+               } else if (plls->wrpll1_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll1_refcount++;
                        reg = WRPLL_CTL1;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
                } else if (plls->wrpll2_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll2_refcount++;
                        reg = WRPLL_CTL2;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
                } else {
                        DRM_ERROR("No WRPLLs available!\n");
                        return false;
                }
 
-               WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
-                    "WRPLL already enabled\n");
+               DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+                             clock, p, n2, r2);
 
-               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
-                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
-                     WRPLL_DIVIDER_POST(p);
+               if (reg == WRPLL_CTL1) {
+                       plls->wrpll1_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+               } else {
+                       plls->wrpll2_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+               }
 
        } else if (type == INTEL_OUTPUT_ANALOG) {
                if (plls->spll_refcount == 0) {
                        DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
                                      pipe_name(pipe));
                        plls->spll_refcount++;
-                       reg = SPLL_CTL;
                        intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
                } else {
                        DRM_ERROR("SPLL already in use\n");
                        return false;
                }
 
-               WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
-                    "SPLL already enabled\n");
-
-               val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
-
        } else {
                WARN(1, "Invalid DDI encoder type %d\n", type);
                return false;
        }
 
-       I915_WRITE(reg, val);
-       udelay(20);
-
        return true;
 }
 
+/*
+ * To be called after intel_ddi_pll_select(). That one selects the PLL to be
+ * used, this one actually enables the PLL.
+ */
+void intel_ddi_pll_enable(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+       int clock = crtc->config.port_clock;
+       uint32_t reg, cur_val, new_val;
+       int refcount;
+       const char *pll_name;
+       uint32_t enable_bit = (1 << 31);
+       unsigned int p, n2, r2;
+
+       BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
+       BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
+
+       switch (crtc->ddi_pll_sel) {
+       case PORT_CLK_SEL_LCPLL_2700:
+       case PORT_CLK_SEL_LCPLL_1350:
+       case PORT_CLK_SEL_LCPLL_810:
+               /*
+                * LCPLL should always be enabled at this point of the mode set
+                * sequence, so nothing to do.
+                */
+               return;
+
+       case PORT_CLK_SEL_SPLL:
+               pll_name = "SPLL";
+               reg = SPLL_CTL;
+               refcount = plls->spll_refcount;
+               new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
+                         SPLL_PLL_SSC;
+               break;
+
+       case PORT_CLK_SEL_WRPLL1:
+       case PORT_CLK_SEL_WRPLL2:
+               if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
+                       pll_name = "WRPLL1";
+                       reg = WRPLL_CTL1;
+                       refcount = plls->wrpll1_refcount;
+               } else {
+                       pll_name = "WRPLL2";
+                       reg = WRPLL_CTL2;
+                       refcount = plls->wrpll2_refcount;
+               }
+
+               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+                         WRPLL_DIVIDER_REFERENCE(r2) |
+                         WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
+
+               break;
+
+       case PORT_CLK_SEL_NONE:
+               WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
+               return;
+       default:
+               WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
+               return;
+       }
+
+       cur_val = I915_READ(reg);
+
+       WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
+       if (refcount == 1) {
+               WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
+               I915_WRITE(reg, new_val);
+               POSTING_READ(reg);
+               udelay(20);
+       } else {
+               WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
+       }
+}
+
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -1057,12 +1136,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
        enum pipe pipe;
        struct intel_crtc *intel_crtc;
 
+       dev_priv->ddi_plls.spll_refcount = 0;
+       dev_priv->ddi_plls.wrpll1_refcount = 0;
+       dev_priv->ddi_plls.wrpll2_refcount = 0;
+
        for_each_pipe(pipe) {
                intel_crtc =
                        to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-               if (!intel_crtc->active)
+               if (!intel_crtc->active) {
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
                        continue;
+               }
 
                intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
                                                                 pipe);
@@ -1115,9 +1200,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               ironlake_edp_panel_vdd_on(intel_dp);
                ironlake_edp_panel_on(intel_dp);
-               ironlake_edp_panel_vdd_off(intel_dp, true);
        }
 
        WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
@@ -1160,7 +1243,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               ironlake_edp_panel_vdd_on(intel_dp);
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
                ironlake_edp_panel_off(intel_dp);
        }
index 54e82a80cf507fe90366ad1e0fb33f082073ca83..14b024becb9132be12b6b368a8051a65ef54405f 100644 (file)
@@ -90,8 +90,8 @@ intel_fdi_link_freq(struct drm_device *dev)
 
 static const intel_limit_t intel_limits_i8xx_dac = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -103,8 +103,8 @@ static const intel_limit_t intel_limits_i8xx_dac = {
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -116,8 +116,8 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m1 * clock->m2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m2 + 2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -748,10 +754,10 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
        return intel_crtc->config.cpu_transcoder;
 }
 
-static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
+static void g4x_wait_for_vblank(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 frame, frame_reg = PIPEFRAME(pipe);
+       u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe);
 
        frame = I915_READ(frame_reg);
 
@@ -772,8 +778,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipestat_reg = PIPESTAT(pipe);
 
-       if (INTEL_INFO(dev)->gen >= 5) {
-               ironlake_wait_for_vblank(dev, pipe);
+       if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+               g4x_wait_for_vblank(dev, pipe);
                return;
        }
 
@@ -1205,15 +1211,12 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        }
 }
 
-static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
 {
        u32 val;
        bool enabled;
 
-       if (HAS_PCH_LPT(dev_priv->dev)) {
-               DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n");
-               return;
-       }
+       WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
 
        val = I915_READ(PCH_DREF_CONTROL);
        enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
@@ -1358,9 +1361,27 @@ static void intel_init_dpio(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (!IS_VALLEYVIEW(dev))
+               return;
+
+       DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
+}
+
+static void intel_reset_dpio(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        if (!IS_VALLEYVIEW(dev))
                return;
 
+       /*
+        * Enable the CRI clock source so we can get at the display and the
+        * reference clock for VGA hotplug / manual detection.
+        */
+       I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+                  DPLL_REFA_CLK_ENABLE_VLV |
+                  DPLL_INTEGRATED_CRI_CLK_VLV);
+
        /*
         * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
         *  6.  De-assert cmn_reset/side_reset. Same as VLV X0.
@@ -1487,25 +1508,35 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        /* Make sure the pipe isn't still relying on us */
        assert_pipe_disabled(dev_priv, pipe);
 
-       /* Leave integrated clock source enabled */
+       /*
+        * Leave integrated clock source and reference clock enabled for pipe B.
+        * The latter is needed for VGA hotplug / manual detection.
+        */
        if (pipe == PIPE_B)
-               val = DPLL_INTEGRATED_CRI_CLK_VLV;
+               val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REFA_CLK_ENABLE_VLV;
        I915_WRITE(DPLL(pipe), val);
        POSTING_READ(DPLL(pipe));
 }
 
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+               struct intel_digital_port *dport)
 {
        u32 port_mask;
 
-       if (!port)
+       switch (dport->port) {
+       case PORT_B:
                port_mask = DPLL_PORTB_READY_MASK;
-       else
+               break;
+       case PORT_C:
                port_mask = DPLL_PORTC_READY_MASK;
+               break;
+       default:
+               BUG();
+       }
 
        if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
                WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
-                    'B' + port, I915_READ(DPLL(0)));
+                    port_name(dport->port), I915_READ(DPLL(0)));
 }
 
 /**
@@ -2233,7 +2264,12 @@ void intel_display_handle_reset(struct drm_device *dev)
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                mutex_lock(&crtc->mutex);
-               if (intel_crtc->active)
+               /*
+                * FIXME: Once we have proper support for primary planes (and
+                * disabling them without disabling the entire crtc) allow again
+                * a NULL crtc->fb.
+                */
+               if (intel_crtc->active && crtc->fb)
                        dev_priv->display.update_plane(crtc, crtc->fb,
                                                       crtc->x, crtc->y);
                mutex_unlock(&crtc->mutex);
@@ -2350,6 +2386,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                        I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0);
                        I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0);
                }
+               intel_crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay;
+               intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay;
        }
 
        ret = dev_priv->display.update_plane(crtc, fb, x, y);
@@ -3399,9 +3437,8 @@ void hsw_enable_ips(struct intel_crtc *crtc)
                mutex_unlock(&dev_priv->rps.hw_lock);
                /* Quoting Art Runyan: "its not safe to expect any particular
                 * value in IPS_CTL bit 31 after enabling IPS through the
-                * mailbox." Therefore we need to defer waiting on the state
-                * change.
-                * TODO: need to fix this for state checker
+                * mailbox." Moreover, the mailbox may return a bogus state,
+                * so we need to just enable it and continue on.
                 */
        } else {
                I915_WRITE(IPS_CTL, IPS_ENABLE);
@@ -3428,9 +3465,10 @@ void hsw_disable_ips(struct intel_crtc *crtc)
                mutex_lock(&dev_priv->rps.hw_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
                mutex_unlock(&dev_priv->rps.hw_lock);
-       } else
+       } else {
                I915_WRITE(IPS_CTL, 0);
-       POSTING_READ(IPS_CTL);
+               POSTING_READ(IPS_CTL);
+       }
 
        /* We need to wait for a vblank before we can disable the plane. */
        intel_wait_for_vblank(dev, crtc->pipe);
@@ -3465,7 +3503,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
        /* Workaround : Do not read or write the pipe palette/gamma data while
         * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
         */
-       if (intel_crtc->config.ips_enabled &&
+       if (IS_HASWELL(dev) && intel_crtc->config.ips_enabled &&
            ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
             GAMMA_MODE_MODE_SPLIT)) {
                hsw_disable_ips(intel_crtc);
@@ -3910,6 +3948,174 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
        I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+int valleyview_get_vco(struct drm_i915_private *dev_priv)
+{
+       int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
+
+       /* Obtain SKU information */
+       mutex_lock(&dev_priv->dpio_lock);
+       hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
+               CCK_FUSE_HPLL_FREQ_MASK;
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       return vco_freq[hpll_freq];
+}
+
+/* Adjust CDclk dividers to allow high res or save power if possible */
+static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val, cmd;
+
+       if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
+               cmd = 2;
+       else if (cdclk == 266)
+               cmd = 1;
+       else
+               cmd = 0;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
+       val &= ~DSPFREQGUAR_MASK;
+       val |= (cmd << DSPFREQGUAR_SHIFT);
+       vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
+       if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
+                     DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
+                    50)) {
+               DRM_ERROR("timed out waiting for CDclk change\n");
+       }
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       if (cdclk == 400) {
+               u32 divider, vco;
+
+               vco = valleyview_get_vco(dev_priv);
+               divider = ((vco << 1) / cdclk) - 1;
+
+               mutex_lock(&dev_priv->dpio_lock);
+               /* adjust cdclk divider */
+               val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+               val &= ~0xf;
+               val |= divider;
+               vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+               mutex_unlock(&dev_priv->dpio_lock);
+       }
+
+       mutex_lock(&dev_priv->dpio_lock);
+       /* adjust self-refresh exit latency value */
+       val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
+       val &= ~0x7f;
+
+       /*
+        * For high bandwidth configs, we set a higher latency in the bunit
+        * so that the core display fetch happens in time to avoid underruns.
+        */
+       if (cdclk == 400)
+               val |= 4500 / 250; /* 4.5 usec */
+       else
+               val |= 3000 / 250; /* 3.0 usec */
+       vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       /* Since we changed the CDclk, we need to update the GMBUSFREQ too */
+       intel_i2c_reset(dev);
+}
+
+static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
+{
+       int cur_cdclk, vco;
+       int divider;
+
+       vco = valleyview_get_vco(dev_priv);
+
+       mutex_lock(&dev_priv->dpio_lock);
+       divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       divider &= 0xf;
+
+       cur_cdclk = (vco << 1) / (divider + 1);
+
+       return cur_cdclk;
+}
+
+static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
+                                int max_pixclk)
+{
+       int cur_cdclk;
+
+       cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       /*
+        * Really only a few cases to deal with, as only 4 CDclks are supported:
+        *   200MHz
+        *   267MHz
+        *   320MHz
+        *   400MHz
+        * So we check to see whether we're above 90% of the lower bin and
+        * adjust if needed.
+        */
+       if (max_pixclk > 288000) {
+               return 400;
+       } else if (max_pixclk > 240000) {
+               return 320;
+       } else
+               return 266;
+       /* Looks like the 200MHz CDclk freq doesn't work on some configs */
+}
+
+static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv,
+                                unsigned modeset_pipes,
+                                struct intel_crtc_config *pipe_config)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = 0;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head) {
+               if (modeset_pipes & (1 << intel_crtc->pipe))
+                       max_pixclk = max(max_pixclk,
+                                        pipe_config->adjusted_mode.crtc_clock);
+               else if (intel_crtc->base.enabled)
+                       max_pixclk = max(max_pixclk,
+                                        intel_crtc->config.adjusted_mode.crtc_clock);
+       }
+
+       return max_pixclk;
+}
+
+static void valleyview_modeset_global_pipes(struct drm_device *dev,
+                                           unsigned *prepare_pipes,
+                                           unsigned modeset_pipes,
+                                           struct intel_crtc_config *pipe_config)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes,
+                                              pipe_config);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk)
+               return;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head)
+               if (intel_crtc->base.enabled)
+                       *prepare_pipes |= (1 << intel_crtc->pipe);
+}
+
+static void valleyview_modeset_global_resources(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+       int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
+
+       if (req_cdclk != cur_cdclk)
+               valleyview_set_cdclk(dev, req_cdclk);
+}
+
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -4570,9 +4776,8 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
                refclk = 100000;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-                             refclk / 1000);
+               refclk = dev_priv->vbt.lvds_ssc_freq;
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
        } else if (!IS_GEN2(dev)) {
                refclk = 96000;
        } else {
@@ -4634,24 +4839,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
         * PLLB opamp always calibrates to max value of 0x3f, force enable it
         * and set it to a reasonable value instead.
         */
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
        reg_val |= 0x00000030;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x8cffffff;
        reg_val = 0x8c000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x00ffffff;
        reg_val |= 0xb0000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 }
 
 static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
@@ -4720,15 +4925,15 @@ static void vlv_update_pll(struct intel_crtc *crtc)
                vlv_pllb_recal_opamp(dev_priv, pipe);
 
        /* Set up Tx target for periodic Rcomp update */
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
 
        /* Disable target IRef on PLL */
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
        reg_val &= 0x00ffffff;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
 
        /* Disable fast lock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610);
+       vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
 
        /* Set idtafcrecal before PLL is enabled */
        mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
@@ -4742,50 +4947,54 @@ static void vlv_update_pll(struct intel_crtc *crtc)
         * Note: don't use the DAC post divider as it seems unstable.
         */
        mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
-       vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
 
        mdiv |= DPIO_ENABLE_CALIBRATION;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
 
        /* Set HBR and RBR LPF coefficients */
        if (crtc->config.port_clock == 162000 ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
-               vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x009f0003);
        else
-               vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x00d0000f);
 
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
                /* Use SSC source */
                if (!pipe)
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
        } else { /* HDMI or VGA */
                /* Use bend source */
                if (!pipe)
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
        }
 
-       coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe));
+       coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
        coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))
                coreclk |= 0x01000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
-       vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
 
-       /* Enable DPIO clock input */
+       /*
+        * Enable DPIO clock input. We should never disable the reference
+        * clock for pipe B, since VGA hotplug / manual detection depends
+        * on it.
+        */
        dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
                DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
        /* We should never disable this, set it here for state tracking */
@@ -5230,6 +5439,9 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
+               return;
+
        tmp = I915_READ(PFIT_CONTROL);
        if (!(tmp & PFIT_ENABLE))
                return;
@@ -5261,7 +5473,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
        int refclk = 100000;
 
        mutex_lock(&dev_priv->dpio_lock);
-       mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe));
+       mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
        mutex_unlock(&dev_priv->dpio_lock);
 
        clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
@@ -5718,9 +5930,9 @@ static int ironlake_get_refclk(struct drm_crtc *crtc)
        }
 
        if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
                              dev_priv->vbt.lvds_ssc_freq);
-               return dev_priv->vbt.lvds_ssc_freq * 1000;
+               return dev_priv->vbt.lvds_ssc_freq;
        }
 
        return 120000;
@@ -5982,7 +6194,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        factor = 21;
        if (is_lvds) {
                if ((intel_panel_use_ssc(dev_priv) &&
-                    dev_priv->vbt.lvds_ssc_freq == 100) ||
+                    dev_priv->vbt.lvds_ssc_freq == 100000) ||
                    (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
                        factor = 25;
        } else if (intel_crtc->config.sdvo_tv_clock)
@@ -6323,7 +6535,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        val = I915_READ(DEIMR);
-       WARN((val & ~DE_PCH_EVENT_IVB) != val,
+       WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
             "Unexpected DEIMR bits enabled: 0x%x\n", val);
        val = I915_READ(SDEIMR);
        WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
@@ -6402,7 +6614,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6436,7 +6648,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -6447,6 +6659,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        struct drm_device *dev = dev_priv->dev;
        uint32_t val;
 
+       WARN_ON(!HAS_PC8(dev));
+
        if (dev_priv->pc8.enabled)
                return;
 
@@ -6463,6 +6677,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        lpt_disable_clkout_dp(dev);
        hsw_pc8_disable_interrupts(dev);
        hsw_disable_lcpll(dev_priv, true, true);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
@@ -6492,12 +6708,16 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
        if (dev_priv->pc8.disable_count != 1)
                return;
 
+       WARN_ON(!HAS_PC8(dev));
+
        cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
        if (!dev_priv->pc8.enabled)
                return;
 
        DRM_DEBUG_KMS("Disabling package C8+\n");
 
+       intel_runtime_pm_get(dev_priv);
+
        hsw_restore_lcpll(dev_priv);
        hsw_pc8_restore_interrupts(dev);
        lpt_init_pch_refclk(dev);
@@ -6704,8 +6924,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
        int plane = intel_crtc->plane;
        int ret;
 
-       if (!intel_ddi_pll_mode_set(crtc))
+       if (!intel_ddi_pll_select(intel_crtc))
                return -EINVAL;
+       intel_ddi_pll_enable(intel_crtc);
 
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
@@ -6796,8 +7017,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        if (intel_display_power_enabled(dev, pfit_domain))
                ironlake_get_pfit_config(crtc, pipe_config);
 
-       pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
-                                  (I915_READ(IPS_CTL) & IPS_ENABLE);
+       if (IS_HASWELL(dev))
+               pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+                       (I915_READ(IPS_CTL) & IPS_ENABLE);
 
        pipe_config->pixel_multiplier = 1;
 
@@ -7689,7 +7911,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
        u32 dpll = pipe_config->dpll_hw_state.dpll;
 
        if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
-               return dev_priv->vbt.lvds_ssc_freq * 1000;
+               return dev_priv->vbt.lvds_ssc_freq;
        else if (HAS_PCH_SPLIT(dev))
                return 120000;
        else if (!IS_GEN2(dev))
@@ -7752,12 +7974,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                else
                        i9xx_clock(refclk, &clock);
        } else {
-               bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
+               u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
+               bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
 
                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 (lvds & LVDS_CLKB_POWER_UP)
+                               clock.p2 = 7;
+                       else
+                               clock.p2 = 14;
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
@@ -9122,7 +9349,9 @@ intel_pipe_config_compare(struct drm_device *dev,
                PIPE_CONF_CHECK_I(pch_pfit.size);
        }
 
-       PIPE_CONF_CHECK_I(ips_enabled);
+       /* BDW+ don't expose a synchronous way to read the state */
+       if (IS_HASWELL(dev))
+               PIPE_CONF_CHECK_I(ips_enabled);
 
        PIPE_CONF_CHECK_I(double_wide);
 
@@ -9368,21 +9597,19 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_display_mode *saved_mode, *saved_hwmode;
+       struct drm_display_mode *saved_mode;
        struct intel_crtc_config *pipe_config = NULL;
        struct intel_crtc *intel_crtc;
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
        int ret = 0;
 
-       saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL);
+       saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
        if (!saved_mode)
                return -ENOMEM;
-       saved_hwmode = saved_mode + 1;
 
        intel_modeset_affected_pipes(crtc, &modeset_pipes,
                                     &prepare_pipes, &disable_pipes);
 
-       *saved_hwmode = crtc->hwmode;
        *saved_mode = crtc->mode;
 
        /* Hack: Because we don't (yet) support global modeset on multiple
@@ -9402,6 +9629,21 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                                       "[modeset]");
        }
 
+       /*
+        * See if the config requires any additional preparation, e.g.
+        * to adjust global state with pipes off.  We need to do this
+        * here so we can get the modeset_pipe updated config for the new
+        * mode set on this crtc.  For other crtcs we need to use the
+        * adjusted_mode bits in the crtc directly.
+        */
+       if (IS_VALLEYVIEW(dev)) {
+               valleyview_modeset_global_pipes(dev, &prepare_pipes,
+                                               modeset_pipes, pipe_config);
+
+               /* may have added more to prepare_pipes than we should */
+               prepare_pipes &= ~disable_pipes;
+       }
+
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
 
@@ -9418,6 +9660,14 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                /* mode_set/enable/disable functions rely on a correct pipe
                 * config. */
                to_intel_crtc(crtc)->config = *pipe_config;
+
+               /*
+                * Calculate and store various constants which
+                * are later needed by vblank and swap-completion
+                * timestamping. They are derived from true hwmode.
+                */
+               drm_calc_timestamping_constants(crtc,
+                                               &pipe_config->adjusted_mode);
        }
 
        /* Only after disabling all output pipelines that will be changed can we
@@ -9441,23 +9691,10 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
                dev_priv->display.crtc_enable(&intel_crtc->base);
 
-       if (modeset_pipes) {
-               /* Store real post-adjustment hardware mode. */
-               crtc->hwmode = pipe_config->adjusted_mode;
-
-               /* Calculate and store various constants which
-                * are later needed by vblank and swap-completion
-                * timestamping. They are derived from true hwmode.
-                */
-               drm_calc_timestamping_constants(crtc);
-       }
-
        /* FIXME: add subpixel order */
 done:
-       if (ret && crtc->enabled) {
-               crtc->hwmode = *saved_hwmode;
+       if (ret && crtc->enabled)
                crtc->mode = *saved_mode;
-       }
 
 out:
        kfree(pipe_config);
@@ -9694,17 +9931,21 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        /* Check for any encoders that needs to be disabled. */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
                            base.head) {
+               int num_connectors = 0;
                list_for_each_entry(connector,
                                    &dev->mode_config.connector_list,
                                    base.head) {
                        if (connector->new_encoder == encoder) {
                                WARN_ON(!connector->new_encoder->new_crtc);
-
-                               goto next_encoder;
+                               num_connectors++;
                        }
                }
-               encoder->new_crtc = NULL;
-next_encoder:
+
+               if (num_connectors == 0)
+                       encoder->new_crtc = NULL;
+               else if (num_connectors > 1)
+                       return -EINVAL;
+
                /* Only now check for crtc changes so we don't miss encoders
                 * that will be disabled. */
                if (&encoder->new_crtc->base != encoder->base.crtc) {
@@ -9775,6 +10016,16 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
                ret = intel_pipe_set_base(set->crtc,
                                          set->x, set->y, set->fb);
+               /*
+                * In the fastboot case this may be our only check of the
+                * state after boot.  It would be better to only do it on
+                * the first update, but we don't have a nice way of doing that
+                * (and really, set_config isn't used much for high freq page
+                * flipping, so increasing its cost here shouldn't be a big
+                * deal).
+                */
+               if (i915_fastboot && ret == 0)
+                       intel_modeset_check_state(set->crtc->dev);
        }
 
        if (ret) {
@@ -9835,7 +10086,7 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
                                struct intel_shared_dpll *pll)
 {
        /* PCH refclock must be enabled first */
-       assert_pch_refclk_enabled(dev_priv);
+       ibx_assert_pch_refclk_enabled(dev_priv);
 
        I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll);
 
@@ -9903,8 +10154,6 @@ static void intel_shared_dpll_init(struct drm_device *dev)
                dev_priv->num_shared_dpll = 0;
 
        BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
-       DRM_DEBUG_KMS("%i shared PLLs initialized\n",
-                     dev_priv->num_shared_dpll);
 }
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
@@ -9926,10 +10175,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                intel_crtc->lut_b[i] = i;
        }
 
-       /* Swap pipes & planes for FBC on pre-965 */
+       /*
+        * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
+        * is hooked to plane B. Hence we want plane A feeding pipe B.
+        */
        intel_crtc->pipe = pipe;
        intel_crtc->plane = pipe;
-       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
+       if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) {
                DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
                intel_crtc->plane = !pipe;
        }
@@ -10018,6 +10270,28 @@ static bool has_edp_a(struct drm_device *dev)
        return true;
 }
 
+const char *intel_output_name(int output)
+{
+       static const char *names[] = {
+               [INTEL_OUTPUT_UNUSED] = "Unused",
+               [INTEL_OUTPUT_ANALOG] = "Analog",
+               [INTEL_OUTPUT_DVO] = "DVO",
+               [INTEL_OUTPUT_SDVO] = "SDVO",
+               [INTEL_OUTPUT_LVDS] = "LVDS",
+               [INTEL_OUTPUT_TVOUT] = "TV",
+               [INTEL_OUTPUT_HDMI] = "HDMI",
+               [INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort",
+               [INTEL_OUTPUT_EDP] = "eDP",
+               [INTEL_OUTPUT_DSI] = "DSI",
+               [INTEL_OUTPUT_UNKNOWN] = "Unknown",
+       };
+
+       if (output < 0 || output >= ARRAY_SIZE(names) || !names[output])
+               return "Invalid";
+
+       return names[output];
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -10412,8 +10686,11 @@ static void intel_init_display(struct drm_device *dev)
                }
        } else if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
-       } else if (IS_VALLEYVIEW(dev))
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.modeset_global_resources =
+                       valleyview_modeset_global_resources;
                dev_priv->display.write_eld = ironlake_write_eld;
+       }
 
        /* Default just returns -ENODEV to indicate unsupported */
        dev_priv->display.queue_flip = intel_default_queue_flip;
@@ -10440,6 +10717,8 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.queue_flip = intel_gen7_queue_flip;
                break;
        }
+
+       intel_panel_init_backlight_funcs(dev);
 }
 
 /*
@@ -10476,17 +10755,6 @@ static void quirk_invert_brightness(struct drm_device *dev)
        DRM_INFO("applying inverted panel brightness quirk\n");
 }
 
-/*
- * Some machines (Dell XPS13) suffer broken backlight controls if
- * BLM_PCH_PWM_ENABLE is set.
- */
-static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
-       DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
-}
-
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -10541,16 +10809,20 @@ static struct intel_quirk intel_quirks[] = {
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 
-       /*
-        * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
-        * seem to use inverted backlight PWM.
-        */
-       { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
+       /* Acer Aspire 5734Z must invert backlight brightness */
+       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
+
+       /* Acer/eMachines G725 */
+       { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
 
-       /* Dell XPS13 HD Sandy Bridge */
-       { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
-       /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
-       { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
+       /* Acer/eMachines e725 */
+       { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
+
+       /* Acer/Packard Bell NCL20 */
+       { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
+
+       /* Acer Aspire 4736Z */
+       { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -10594,18 +10866,11 @@ static void i915_disable_vga(struct drm_device *dev)
 
 void intel_modeset_init_hw(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
        intel_prepare_ddi(dev);
 
        intel_init_clock_gating(dev);
 
-       /* Enable the CRI clock source so we can get at the display */
-       if (IS_VALLEYVIEW(dev))
-               I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
-                          DPLL_INTEGRATED_CRI_CLK_VLV);
-
-       intel_init_dpio(dev);
+       intel_reset_dpio(dev);
 
        mutex_lock(&dev->struct_mutex);
        intel_enable_gt_powersave(dev);
@@ -10667,6 +10932,9 @@ void intel_modeset_init(struct drm_device *dev)
                }
        }
 
+       intel_init_dpio(dev);
+       intel_reset_dpio(dev);
+
        intel_cpu_pll_init(dev);
        intel_shared_dpll_init(dev);
 
@@ -10870,7 +11138,7 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (HAS_POWER_WELL(dev) &&
+       if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
            (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
                return;
 
@@ -11014,7 +11282,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                pll->on = false;
        }
 
-       if (IS_HASWELL(dev))
+       if (HAS_PCH_SPLIT(dev))
                ilk_wm_get_hw_state(dev);
 
        if (force_restore) {
@@ -11044,10 +11312,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_setup_overlay(dev);
 
-       drm_modeset_lock_all(dev);
+       mutex_lock(&dev->mode_config.mutex);
        drm_mode_config_reset(dev);
        intel_modeset_setup_hw_state(dev, false);
-       drm_modeset_unlock_all(dev);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11092,12 +11360,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
-       /* destroy backlight, if any, before the connectors */
-       intel_panel_destroy_backlight(dev);
-
-       /* destroy the sysfs files before encoders/connectors */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+       /* destroy the backlight and sysfs files before encoders/connectors */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_panel_destroy_backlight(connector);
                drm_sysfs_connector_remove(connector);
+       }
 
        drm_mode_config_cleanup(dev);
 
@@ -11152,6 +11419,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
+               bool power_domain_on;
                u32 source;
        } pipe[I915_MAX_PIPES];
 
@@ -11166,6 +11434,7 @@ struct intel_display_error_state {
        } plane[I915_MAX_PIPES];
 
        struct intel_transcoder_error_state {
+               bool power_domain_on;
                enum transcoder cpu_transcoder;
 
                u32 conf;
@@ -11199,11 +11468,13 @@ intel_display_capture_error_state(struct drm_device *dev)
        if (error == NULL)
                return NULL;
 
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i)))
+               error->pipe[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->pipe[i].power_domain_on)
                        continue;
 
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
@@ -11239,8 +11510,10 @@ intel_display_capture_error_state(struct drm_device *dev)
        for (i = 0; i < error->num_transcoders; i++) {
                enum transcoder cpu_transcoder = transcoders[i];
 
-               if (!intel_display_power_enabled(dev,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
+               error->transcoder[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev,
+                               POWER_DOMAIN_TRANSCODER(cpu_transcoder));
+               if (!error->transcoder[i].power_domain_on)
                        continue;
 
                error->transcoder[i].cpu_transcoder = cpu_transcoder;
@@ -11270,11 +11543,13 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                return;
 
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
+               err_printf(m, "  Power: %s\n",
+                          error->pipe[i].power_domain_on ? "on" : "off");
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
 
                err_printf(m, "Plane [%d]:\n", i);
@@ -11300,6 +11575,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        for (i = 0; i < error->num_transcoders; i++) {
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  Power: %s\n",
+                          error->transcoder[i].power_domain_on ? "on" : "off");
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
index 30c627c7b7ba18a0dbd546859b047a769cad1d64..7df5085973e917ccd01c72487210621b78b783e9 100644 (file)
@@ -142,7 +142,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
        return (max_link_clock * max_lanes * 8) / 10;
 }
 
-static int
+static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
@@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        int i, ret, recv_bytes;
        uint32_t status;
        int try, precharge, clock = 0;
-       bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
+       bool has_aux_irq = true;
        uint32_t timeout;
 
        /* dp aux is extremely sensitive to irq latency, hence request the
@@ -542,7 +542,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
                return -E2BIG;
 
        intel_dp_check_edp(intel_dp);
-       msg[0] = AUX_NATIVE_WRITE << 4;
+       msg[0] = DP_AUX_NATIVE_WRITE << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = send_bytes - 1;
@@ -552,9 +552,10 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        break;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -586,7 +587,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                return -E2BIG;
 
        intel_dp_check_edp(intel_dp);
-       msg[0] = AUX_NATIVE_READ << 4;
+       msg[0] = DP_AUX_NATIVE_READ << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = recv_bytes - 1;
@@ -601,12 +602,12 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                        return -EPROTO;
                if (ret < 0)
                        return ret;
-               ack = reply[0];
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+               ack = reply[0] >> 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
                        memcpy(recv, reply + 1, ret - 1);
                        return ret - 1;
                }
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -633,12 +634,12 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        intel_dp_check_edp(intel_dp);
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[0] = AUX_I2C_READ << 4;
+               msg[0] = DP_AUX_I2C_READ << 4;
        else
-               msg[0] = AUX_I2C_WRITE << 4;
+               msg[0] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[0] |= AUX_I2C_MOT << 4;
+               msg[0] |= DP_AUX_I2C_MOT << 4;
 
        msg[1] = address >> 8;
        msg[2] = address;
@@ -675,17 +676,17 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        goto out;
                }
 
-               switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        ret = -EREMOTEIO;
                        goto out;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        /*
                         * For now, just give more slack to branch devices. We
                         * could check the DPCD for I2C bit rate capabilities,
@@ -706,18 +707,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        goto out;
                }
 
-               switch (reply[0] & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ) {
                                *read_byte = reply[1];
                        }
                        ret = reply_bytes - 1;
                        goto out;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        ret = -EREMOTEIO;
                        goto out;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
                        udelay(100);
                        break;
@@ -1037,6 +1038,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
                                I915_READ(pp_stat_reg),
                                I915_READ(pp_ctrl_reg));
        }
+
+       DRM_DEBUG_KMS("Wait complete\n");
 }
 
 static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
@@ -1092,6 +1095,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
        if (ironlake_edp_have_panel_vdd(intel_dp))
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
        if (!ironlake_edp_have_panel_power(intel_dp))
@@ -1140,7 +1145,11 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
                /* Make sure sequencer is idle before allowing subsequent activity */
                DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
                I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
-               msleep(intel_dp->panel_power_down_delay);
+
+               if ((pp & POWER_TARGET_ON) == 0)
+                       msleep(intel_dp->panel_power_cycle_delay);
+
+               intel_runtime_pm_put(dev_priv);
        }
 }
 
@@ -1233,20 +1242,16 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
        DRM_DEBUG_KMS("Turn eDP power off\n");
 
-       WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
-
        pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
-       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
 
-       intel_dp->want_panel_vdd = false;
-
        ironlake_wait_panel_off(intel_dp);
 }
 
@@ -1772,7 +1777,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
-       ironlake_edp_panel_vdd_on(intel_dp);
        ironlake_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        ironlake_edp_panel_off(intel_dp);
@@ -1845,23 +1849,23 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
        struct edp_power_seq power_seq;
        u32 val;
 
        mutex_lock(&dev_priv->dpio_lock);
 
-       val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1872,7 +1876,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
        intel_enable_dp(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -1882,24 +1886,24 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
                         DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
                         DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
                         (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
                                 DPIO_PCS_CLK_SOFT_RESET);
 
        /* Fix up inter-pair skew failure */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1941,18 +1945,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
                                              DP_LINK_STATUS_SIZE);
 }
 
-#if 0
-static char    *voltage_names[] = {
-       "0.4V", "0.6V", "0.8V", "1.2V"
-};
-static char    *pre_emph_names[] = {
-       "0dB", "3.5dB", "6dB", "9.5dB"
-};
-static char    *link_train_names[] = {
-       "pattern 1", "pattern 2", "idle", "off"
-};
-#endif
-
 /*
  * These are source-specific values; current Intel hardware supports
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
@@ -2050,7 +2042,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        unsigned long demph_reg_value, preemph_reg_value,
                uniqtranscale_reg_value;
        uint8_t train_set = intel_dp->train_set[0];
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -2127,14 +2119,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        }
 
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port),
                         uniqtranscale_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000);
        mutex_unlock(&dev_priv->dpio_lock);
 
        return 0;
@@ -3082,9 +3074,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        enum drm_connector_status status;
        struct edid *edid = NULL;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, drm_get_connector_name(connector));
 
@@ -3096,7 +3091,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                status = g4x_dp_detect(intel_dp);
 
        if (status != connector_status_connected)
-               return status;
+               goto out;
 
        intel_dp_probe_oui(intel_dp);
 
@@ -3112,7 +3107,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
        if (intel_encoder->type != INTEL_OUTPUT_EDP)
                intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-       return connector_status_connected;
+       status = connector_status_connected;
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
index 79f91f26e288d4bf2ae7815cb82cfc3271745bd5..8754db9e3d520fc00922bbe414dbae9f0632c05e 100644 (file)
@@ -65,8 +65,8 @@
 #define wait_for_atomic_us(COND, US) _wait_for((COND), \
                                               DIV_ROUND_UP((US), 1000), 0)
 
-#define KHz(x) (1000*x)
-#define MHz(x) KHz(1000*x)
+#define KHz(x) (1000 * (x))
+#define MHz(x) KHz(1000 * (x))
 
 /*
  * Display related stuff
@@ -155,7 +155,19 @@ struct intel_encoder {
 
 struct intel_panel {
        struct drm_display_mode *fixed_mode;
+       struct drm_display_mode *downclock_mode;
        int fitting_mode;
+
+       /* backlight */
+       struct {
+               bool present;
+               u32 level;
+               u32 max;
+               bool enabled;
+               bool combination_mode;  /* gen 2/4 only */
+               bool active_low_pwm;
+               struct backlight_device *device;
+       } backlight;
 };
 
 struct intel_connector {
@@ -443,7 +455,7 @@ struct intel_hdmi {
        bool rgb_quant_range_selectable;
        void (*write_infoframe)(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len);
+                               const void *frame, ssize_t len);
        void (*set_infoframes)(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode);
 };
@@ -490,9 +502,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
 {
        switch (dport->port) {
        case PORT_B:
-               return 0;
+               return DPIO_CH0;
        case PORT_C:
-               return 1;
+               return DPIO_CH1;
        default:
                BUG();
        }
@@ -601,7 +613,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
-bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
+bool intel_ddi_pll_select(struct intel_crtc *crtc);
+void intel_ddi_pll_enable(struct intel_crtc *crtc);
 void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
@@ -612,6 +625,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
 
 
 /* intel_display.c */
+const char *intel_output_name(int output);
 int intel_pch_rawclk(struct drm_device *dev);
 void intel_mark_busy(struct drm_device *dev);
 void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
@@ -638,7 +652,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+                        struct intel_digital_port *dport);
 bool intel_get_load_detect_pipe(struct drm_connector *connector,
                                struct drm_display_mode *mode,
                                struct intel_load_detect_pipe *old);
@@ -690,11 +705,10 @@ void
 ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
                                int dotclock);
 bool intel_crtc_active(struct drm_crtc *crtc);
-void i915_disable_vga_mem(struct drm_device *dev);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
-
+int valleyview_get_vco(struct drm_i915_private *dev_priv);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
@@ -808,9 +822,13 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 int intel_panel_setup_backlight(struct drm_connector *connector);
 void intel_panel_enable_backlight(struct intel_connector *connector);
 void intel_panel_disable_backlight(struct intel_connector *connector);
-void intel_panel_destroy_backlight(struct drm_device *dev);
+void intel_panel_destroy_backlight(struct drm_connector *connector);
+void intel_panel_init_backlight_funcs(struct drm_device *dev);
 enum drm_connector_status intel_panel_detect(struct drm_device *dev);
-
+extern struct drm_display_mode *intel_find_panel_downclock(
+                               struct drm_device *dev,
+                               struct drm_display_mode *fixed_mode,
+                               struct drm_connector *connector);
 
 /* intel_pm.c */
 void intel_init_clock_gating(struct drm_device *dev);
@@ -830,6 +848,8 @@ int intel_power_domains_init(struct drm_device *dev);
 void intel_power_domains_remove(struct drm_device *dev);
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain);
+bool intel_display_power_enabled_sw(struct drm_device *dev,
+                                   enum intel_display_power_domain domain);
 void intel_display_power_get(struct drm_device *dev,
                             enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_device *dev,
@@ -844,6 +864,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
index d257b093ca68757874925999fae766a727755212..fabbf0d895cf2a5e133d804d5e8e05f0f26f79ad 100644 (file)
 static const struct intel_dsi_device intel_dsi_devices[] = {
 };
 
-
-static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val,
-                          u32 mask)
-{
-       u32 tmp = vlv_cck_read(dev_priv, reg);
-       tmp &= ~mask;
-       tmp |= val;
-       vlv_cck_write(dev_priv, reg, tmp);
-}
-
-static void band_gap_wa(struct drm_i915_private *dev_priv)
+static void band_gap_reset(struct drm_i915_private *dev_priv)
 {
        mutex_lock(&dev_priv->dpio_lock);
 
-       /* Enable bandgap fix in GOP driver */
-       vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000);
-       msleep(20);
-
-       /* Turn Display Trunk on */
-       vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000);
-       msleep(20);
-
-       vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000);
-       msleep(20);
-
-       vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0001);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0005);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0025);
+       udelay(150);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0000);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0000);
 
        mutex_unlock(&dev_priv->dpio_lock);
-
-       /* Need huge delay, otherwise clock is not stable */
-       msleep(100);
 }
 
 static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector)
@@ -132,14 +101,47 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
        vlv_enable_dsi_pll(encoder);
 }
 
+static void intel_dsi_device_ready(struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
+       DRM_DEBUG_KMS("\n");
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+}
 static void intel_dsi_pre_enable(struct intel_encoder *encoder)
 {
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
        DRM_DEBUG_KMS("\n");
+
+       if (intel_dsi->dev.dev_ops->panel_reset)
+               intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
+
+       /* put device in ready state */
+       intel_dsi_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->send_otp_cmds)
+               intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
 }
 
 static void intel_dsi_enable(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -147,41 +149,28 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
-       temp = I915_READ(MIPI_DEVICE_READY(pipe));
-       if ((temp & DEVICE_READY) == 0) {
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY);
-       } else if (temp & ULPS_STATE_MASK) {
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT);
-               /*
-                * We need to ensure that there is a minimum of 1 ms time
-                * available before clearing the UPLS exit state.
-                */
-               msleep(2);
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
-       }
-
        if (is_cmd_mode(intel_dsi))
                I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
-
-       if (is_vid_mode(intel_dsi)) {
+       else {
                msleep(20); /* XXX */
                dpi_send_cmd(intel_dsi, TURN_ON);
                msleep(100);
 
                /* assert ip_tg_enable signal */
-               temp = I915_READ(MIPI_PORT_CTRL(pipe));
+               temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
+               temp = temp | intel_dsi->port_bits;
                I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
                POSTING_READ(MIPI_PORT_CTRL(pipe));
        }
 
-       intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+       if (intel_dsi->dev.dev_ops->enable)
+               intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
 }
 
 static void intel_dsi_disable(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -189,8 +178,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
-       intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
-
        if (is_vid_mode(intel_dsi)) {
                dpi_send_cmd(intel_dsi, SHUTDOWN);
                msleep(10);
@@ -203,20 +190,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
                msleep(2);
        }
 
-       temp = I915_READ(MIPI_DEVICE_READY(pipe));
-       if (temp & DEVICE_READY) {
-               temp &= ~DEVICE_READY;
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
-       }
+       /* if disable packets are sent before sending shutdown packet then in
+        * some next enable sequence send turn on packet error is observed */
+       if (intel_dsi->dev.dev_ops->disable)
+               intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
 }
 
-static void intel_dsi_post_disable(struct intel_encoder *encoder)
+static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
 {
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
        DRM_DEBUG_KMS("\n");
 
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+
+       if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
+                                       == 0x00000), 30))
+               DRM_ERROR("DSI LP not going Low\n");
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+
        vlv_disable_dsi_pll(encoder);
 }
+static void intel_dsi_post_disable(struct intel_encoder *encoder)
+{
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
+       DRM_DEBUG_KMS("\n");
+
+       intel_dsi_clear_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->disable_panel_power)
+               intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);
+}
 
 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
                                   enum pipe *pipe)
@@ -251,8 +272,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
        /* XXX: read flags, set to adjusted_mode */
 }
 
-static int intel_dsi_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_dsi_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
@@ -352,11 +374,8 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 
        DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
 
-       /* Update the DSI PLL */
-       vlv_enable_dsi_pll(intel_encoder);
-
        /* XXX: Location of the call */
-       band_gap_wa(dev_priv);
+       band_gap_reset(dev_priv);
 
        /* escape clock divider, 20MHz, shared for A and C. device ready must be
         * off when doing this! txclkesc? */
@@ -373,11 +392,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
        I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
        I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);
 
-       I915_WRITE(MIPI_DPHY_PARAM(pipe),
-                  0x3c << EXIT_ZERO_COUNT_SHIFT |
-                  0x1f << TRAIL_COUNT_SHIFT |
-                  0xc5 << CLK_ZERO_COUNT_SHIFT |
-                  0x1f << PREPARE_COUNT_SHIFT);
+       I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg);
 
        I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
                   adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
@@ -425,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
                                       adjusted_mode->htotal,
                                       bpp, intel_dsi->lane_count) + 1);
        }
-       I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */
-       I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */
-       I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */
+       I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
+       I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
+       I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);
 
        /* dphy stuff */
 
@@ -442,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
         *
         * XXX: write MIPI_STOP_STATE_STALL?
         */
-       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46);
+       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
+                                               intel_dsi->hs_to_lp_count);
 
        /* XXX: low power clock equivalence in terms of byte clock. the number
         * of byte clocks occupied in one low power clock. based on txbyteclkhs
         * and txclkesc. txclkesc time / txbyteclk time * (105 +
         * MIPI_STOP_STATE_STALL) / 105.???
         */
-       I915_WRITE(MIPI_LP_BYTECLK(pipe), 4);
+       I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);
 
        /* the bw essential for transmitting 16 long packets containing 252
         * bytes meant for dcs write memory command is programmed in this
         * register in terms of byte clocks. based on dsi transfer rate and the
         * number of lanes configured the time taken to transmit 16 long packets
         * in a dsi stream varies. */
-       I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820);
+       I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);
 
        I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
-                  0xa << LP_HS_SSW_CNT_SHIFT |
-                  0x14 << HS_LP_PWR_SW_CNT_SHIFT);
+                  intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
+                  intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
 
        if (is_vid_mode(intel_dsi))
                I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
-                          intel_dsi->video_mode_format);
+                               intel_dsi->video_frmt_cfg_bits |
+                               intel_dsi->video_mode_format);
 }
 
 static enum drm_connector_status
index c7765f33d5245fa2ff1fd03fe2bb12339a716473..b4a27cec882f76d7cab17400d8adf438532b4c9d 100644 (file)
@@ -39,6 +39,13 @@ struct intel_dsi_device {
 struct intel_dsi_dev_ops {
        bool (*init)(struct intel_dsi_device *dsi);
 
+       void (*panel_reset)(struct intel_dsi_device *dsi);
+
+       void (*disable_panel_power)(struct intel_dsi_device *dsi);
+
+       /* one time programmable commands if needed */
+       void (*send_otp_cmds)(struct intel_dsi_device *dsi);
+
        /* This callback must be able to assume DSI commands can be sent */
        void (*enable)(struct intel_dsi_device *dsi);
 
@@ -89,6 +96,20 @@ struct intel_dsi {
 
        /* eot for MIPI_EOT_DISABLE register */
        u32 eot_disable;
+
+       u32 port_bits;
+       u32 bw_timer;
+       u32 dphy_reg;
+       u32 video_frmt_cfg_bits;
+       u16 lp_byte_clk;
+
+       /* timeouts in byte clocks */
+       u16 lp_rx_timeout;
+       u16 turn_arnd_val;
+       u16 rst_timer_val;
+       u16 hs_to_lp_count;
+       u16 clk_lp_to_hs_count;
+       u16 clk_hs_to_lp_count;
 };
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
index 44279b2ade888a7821d75da44ab523ab8f1f318a..ba79ec19da3b8ce8d4379df2545c1ea54c3a8f3e 100644 (file)
@@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
        71, 35                                                  /* 91 - 92 */
 };
 
+#ifdef DSI_CLK_FROM_RR
+
 static u32 dsi_rr_formula(const struct drm_display_mode *mode,
                          int pixel_format, int video_mode_format,
                          int lane_count, bool eotp)
@@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
 
        /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
        dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
-       dsi_clk = dsi_bit_clock_hz / (1000 * 1000);
+       dsi_clk = dsi_bit_clock_hz / 1000;
 
        if (eotp && video_mode_format == VIDEO_MODE_BURST)
                dsi_clk *= 2;
@@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
        return dsi_clk;
 }
 
-#ifdef MNP_FROM_TABLE
-
-struct dsi_clock_table {
-       u32 freq;
-       u8 m;
-       u8 p;
-};
-
-static const struct dsi_clock_table dsi_clk_tbl[] = {
-       {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6},
-       {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6},
-       {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5},
-       {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5},
-       {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5},
-       {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5},
-       {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5},
-       {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5},
-       {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5},
-       {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4},
-       {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4},
-       {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3},
-       {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3},
-       {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3},
-       {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3},
-       {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3},
-       {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2},
-       {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2},
-       {1000, 80, 2},          /* dsi clock frequency in Mhz*/
-};
+#else
 
-static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
+/* Get DSI clock from pixel clock */
+static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
+                         int pixel_format, int lane_count)
 {
-       unsigned int i;
-       u8 m;
-       u8 n;
-       u8 p;
-       u32 m_seed;
-
-       if (dsi_clk < 300 || dsi_clk > 1000)
-               return -ECHRNG;
+       u32 dsi_clk_khz;
+       u32 bpp;
 
-       for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
-               if (dsi_clk_tbl[i].freq > dsi_clk)
-                       break;
+       switch (pixel_format) {
+       default:
+       case VID_MODE_FORMAT_RGB888:
+       case VID_MODE_FORMAT_RGB666_LOOSE:
+               bpp = 24;
+               break;
+       case VID_MODE_FORMAT_RGB666:
+               bpp = 18;
+               break;
+       case VID_MODE_FORMAT_RGB565:
+               bpp = 16;
+               break;
        }
 
-       m = dsi_clk_tbl[i].m;
-       p = dsi_clk_tbl[i].p;
-       m_seed = lfsr_converts[m - 62];
-       n = 1;
-       dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2);
-       dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
-               m_seed << DSI_PLL_M1_DIV_SHIFT;
+       /* DSI data rate = pixel clock * bits per pixel / lane count
+          pixel clock is converted from KHz to Hz */
+       dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
 
-       return 0;
+       return dsi_clk_khz;
 }
 
-#else
+#endif
 
 static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
 {
@@ -194,36 +169,47 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        u32 ref_clk;
        u32 error;
        u32 tmp_error;
-       u32 target_dsi_clk;
-       u32 calc_dsi_clk;
+       int target_dsi_clk;
+       int calc_dsi_clk;
        u32 calc_m;
        u32 calc_p;
        u32 m_seed;
 
-       if (dsi_clk < 300 || dsi_clk > 1150) {
+       /* dsi_clk is expected in KHZ */
+       if (dsi_clk < 300000 || dsi_clk > 1150000) {
                DRM_ERROR("DSI CLK Out of Range\n");
                return -ECHRNG;
        }
 
        ref_clk = 25000;
-       target_dsi_clk = dsi_clk * 1000;
+       target_dsi_clk = dsi_clk;
        error = 0xFFFFFFFF;
+       tmp_error = 0xFFFFFFFF;
        calc_m = 0;
        calc_p = 0;
 
        for (m = 62; m <= 92; m++) {
                for (p = 2; p <= 6; p++) {
-
+                       /* Find the optimal m and p divisors
+                       with minimal error +/- the required clock */
                        calc_dsi_clk = (m * ref_clk) / p;
-                       if (calc_dsi_clk >= target_dsi_clk) {
-                               tmp_error = calc_dsi_clk - target_dsi_clk;
-                               if (tmp_error < error) {
-                                       error = tmp_error;
-                                       calc_m = m;
-                                       calc_p = p;
-                               }
+                       if (calc_dsi_clk == target_dsi_clk) {
+                               calc_m = m;
+                               calc_p = p;
+                               error = 0;
+                               break;
+                       } else
+                               tmp_error = abs(target_dsi_clk - calc_dsi_clk);
+
+                       if (tmp_error < error) {
+                               error = tmp_error;
+                               calc_m = m;
+                               calc_p = p;
                        }
                }
+
+               if (error == 0)
+                       break;
        }
 
        m_seed = lfsr_converts[calc_m - 62];
@@ -235,8 +221,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        return 0;
 }
 
-#endif
-
 /*
  * XXX: The muxing and gating is hard coded for now. Need to add support for
  * sharing PLLs with two DSI outputs.
@@ -251,9 +235,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
        struct dsi_mnp dsi_mnp;
        u32 dsi_clk;
 
-       dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
-                                intel_dsi->video_mode_format,
-                                intel_dsi->lane_count, !intel_dsi->eot_disable);
+       dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
+                                               intel_dsi->lane_count);
 
        ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
        if (ret) {
index 3c77365468562ab026910a1e111fb932b288f242..eeff998e52efdea93534ffb680582503f9f2a56c 100644 (file)
@@ -234,8 +234,9 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_dvo_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_dvo_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
 
index 895fcb4fbd9446bfbfafc90f95948d9a4bea5c55..39eac9937a4aa1a89c176ef77d727cfb615b8cd1 100644 (file)
@@ -57,18 +57,14 @@ static struct fb_ops intelfb_ops = {
        .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
-static int intelfb_create(struct drm_fb_helper *helper,
-                         struct drm_fb_helper_surface_size *sizes)
+static int intelfb_alloc(struct drm_fb_helper *helper,
+                        struct drm_fb_helper_surface_size *sizes)
 {
        struct intel_fbdev *ifbdev =
                container_of(helper, struct intel_fbdev, helper);
        struct drm_device *dev = helper->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd = {};
        struct drm_i915_gem_object *obj;
-       struct device *device = &dev->pdev->dev;
        int size, ret;
 
        /* we don't do packed 24bpp */
@@ -94,8 +90,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       mutex_lock(&dev->struct_mutex);
-
        /* Flush everything out, we'll be doing GTT only from now on */
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
        if (ret) {
@@ -103,7 +97,50 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out_unref;
        }
 
-       info = framebuffer_alloc(0, device);
+       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
+       if (ret)
+               goto out_unpin;
+
+       return 0;
+
+out_unpin:
+       i915_gem_object_unpin(obj);
+out_unref:
+       drm_gem_object_unreference(&obj->base);
+out:
+       return ret;
+}
+
+static int intelfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+       struct drm_device *dev = helper->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_i915_gem_object *obj;
+       int size, ret;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (!intel_fb->obj) {
+               DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
+               ret = intelfb_alloc(helper, sizes);
+               if (ret)
+                       goto out_unlock;
+       } else {
+               DRM_DEBUG_KMS("re-using BIOS fb\n");
+               sizes->fb_width = intel_fb->base.width;
+               sizes->fb_height = intel_fb->base.height;
+       }
+
+       obj = intel_fb->obj;
+       size = obj->base.size;
+
+       info = framebuffer_alloc(0, &dev->pdev->dev);
        if (!info) {
                ret = -ENOMEM;
                goto out_unpin;
@@ -111,10 +148,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        info->par = helper;
 
-       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
-       if (ret)
-               goto out_unpin;
-
        fb = &ifbdev->ifb.base;
 
        ifbdev->helper.fb = fb;
@@ -170,17 +203,15 @@ static int intelfb_create(struct drm_fb_helper *helper,
                      fb->width, fb->height,
                      i915_gem_obj_ggtt_offset(obj), obj);
 
-
        mutex_unlock(&dev->struct_mutex);
        vga_switcheroo_client_fb_set(dev->pdev, info);
        return 0;
 
 out_unpin:
        i915_gem_object_unpin(obj);
-out_unref:
        drm_gem_object_unreference(&obj->base);
+out_unlock:
        mutex_unlock(&dev->struct_mutex);
-out:
        return ret;
 }
 
@@ -297,8 +328,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
        fb_set_suspend(info, state);
 }
 
-MODULE_LICENSE("GPL and additional rights");
-
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index 03f9ca70530c03f441ae037b16cf0c5e80b908ab..6db0d9d17f47e7b5ce5c43a7aa7795de71ea6346 100644 (file)
@@ -130,9 +130,9 @@ static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
 
 static void g4x_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val = I915_READ(VIDEO_DIP_CTL);
@@ -167,9 +167,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -205,9 +205,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -246,9 +246,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -284,9 +284,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -853,8 +853,9 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
                return 225000;
 }
 
-static int intel_hdmi_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_hdmi_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
                return MODE_CLOCK_HIGH;
@@ -1081,7 +1082,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
        u32 val;
 
@@ -1090,41 +1091,33 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
 
        /* Enable clock channels for this port */
        mutex_lock(&dev_priv->dpio_lock);
-       val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
 
        /* HDMI 1.0V-2dB */
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port),
-                        0x2b245f5f);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
-                        0x5578b83a);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port),
-                        0x0c782040);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port),
-                        0x2b247878);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
-                        0x00002000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
 
        /* Program lane clock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port),
-                        0x00760018);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port),
-                        0x00400888);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
        mutex_unlock(&dev_priv->dpio_lock);
 
        intel_enable_hdmi(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
@@ -1134,7 +1127,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        if (!IS_VALLEYVIEW(dev))
@@ -1142,24 +1135,22 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
                         DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
                         DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
                         (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
                         DPIO_PCS_CLK_SOFT_RESET);
 
        /* Fix up inter-pair skew failure */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
-
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
-                        0x00002000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
+
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1169,13 +1160,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        /* Reset lanes to avoid HDMI flicker (VLV w/a) */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
index 2ca17b14b6c1c91710601dfcb34c661b45707347..b1dc33f478991755ec114fe66fbad7bc40fec4c0 100644 (file)
@@ -82,20 +82,11 @@ static int get_disp_clk_div(struct drm_i915_private *dev_priv,
 
 static void gmbus_set_freq(struct drm_i915_private *dev_priv)
 {
-       int vco_freq[] = { 800, 1600, 2000, 2400 };
-       int gmbus_freq = 0, cdclk_div, hpll_freq;
+       int vco, gmbus_freq = 0, cdclk_div;
 
        BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
 
-       /* Skip setting the gmbus freq if BIOS has already programmed it */
-       if (I915_READ(GMBUSFREQ_VLV) != 0xA0)
-               return;
-
-       /* Obtain SKU information */
-       mutex_lock(&dev_priv->dpio_lock);
-       hpll_freq =
-               vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK;
-       mutex_unlock(&dev_priv->dpio_lock);
+       vco = valleyview_get_vco(dev_priv);
 
        /* Get the CDCLK divide ratio */
        cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
@@ -106,7 +97,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv)
         * in fact 1MHz is the correct frequency.
         */
        if (cdclk_div)
-               gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div;
+               gmbus_freq = (vco << 1) / cdclk_div;
 
        if (WARN_ON(gmbus_freq == 0))
                return;
index c3b4da7895ed1c82b185b78ca06d00053cff2402..8bcb93a2a9f6b1d09780c3154f6c656895451e8e 100644 (file)
@@ -256,8 +256,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
        POSTING_READ(lvds_encoder->reg);
 }
 
-static int intel_lvds_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_lvds_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
@@ -446,9 +447,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        if (dev_priv->modeset_restore == MODESET_DONE)
                goto exit;
 
-       drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev, true);
-       drm_modeset_unlock_all(dev);
+       /*
+        * Some old platform's BIOS love to wreak havoc while the lid is closed.
+        * We try to detect this here and undo any damage. The split for PCH
+        * platforms is rather conservative and a bit arbitrary expect that on
+        * those platforms VGA disabling requires actual legacy VGA I/O access,
+        * and as part of the cleanup in the hw state restore we also redisable
+        * the vga plane.
+        */
+       if (!HAS_PCH_SPLIT(dev)) {
+               drm_modeset_lock_all(dev);
+               intel_modeset_setup_hw_state(dev, true);
+               drm_modeset_unlock_all(dev);
+       }
 
        dev_priv->modeset_restore = MODESET_DONE;
 
@@ -744,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-/**
- * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
- * @dev: drm device
- * @connector: LVDS connector
- *
- * Find the reduced downclock for LVDS in EDID.
- */
-static void intel_find_lvds_downclock(struct drm_device *dev,
-                                     struct drm_display_mode *fixed_mode,
-                                     struct drm_connector *connector)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_display_mode *scan;
-       int temp_downclock;
-
-       temp_downclock = fixed_mode->clock;
-       list_for_each_entry(scan, &connector->probed_modes, head) {
-               /*
-                * If one mode has the same resolution with the fixed_panel
-                * mode while they have the different refresh rate, it means
-                * that the reduced downclock is found for the LVDS. In such
-                * case we can set the different FPx0/1 to dynamically select
-                * between low and high frequency.
-                */
-               if (scan->hdisplay == fixed_mode->hdisplay &&
-                   scan->hsync_start == fixed_mode->hsync_start &&
-                   scan->hsync_end == fixed_mode->hsync_end &&
-                   scan->htotal == fixed_mode->htotal &&
-                   scan->vdisplay == fixed_mode->vdisplay &&
-                   scan->vsync_start == fixed_mode->vsync_start &&
-                   scan->vsync_end == fixed_mode->vsync_end &&
-                   scan->vtotal == fixed_mode->vtotal) {
-                       if (scan->clock < temp_downclock) {
-                               /*
-                                * The downclock is already found. But we
-                                * expect to find the lower downclock.
-                                */
-                               temp_downclock = scan->clock;
-                       }
-               }
-       }
-       if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
-               /* We found the downclock for LVDS. */
-               dev_priv->lvds_downclock_avail = 1;
-               dev_priv->lvds_downclock = temp_downclock;
-               DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
-                             "Normal clock %dKhz, downclock %dKhz\n",
-                             fixed_mode->clock, temp_downclock);
-       }
-}
-
 /*
  * Enumerate the child dev array parsed from VBT to check whether
  * the LVDS is present.
@@ -1072,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
 
                        fixed_mode = drm_mode_duplicate(dev, scan);
                        if (fixed_mode) {
-                               intel_find_lvds_downclock(dev, fixed_mode,
-                                                         connector);
+                               intel_connector->panel.downclock_mode =
+                                       intel_find_panel_downclock(dev,
+                                       fixed_mode, connector);
+                               if (intel_connector->panel.downclock_mode !=
+                                       NULL && i915_lvds_downclock) {
+                                       /* We found the downclock for LVDS. */
+                                       dev_priv->lvds_downclock_avail = true;
+                                       dev_priv->lvds_downclock =
+                                               intel_connector->panel.
+                                               downclock_mode->clock;
+                                       DRM_DEBUG_KMS("LVDS downclock is found"
+                                       " in EDID. Normal clock %dKhz, "
+                                       "downclock %dKhz\n",
+                                       fixed_mode->clock,
+                                       dev_priv->lvds_downclock);
+                               }
                                goto out;
                        }
                }
index 6d69a9bad86545c6a8cfc8e8ff86480d462c2132..3da259e280bad48696d0bbc905a2835c258d1b38 100644 (file)
@@ -64,7 +64,7 @@ struct opregion_header {
        u8 driver_ver[16];
        u32 mboxes;
        u8 reserved[164];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #1: public ACPI methods */
 struct opregion_acpi {
@@ -86,7 +86,7 @@ struct opregion_acpi {
        u32 cnot;       /* current OS notification */
        u32 nrdy;       /* driver status */
        u8 rsvd2[60];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #2: SWSCI */
 struct opregion_swsci {
@@ -94,7 +94,7 @@ struct opregion_swsci {
        u32 parm;       /* command parameters */
        u32 dslp;       /* driver sleep time-out */
        u8 rsvd[244];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #3: ASLE */
 struct opregion_asle {
@@ -115,7 +115,7 @@ struct opregion_asle {
        u32 srot;       /* supported rotation angles */
        u32 iuer;       /* IUER events */
        u8 rsvd[86];
-} __attribute__((packed));
+} __packed;
 
 /* Driver readiness indicator */
 #define ASLE_ARDY_READY                (1 << 0)
@@ -396,13 +396,10 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct intel_connector *intel_connector = NULL;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
+       struct intel_connector *intel_connector;
+       struct intel_panel *panel;
        struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
-       u32 ret = 0;
-       bool found = false;
 
        DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
 
@@ -414,38 +411,24 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
                return ASLC_BACKLIGHT_FAILED;
 
        mutex_lock(&dev->mode_config.mutex);
+
        /*
-        * Could match the OpRegion connector here instead, but we'd also need
-        * to verify the connector could handle a backlight call.
+        * Update backlight on all connectors that support backlight (usually
+        * only one).
         */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               if (encoder->crtc == crtc) {
-                       found = true;
-                       break;
-               }
-
-       if (!found) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               if (connector->encoder == encoder)
-                       intel_connector = to_intel_connector(connector);
-
-       if (!intel_connector) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
        DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
-       intel_panel_set_backlight(intel_connector, bclp, 255);
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_connector = to_intel_connector(connector);
+               panel = &intel_connector->panel;
+               if (panel->backlight.present)
+                       intel_panel_set_backlight(intel_connector, bclp, 255);
+       }
        iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
 
-out:
        mutex_unlock(&dev->mode_config.mutex);
 
-       return ret;
+
+       return 0;
 }
 
 static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
index a98a990fbab3561368239ce7a7ac020c1d44f0c7..a759ecdb7a6ebaddee622ffd5a1d7900fcf5aee3 100644 (file)
@@ -1005,7 +1005,7 @@ static int intel_panel_fitter_pipe(struct drm_device *dev)
        u32  pfit_control;
 
        /* i830 doesn't have a panel fitter */
-       if (IS_I830(dev))
+       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
                return -1;
 
        pfit_control = I915_READ(PFIT_CONTROL);
index e6f782d1c6696d94fe4d4a80cf7f4d6ee6b5c7d7..20ebc3e83d39fa073d80ad46386884635dd1dce3 100644 (file)
@@ -325,214 +325,170 @@ out:
        pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
-static int is_backlight_combination_mode(struct drm_device *dev)
+static int i915_panel_invert_brightness;
+MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
+       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
+       "report PCI device ID, subsystem vendor and subsystem device ID "
+       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
+       "It will then be included in an upcoming module version.");
+module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
+static u32 intel_panel_compute_brightness(struct intel_connector *connector,
+                                         u32 val)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
 
-       if (IS_GEN4(dev))
-               return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
+       WARN_ON(panel->backlight.max == 0);
 
-       if (IS_GEN2(dev))
-               return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
+       if (i915_panel_invert_brightness < 0)
+               return val;
 
-       return 0;
+       if (i915_panel_invert_brightness > 0 ||
+           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
+               return panel->backlight.max - val;
+       }
+
+       return val;
 }
 
-/* XXX: query mode clock or hardware clock and program max PWM appropriately
- * when it's 0.
- */
-static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe)
+static u32 bdw_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val;
-
-       WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock));
 
-       /* Restore the CTL value if it lost, e.g. GPU reset */
-
-       if (HAS_PCH_SPLIT(dev_priv->dev)) {
-               val = I915_READ(BLC_PWM_PCH_CTL2);
-               if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = val;
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL2;
-                       I915_WRITE(BLC_PWM_PCH_CTL2, val);
-               }
-       } else if (IS_VALLEYVIEW(dev)) {
-               val = I915_READ(VLV_BLC_PWM_CTL(pipe));
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       dev_priv->regfile.saveBLC_PWM_CTL2 =
-                               I915_READ(VLV_BLC_PWM_CTL2(pipe));
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), val);
-                       I915_WRITE(VLV_BLC_PWM_CTL2(pipe),
-                                  dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
+       return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-               if (!val)
-                       val = 0x0f42ffff;
-       } else {
-               val = I915_READ(BLC_PWM_CTL);
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                                       I915_READ(BLC_PWM_CTL2);
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(BLC_PWM_CTL, val);
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               I915_WRITE(BLC_PWM_CTL2,
-                                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
-       }
+static u32 pch_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       return val;
+       return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 }
 
-static u32 intel_panel_get_max_backlight(struct drm_device *dev,
-                                        enum pipe pipe)
+static u32 i9xx_get_backlight(struct intel_connector *connector)
 {
-       u32 max;
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 val;
 
-       max = i915_read_blc_pwm_ctl(dev, pipe);
+       val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+       if (INTEL_INFO(dev)->gen < 4)
+               val >>= 1;
 
-       if (HAS_PCH_SPLIT(dev)) {
-               max >>= 16;
-       } else {
-               if (INTEL_INFO(dev)->gen < 4)
-                       max >>= 17;
-               else
-                       max >>= 16;
+       if (panel->backlight.combination_mode) {
+               u8 lbpc;
 
-               if (is_backlight_combination_mode(dev))
-                       max *= 0xff;
+               pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
+               val *= lbpc;
        }
 
-       DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
-
-       return max;
+       return val;
 }
 
-static int i915_panel_invert_brightness;
-MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
-       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
-       "report PCI device ID, subsystem vendor and subsystem device ID "
-       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
-       "It will then be included in an upcoming module version.");
-module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
-static u32 intel_panel_compute_brightness(struct drm_device *dev,
-                                         enum pipe pipe, u32 val)
+static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (i915_panel_invert_brightness < 0)
-               return val;
+       return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-       if (i915_panel_invert_brightness > 0 ||
-           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
-               if (max)
-                       return max - val;
-       }
+static u32 vlv_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
 
-       return val;
+       return _vlv_get_backlight(dev, pipe);
 }
 
-static u32 intel_panel_get_backlight(struct drm_device *dev,
-                                    enum pipe pipe)
+static u32 intel_panel_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val;
        unsigned long flags;
-       int reg;
-
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       if (IS_BROADWELL(dev)) {
-               val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
-       } else if (HAS_PCH_SPLIT(dev)) {
-               val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-       } else {
-               if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL(pipe);
-               else
-                       reg = BLC_PWM_CTL;
-
-               val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK;
-               if (INTEL_INFO(dev)->gen < 4)
-                       val >>= 1;
 
-               if (is_backlight_combination_mode(dev)) {
-                       u8 lbpc;
-
-                       pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
-                       val *= lbpc;
-               }
-       }
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       val = intel_panel_compute_brightness(dev, pipe, val);
+       val = dev_priv->display.get_backlight(connector);
+       val = intel_panel_compute_brightness(connector, val);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 
        DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
        return val;
 }
 
-static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level)
+static void bdw_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
        I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
 }
 
-static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
+static void pch_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(BLC_PWM_CPU_CTL, val | level);
+       u32 tmp;
+
+       tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
 }
 
-static void intel_panel_actually_set_backlight(struct drm_device *dev,
-                                              enum pipe pipe, u32 level)
+static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 tmp;
-       int reg;
+       struct intel_panel *panel = &connector->panel;
+       u32 tmp, mask;
 
-       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
-       level = intel_panel_compute_brightness(dev, pipe, level);
+       WARN_ON(panel->backlight.max == 0);
 
-       if (IS_BROADWELL(dev))
-               return intel_bdw_panel_set_backlight(dev, level);
-       else if (HAS_PCH_SPLIT(dev))
-               return intel_pch_panel_set_backlight(dev, level);
-
-       if (is_backlight_combination_mode(dev)) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
+       if (panel->backlight.combination_mode) {
                u8 lbpc;
 
-               /* we're screwed, but keep behaviour backwards compatible */
-               if (!max)
-                       max = 1;
-
-               lbpc = level * 0xfe / max + 1;
+               lbpc = level * 0xfe / panel->backlight.max + 1;
                level /= lbpc;
                pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
        }
 
-       if (IS_VALLEYVIEW(dev))
-               reg = VLV_BLC_PWM_CTL(pipe);
-       else
-               reg = BLC_PWM_CTL;
-
-       tmp = I915_READ(reg);
-       if (INTEL_INFO(dev)->gen < 4)
+       if (IS_GEN4(dev)) {
+               mask = BACKLIGHT_DUTY_CYCLE_MASK;
+       } else {
                level <<= 1;
-       tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(reg, tmp | level);
+               mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
+       }
+
+       tmp = I915_READ(BLC_PWM_CTL) & ~mask;
+       I915_WRITE(BLC_PWM_CTL, tmp | level);
+}
+
+static void vlv_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
+}
+
+static void
+intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
+
+       level = intel_panel_compute_brightness(connector, level);
+       dev_priv->display.set_backlight(connector, level);
 }
 
 /* set backlight brightness to level in range [0..max] */
@@ -541,6 +497,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        u32 freq;
        unsigned long flags;
@@ -548,34 +505,77 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
        if (pipe == INVALID_PIPE)
                return;
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       freq = intel_panel_get_max_backlight(dev, pipe);
-       if (!freq) {
-               /* we are screwed, bail out */
-               goto out;
-       }
+       WARN_ON(panel->backlight.max == 0);
 
-       /* scale to hardware, but be careful to not overflow */
+       /* scale to hardware max, but be careful to not overflow */
+       freq = panel->backlight.max;
        if (freq < max)
                level = level * freq / max;
        else
                level = freq / max * level;
 
-       dev_priv->backlight.level = level;
-       if (dev_priv->backlight.device)
-               dev_priv->backlight.device->props.brightness = level;
+       panel->backlight.level = level;
+       if (panel->backlight.device)
+               panel->backlight.device->props.brightness = level;
 
-       if (dev_priv->backlight.enabled)
-               intel_panel_actually_set_backlight(dev, pipe, level);
-out:
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       if (panel->backlight.enabled)
+               intel_panel_actually_set_backlight(connector, level);
+
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
+
+static void pch_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
+
+       tmp = I915_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
+}
+
+static void i9xx_disable_backlight(struct intel_connector *connector)
+{
+       intel_panel_actually_set_backlight(connector, 0);
+}
+
+static void i965_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
+}
+
+static void vlv_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
 }
 
 void intel_panel_disable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        unsigned long flags;
 
@@ -593,150 +593,215 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
                return;
        }
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       dev_priv->backlight.enabled = false;
-       intel_panel_actually_set_backlight(dev, pipe, 0);
+       panel->backlight.enabled = false;
+       dev_priv->display.disable_backlight(connector);
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+static void bdw_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
 
-               I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
 
-               if (HAS_PCH_SPLIT(dev)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp &= ~BLM_PCH_PWM_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
-       }
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       /* BDW always uses the pch pwm controls. */
+       pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
+
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 }
 
-void intel_panel_enable_backlight(struct intel_connector *connector)
+static void pch_enable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        enum transcoder cpu_transcoder =
                intel_pipe_to_cpu_transcoder(dev_priv, pipe);
-       unsigned long flags;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2;
 
-       if (pipe == INVALID_PIPE)
-               return;
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       if (cpu_ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "cpu backlight already enabled\n");
+               cpu_ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       }
 
-       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
+
+       if (cpu_transcoder == TRANSCODER_EDP)
+               cpu_ctl2 = BLM_TRANSCODER_EDP;
+       else
+               cpu_ctl2 = BLM_PIPE(cpu_transcoder);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       POSTING_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
+
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
 
-       if (dev_priv->backlight.level == 0) {
-               dev_priv->backlight.level = intel_panel_get_max_backlight(dev,
-                                                                         pipe);
-               if (dev_priv->backlight.device)
-                       dev_priv->backlight.device->props.brightness =
-                               dev_priv->backlight.level;
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
+}
+
+static void i9xx_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, freq;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+       if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
+               WARN(1, "backlight already enabled\n");
+               I915_WRITE(BLC_PWM_CTL, 0);
        }
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+       ctl = freq << 17;
+       if (IS_GEN2(dev) && panel->backlight.combination_mode)
+               ctl |= BLM_LEGACY_MODE;
+       if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
+               ctl |= BLM_POLARITY_PNV;
 
-               tmp = I915_READ(reg);
+       I915_WRITE(BLC_PWM_CTL, ctl);
+       POSTING_READ(BLC_PWM_CTL);
 
-               /* Note that this can also get called through dpms changes. And
-                * we don't track the backlight dpms state, hence check whether
-                * we have to do anything first. */
-               if (tmp & BLM_PWM_ENABLE)
-                       goto set_level;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
+}
 
-               if (INTEL_INFO(dev)->num_pipes == 3)
-                       tmp &= ~BLM_PIPE_SELECT_IVB;
-               else
-                       tmp &= ~BLM_PIPE_SELECT;
+static void i965_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2, freq;
 
-               if (cpu_transcoder == TRANSCODER_EDP)
-                       tmp |= BLM_TRANSCODER_EDP;
-               else
-                       tmp |= BLM_PIPE(cpu_transcoder);
-               tmp &= ~BLM_PWM_ENABLE;
-
-               I915_WRITE(reg, tmp);
-               POSTING_READ(reg);
-               I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
-
-               if (IS_BROADWELL(dev)) {
-                       /*
-                        * Broadwell requires PCH override to drive the PCH
-                        * backlight pin. The above will configure the CPU
-                        * backlight pin, which we don't plan to use.
-                        */
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               } else if (HAS_PCH_SPLIT(dev) &&
-                   !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp |= BLM_PCH_PWM_ENABLE;
-                       tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CTL2, ctl2);
        }
 
-set_level:
-       /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
-        * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
-        * registers are set.
-        */
-       dev_priv->backlight.enabled = true;
-       intel_panel_actually_set_backlight(dev, pipe,
-                                          dev_priv->backlight.level);
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
+
+       ctl = freq << 16;
+       I915_WRITE(BLC_PWM_CTL, ctl);
+
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       ctl2 = BLM_PIPE(pipe);
+       if (panel->backlight.combination_mode)
+               ctl2 |= BLM_COMBINATION_MODE;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(BLC_PWM_CTL2, ctl2);
+       POSTING_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
 }
 
-/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
-static void intel_panel_init_backlight_regs(struct drm_device *dev)
+static void vlv_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2;
 
-       if (IS_VALLEYVIEW(dev)) {
-               enum pipe pipe;
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       }
 
-               for_each_pipe(pipe) {
-                       u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+       ctl = panel->backlight.max << 16;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
 
-                       /* Skip if the modulation freq is already set */
-                       if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
-                               continue;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-                       cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
-                                  cur_val);
-               }
-       }
+       ctl2 = 0;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
 }
 
-static void intel_panel_init_backlight(struct drm_device *dev)
+void intel_panel_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       unsigned long flags;
+
+       if (pipe == INVALID_PIPE)
+               return;
+
+       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+
+       WARN_ON(panel->backlight.max == 0);
+
+       if (panel->backlight.level == 0) {
+               panel->backlight.level = panel->backlight.max;
+               if (panel->backlight.device)
+                       panel->backlight.device->props.brightness =
+                               panel->backlight.level;
+       }
 
-       intel_panel_init_backlight_regs(dev);
+       dev_priv->display.enable_backlight(connector);
+       panel->backlight.enabled = true;
 
-       dev_priv->backlight.level = intel_panel_get_backlight(dev, 0);
-       dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
 
 enum drm_connector_status
@@ -762,7 +827,7 @@ intel_panel_detect(struct drm_device *dev)
 }
 
 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
-static int intel_panel_update_status(struct backlight_device *bd)
+static int intel_backlight_device_update_status(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
@@ -776,85 +841,362 @@ static int intel_panel_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int intel_panel_get_brightness(struct backlight_device *bd)
+static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
-       enum pipe pipe;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
+       intel_runtime_pm_get(dev_priv);
        mutex_lock(&dev->mode_config.mutex);
-       pipe = intel_get_pipe_from_connector(connector);
+       ret = intel_panel_get_backlight(connector);
        mutex_unlock(&dev->mode_config.mutex);
-       if (pipe == INVALID_PIPE)
-               return 0;
+       intel_runtime_pm_put(dev_priv);
 
-       return intel_panel_get_backlight(connector->base.dev, pipe);
+       return ret;
 }
 
-static const struct backlight_ops intel_panel_bl_ops = {
-       .update_status = intel_panel_update_status,
-       .get_brightness = intel_panel_get_brightness,
+static const struct backlight_ops intel_backlight_device_ops = {
+       .update_status = intel_backlight_device_update_status,
+       .get_brightness = intel_backlight_device_get_brightness,
 };
 
-int intel_panel_setup_backlight(struct drm_connector *connector)
+static int intel_backlight_device_register(struct intel_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        struct backlight_properties props;
-       unsigned long flags;
 
-       intel_panel_init_backlight(dev);
-
-       if (WARN_ON(dev_priv->backlight.device))
+       if (WARN_ON(panel->backlight.device))
                return -ENODEV;
 
+       BUG_ON(panel->backlight.max == 0);
+
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
-       props.brightness = dev_priv->backlight.level;
+       props.brightness = panel->backlight.level;
+       props.max_brightness = panel->backlight.max;
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-       props.max_brightness = intel_panel_get_max_backlight(dev, 0);
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
-       if (props.max_brightness == 0) {
-               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
-               return -ENODEV;
-       }
-       dev_priv->backlight.device =
+       /*
+        * Note: using the same name independent of the connector prevents
+        * registration of multiple backlight devices in the driver.
+        */
+       panel->backlight.device =
                backlight_device_register("intel_backlight",
-                                         connector->kdev,
-                                         to_intel_connector(connector),
-                                         &intel_panel_bl_ops, &props);
+                                         connector->base.kdev,
+                                         connector,
+                                         &intel_backlight_device_ops, &props);
 
-       if (IS_ERR(dev_priv->backlight.device)) {
+       if (IS_ERR(panel->backlight.device)) {
                DRM_ERROR("Failed to register backlight: %ld\n",
-                         PTR_ERR(dev_priv->backlight.device));
-               dev_priv->backlight.device = NULL;
+                         PTR_ERR(panel->backlight.device));
+               panel->backlight.device = NULL;
                return -ENODEV;
        }
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+       struct intel_panel *panel = &connector->panel;
+
+       if (panel->backlight.device) {
+               backlight_device_unregister(panel->backlight.device);
+               panel->backlight.device = NULL;
+       }
+}
+#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+static int intel_backlight_device_register(struct intel_connector *connector)
+{
+       return 0;
+}
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+}
+#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+/*
+ * Note: The setup hooks can't assume pipe is set!
+ *
+ * XXX: Query mode clock or hardware clock and program PWM modulation frequency
+ * appropriately when it's 0. Use VBT and/or sane defaults.
+ */
+static int bdw_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = bdw_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int pch_setup_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       if (dev_priv->backlight.device) {
-               backlight_device_unregister(dev_priv->backlight.device);
-               dev_priv->backlight.device = NULL;
+       struct intel_panel *panel = &connector->panel;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = pch_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
+               (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i9xx_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, val;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+
+       if (IS_GEN2(dev))
+               panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
+
+       if (IS_PINEVIEW(dev))
+               panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
+
+       panel->backlight.max = ctl >> 17;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i965_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, ctl2, val;
+
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+       panel->backlight.max = ctl >> 16;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int vlv_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe;
+       u32 ctl, ctl2, val;
+
+       for_each_pipe(pipe) {
+               u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+
+               /* Skip if the modulation freq is already set */
+               if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
+                       continue;
+
+               cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
+               I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
+                          cur_val);
        }
+
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
+       panel->backlight.max = ctl >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = _vlv_get_backlight(dev, PIPE_A);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
 }
-#else
+
 int intel_panel_setup_backlight(struct drm_connector *connector)
 {
-       intel_panel_init_backlight(connector->dev);
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+       unsigned long flags;
+       int ret;
+
+       /* set level and max in panel struct */
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+       ret = dev_priv->display.setup_backlight(intel_connector);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+
+       if (ret) {
+               DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
+                             drm_get_connector_name(connector));
+               return ret;
+       }
+
+       intel_backlight_device_register(intel_connector);
+
+       panel->backlight.present = true;
+
+       DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
+                     "sysfs interface %sregistered\n",
+                     panel->backlight.enabled ? "enabled" : "disabled",
+                     panel->backlight.level, panel->backlight.max,
+                     panel->backlight.device ? "" : "not ");
+
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+void intel_panel_destroy_backlight(struct drm_connector *connector)
+{
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+
+       panel->backlight.present = false;
+       intel_backlight_device_unregister(intel_connector);
+}
+
+/**
+ * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
+ * @dev: drm device
+ * @fixed_mode : panel native mode
+ * @connector: LVDS/eDP connector
+ *
+ * Return downclock_avail
+ * Find the reduced downclock for LVDS/eDP in EDID.
+ */
+struct drm_display_mode *
+intel_find_panel_downclock(struct drm_device *dev,
+                       struct drm_display_mode *fixed_mode,
+                       struct drm_connector *connector)
+{
+       struct drm_display_mode *scan, *tmp_mode;
+       int temp_downclock;
+
+       temp_downclock = fixed_mode->clock;
+       tmp_mode = NULL;
+
+       list_for_each_entry(scan, &connector->probed_modes, head) {
+               /*
+                * If one mode has the same resolution with the fixed_panel
+                * mode while they have the different refresh rate, it means
+                * that the reduced downclock is found. In such
+                * case we can set the different FPx0/1 to dynamically select
+                * between low and high frequency.
+                */
+               if (scan->hdisplay == fixed_mode->hdisplay &&
+                   scan->hsync_start == fixed_mode->hsync_start &&
+                   scan->hsync_end == fixed_mode->hsync_end &&
+                   scan->htotal == fixed_mode->htotal &&
+                   scan->vdisplay == fixed_mode->vdisplay &&
+                   scan->vsync_start == fixed_mode->vsync_start &&
+                   scan->vsync_end == fixed_mode->vsync_end &&
+                   scan->vtotal == fixed_mode->vtotal) {
+                       if (scan->clock < temp_downclock) {
+                               /*
+                                * The downclock is already found. But we
+                                * expect to find the lower downclock.
+                                */
+                               temp_downclock = scan->clock;
+                               tmp_mode = scan;
+                       }
+               }
+       }
+
+       if (temp_downclock < fixed_mode->clock)
+               return drm_mode_duplicate(dev, tmp_mode);
+       else
+               return NULL;
+}
+
+/* Set up chip specific backlight functions */
+void intel_panel_init_backlight_funcs(struct drm_device *dev)
 {
-       return;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_BROADWELL(dev)) {
+               dev_priv->display.setup_backlight = bdw_setup_backlight;
+               dev_priv->display.enable_backlight = bdw_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = bdw_set_backlight;
+               dev_priv->display.get_backlight = bdw_get_backlight;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->display.setup_backlight = pch_setup_backlight;
+               dev_priv->display.enable_backlight = pch_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = pch_set_backlight;
+               dev_priv->display.get_backlight = pch_get_backlight;
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.setup_backlight = vlv_setup_backlight;
+               dev_priv->display.enable_backlight = vlv_enable_backlight;
+               dev_priv->display.disable_backlight = vlv_disable_backlight;
+               dev_priv->display.set_backlight = vlv_set_backlight;
+               dev_priv->display.get_backlight = vlv_get_backlight;
+       } else if (IS_GEN4(dev)) {
+               dev_priv->display.setup_backlight = i965_setup_backlight;
+               dev_priv->display.enable_backlight = i965_enable_backlight;
+               dev_priv->display.disable_backlight = i965_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       } else {
+               dev_priv->display.setup_backlight = i9xx_setup_backlight;
+               dev_priv->display.enable_backlight = i9xx_enable_backlight;
+               dev_priv->display.disable_backlight = i9xx_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       }
 }
-#endif
 
 int intel_panel_init(struct intel_panel *panel,
                     struct drm_display_mode *fixed_mode)
@@ -871,4 +1213,8 @@ void intel_panel_fini(struct intel_panel *panel)
 
        if (panel->fixed_mode)
                drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
+
+       if (panel->downclock_mode)
+               drm_mode_destroy(intel_connector->base.dev,
+                               panel->downclock_mode);
 }
index 26c29c173221058aeeaa9a3c0d889500b8db9fec..d77cc81900f92100ba2f61d7130bc9b0b60454b5 100644 (file)
@@ -30,7 +30,9 @@
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
+#include <linux/vgaarb.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -86,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev)
        DRM_DEBUG_KMS("disabled FBC\n");
 }
 
-static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void i8xx_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -96,32 +98,40 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int cfb_pitch;
        int plane, i;
-       u32 fbc_ctl, fbc_ctl2;
+       u32 fbc_ctl;
 
        cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
        if (fb->pitches[0] < cfb_pitch)
                cfb_pitch = fb->pitches[0];
 
-       /* FBC_CTL wants 64B units */
-       cfb_pitch = (cfb_pitch / 64) - 1;
+       /* FBC_CTL wants 32B or 64B units */
+       if (IS_GEN2(dev))
+               cfb_pitch = (cfb_pitch / 32) - 1;
+       else
+               cfb_pitch = (cfb_pitch / 64) - 1;
        plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
        /* Clear old tags */
        for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
                I915_WRITE(FBC_TAG + (i * 4), 0);
 
-       /* Set it up... */
-       fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
-       fbc_ctl2 |= plane;
-       I915_WRITE(FBC_CONTROL2, fbc_ctl2);
-       I915_WRITE(FBC_FENCE_OFF, crtc->y);
+       if (IS_GEN4(dev)) {
+               u32 fbc_ctl2;
+
+               /* Set it up... */
+               fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
+               fbc_ctl2 |= plane;
+               I915_WRITE(FBC_CONTROL2, fbc_ctl2);
+               I915_WRITE(FBC_FENCE_OFF, crtc->y);
+       }
 
        /* enable it... */
-       fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
+       fbc_ctl = I915_READ(FBC_CONTROL);
+       fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
+       fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
        if (IS_I945GM(dev))
                fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
        fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
-       fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
        fbc_ctl |= obj->fence_reg;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 
@@ -136,7 +146,7 @@ static bool i8xx_fbc_enabled(struct drm_device *dev)
        return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
 }
 
-static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void g4x_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -145,16 +155,12 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
-       unsigned long stall_watermark = 200;
        u32 dpfc_ctl;
 
        dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
        dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
        I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 
-       I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
-                  (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
-                  (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
        I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
 
        /* enable it... */
@@ -191,7 +197,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
        u32 blt_ecoskpd;
 
        /* Make sure blitter notifies FBC of writes */
-       gen6_gt_force_wake_get(dev_priv);
+
+       /* Blitter is part of Media powerwell on VLV. No impact of
+        * his param in other platforms for now */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA);
+
        blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
        blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
                GEN6_BLITTER_LOCK_SHIFT;
@@ -202,10 +212,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
                         GEN6_BLITTER_LOCK_SHIFT);
        I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
        POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       gen6_gt_force_wake_put(dev_priv);
+
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
 }
 
-static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void ironlake_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -214,7 +225,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
-       unsigned long stall_watermark = 200;
        u32 dpfc_ctl;
 
        dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
@@ -222,12 +232,11 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
        /* Set persistent mode for front-buffer rendering, ala X. */
        dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
-       dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+       dpfc_ctl |= DPFC_CTL_FENCE_EN;
+       if (IS_GEN5(dev))
+               dpfc_ctl |= obj->fence_reg;
        I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
-       I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
-                  (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
-                  (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
        I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
        I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
        /* enable it... */
@@ -265,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
        return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
-static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void gen7_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -295,7 +304,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
        sandybridge_blit_fbc_update(dev);
 
-       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+       DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
 }
 
 bool intel_fbc_enabled(struct drm_device *dev)
@@ -322,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
                 * the prior work.
                 */
                if (work->crtc->fb == work->fb) {
-                       dev_priv->display.enable_fbc(work->crtc,
-                                                    work->interval);
+                       dev_priv->display.enable_fbc(work->crtc);
 
                        dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
                        dev_priv->fbc.fb_id = work->crtc->fb->base.id;
@@ -360,7 +368,7 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
        dev_priv->fbc.fbc_work = NULL;
 }
 
-static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_enable_fbc(struct drm_crtc *crtc)
 {
        struct intel_fbc_work *work;
        struct drm_device *dev = crtc->dev;
@@ -374,13 +382,12 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        work = kzalloc(sizeof(*work), GFP_KERNEL);
        if (work == NULL) {
                DRM_ERROR("Failed to allocate FBC work structure\n");
-               dev_priv->display.enable_fbc(crtc, interval);
+               dev_priv->display.enable_fbc(crtc);
                return;
        }
 
        work->crtc = crtc;
        work->fb = crtc->fb;
-       work->interval = interval;
        INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
        dev_priv->fbc.fbc_work = work;
@@ -454,7 +461,7 @@ void intel_update_fbc(struct drm_device *dev)
        const struct drm_display_mode *adjusted_mode;
        unsigned int max_width, max_height;
 
-       if (!I915_HAS_FBC(dev)) {
+       if (!HAS_FBC(dev)) {
                set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED);
                return;
        }
@@ -530,10 +537,10 @@ void intel_update_fbc(struct drm_device *dev)
                        DRM_DEBUG_KMS("mode too large for compression, disabling\n");
                goto out_disable;
        }
-       if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
-           intel_crtc->plane != 0) {
+       if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) &&
+           intel_crtc->plane != PLANE_A) {
                if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
-                       DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+                       DRM_DEBUG_KMS("plane not A, disabling compression\n");
                goto out_disable;
        }
 
@@ -595,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev)
                intel_disable_fbc(dev);
        }
 
-       intel_enable_fbc(crtc, 500);
+       intel_enable_fbc(crtc);
        dev_priv->fbc.no_fbc_reason = FBC_OK;
        return;
 
@@ -817,7 +824,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
        return size;
 }
 
-static int i85x_get_fifo_size(struct drm_device *dev, int plane)
+static int i830_get_fifo_size(struct drm_device *dev, int plane)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t dsparb = I915_READ(DSPARB);
@@ -850,21 +857,6 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane)
        return size;
 }
 
-static int i830_get_fifo_size(struct drm_device *dev, int plane)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dsparb = I915_READ(DSPARB);
-       int size;
-
-       size = dsparb & 0x7f;
-       size >>= 1; /* Convert to cachelines */
-
-       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
-                     plane ? "B" : "A", size);
-
-       return size;
-}
-
 /* Pineview has different values for various configs */
 static const struct intel_watermark_params pineview_display_wm = {
        PINEVIEW_DISPLAY_FIFO,
@@ -943,14 +935,14 @@ static const struct intel_watermark_params i915_wm_info = {
        2,
        I915_FIFO_LINE_SIZE
 };
-static const struct intel_watermark_params i855_wm_info = {
+static const struct intel_watermark_params i830_wm_info = {
        I855GM_FIFO_SIZE,
        I915_MAX_WM,
        1,
        2,
        I830_FIFO_LINE_SIZE
 };
-static const struct intel_watermark_params i830_wm_info = {
+static const struct intel_watermark_params i845_wm_info = {
        I830_FIFO_SIZE,
        I915_MAX_WM,
        1,
@@ -958,65 +950,6 @@ static const struct intel_watermark_params i830_wm_info = {
        I830_FIFO_LINE_SIZE
 };
 
-static const struct intel_watermark_params ironlake_display_wm_info = {
-       ILK_DISPLAY_FIFO,
-       ILK_DISPLAY_MAXWM,
-       ILK_DISPLAY_DFTWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_cursor_wm_info = {
-       ILK_CURSOR_FIFO,
-       ILK_CURSOR_MAXWM,
-       ILK_CURSOR_DFTWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_display_srwm_info = {
-       ILK_DISPLAY_SR_FIFO,
-       ILK_DISPLAY_MAX_SRWM,
-       ILK_DISPLAY_DFT_SRWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_cursor_srwm_info = {
-       ILK_CURSOR_SR_FIFO,
-       ILK_CURSOR_MAX_SRWM,
-       ILK_CURSOR_DFT_SRWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-
-static const struct intel_watermark_params sandybridge_display_wm_info = {
-       SNB_DISPLAY_FIFO,
-       SNB_DISPLAY_MAXWM,
-       SNB_DISPLAY_DFTWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_cursor_wm_info = {
-       SNB_CURSOR_FIFO,
-       SNB_CURSOR_MAXWM,
-       SNB_CURSOR_DFTWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_display_srwm_info = {
-       SNB_DISPLAY_SR_FIFO,
-       SNB_DISPLAY_MAX_SRWM,
-       SNB_DISPLAY_DFT_SRWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_cursor_srwm_info = {
-       SNB_CURSOR_SR_FIFO,
-       SNB_CURSOR_MAX_SRWM,
-       SNB_CURSOR_DFT_SRWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-
-
 /**
  * intel_calculate_wm - calculate watermark level
  * @clock_in_khz: pixel clock
@@ -1567,7 +1500,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        else if (!IS_GEN2(dev))
                wm_info = &i915_wm_info;
        else
-               wm_info = &i855_wm_info;
+               wm_info = &i830_wm_info;
 
        fifo_size = dev_priv->display.get_fifo_size(dev, 0);
        crtc = intel_get_crtc_for_plane(dev, 0);
@@ -1615,7 +1548,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        if (IS_I945G(dev) || IS_I945GM(dev))
                I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
        else if (IS_I915GM(dev))
-               I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
+               I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_SELF_EN));
 
        /* Calc sr entries for one plane configs */
        if (HAS_FW_BLC(dev) && enabled) {
@@ -1667,14 +1600,14 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                                I915_WRITE(FW_BLC_SELF,
                                           FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
                        else if (IS_I915GM(dev))
-                               I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
+                               I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_SELF_EN));
                        DRM_DEBUG_KMS("memory self refresh enabled\n");
                } else
                        DRM_DEBUG_KMS("memory self refresh disabled\n");
        }
 }
 
-static void i830_update_wm(struct drm_crtc *unused_crtc)
+static void i845_update_wm(struct drm_crtc *unused_crtc)
 {
        struct drm_device *dev = unused_crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1689,7 +1622,7 @@ static void i830_update_wm(struct drm_crtc *unused_crtc)
 
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
-                                      &i830_wm_info,
+                                      &i845_wm_info,
                                       dev_priv->display.get_fifo_size(dev, 0),
                                       4, latency_ns);
        fwater_lo = I915_READ(FW_BLC) & ~0xfff;
@@ -1700,423 +1633,6 @@ static void i830_update_wm(struct drm_crtc *unused_crtc)
        I915_WRITE(FW_BLC, fwater_lo);
 }
 
-/*
- * Check the wm result.
- *
- * If any calculated watermark values is larger than the maximum value that
- * can be programmed into the associated watermark register, that watermark
- * must be disabled.
- */
-static bool ironlake_check_srwm(struct drm_device *dev, int level,
-                               int fbc_wm, int display_wm, int cursor_wm,
-                               const struct intel_watermark_params *display,
-                               const struct intel_watermark_params *cursor)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d,"
-                     " cursor %d\n", level, display_wm, fbc_wm, cursor_wm);
-
-       if (fbc_wm > SNB_FBC_MAX_SRWM) {
-               DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
-                             fbc_wm, SNB_FBC_MAX_SRWM, level);
-
-               /* fbc has it's own way to disable FBC WM */
-               I915_WRITE(DISP_ARB_CTL,
-                          I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
-               return false;
-       } else if (INTEL_INFO(dev)->gen >= 6) {
-               /* enable FBC WM (except on ILK, where it must remain off) */
-               I915_WRITE(DISP_ARB_CTL,
-                          I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS);
-       }
-
-       if (display_wm > display->max_wm) {
-               DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
-                             display_wm, SNB_DISPLAY_MAX_SRWM, level);
-               return false;
-       }
-
-       if (cursor_wm > cursor->max_wm) {
-               DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
-                             cursor_wm, SNB_CURSOR_MAX_SRWM, level);
-               return false;
-       }
-
-       if (!(fbc_wm || display_wm || cursor_wm)) {
-               DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
-               return false;
-       }
-
-       return true;
-}
-
-/*
- * Compute watermark values of WM[1-3],
- */
-static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
-                                 int latency_ns,
-                                 const struct intel_watermark_params *display,
-                                 const struct intel_watermark_params *cursor,
-                                 int *fbc_wm, int *display_wm, int *cursor_wm)
-{
-       struct drm_crtc *crtc;
-       const struct drm_display_mode *adjusted_mode;
-       unsigned long line_time_us;
-       int hdisplay, htotal, pixel_size, clock;
-       int line_count, line_size;
-       int small, large;
-       int entries;
-
-       if (!latency_ns) {
-               *fbc_wm = *display_wm = *cursor_wm = 0;
-               return false;
-       }
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
-       clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->crtc_htotal;
-       hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
-
-       line_time_us = (htotal * 1000) / clock;
-       line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = hdisplay * pixel_size;
-
-       /* Use the minimum of the small and large buffer method for primary */
-       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-       large = line_count * line_size;
-
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *display_wm = entries + display->guard_size;
-
-       /*
-        * Spec says:
-        * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
-        */
-       *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
-
-       /* calculate the self-refresh watermark for display cursor */
-       entries = line_count * pixel_size * 64;
-       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
-       *cursor_wm = entries + cursor->guard_size;
-
-       return ironlake_check_srwm(dev, level,
-                                  *fbc_wm, *display_wm, *cursor_wm,
-                                  display, cursor);
-}
-
-static void ironlake_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int fbc_wm, plane_wm, cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &ironlake_display_wm_info,
-                           dev_priv->wm.pri_latency[0] * 100,
-                           &ironlake_cursor_wm_info,
-                           dev_priv->wm.cur_latency[0] * 100,
-                           &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEA_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &ironlake_display_wm_info,
-                           dev_priv->wm.pri_latency[0] * 100,
-                           &ironlake_cursor_wm_info,
-                           dev_priv->wm.cur_latency[0] * 100,
-                           &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEB_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled))
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &ironlake_display_srwm_info,
-                                  &ironlake_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &ironlake_display_srwm_info,
-                                  &ironlake_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /*
-        * WM3 is unsupported on ILK, probably because we don't have latency
-        * data for that power state
-        */
-}
-
-static void sandybridge_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = dev_priv->wm.pri_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int fbc_wm, plane_wm, cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEA_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEA_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEB_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEB_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        *
-        * SNB support 3 levels of watermark.
-        *
-        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-        * and disabled in the descending order
-        *
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled) ||
-           dev_priv->sprite_scaling_enabled)
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM3 */
-       if (!ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.pri_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM3_LP_ILK,
-                  WM3_LP_EN |
-                  (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-}
-
-static void ivybridge_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = dev_priv->wm.pri_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int fbc_wm, plane_wm, cursor_wm;
-       int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEA_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEA_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEB_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEB_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_C,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEC_IVB);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEC_IVB, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_C;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        *
-        * SNB support 3 levels of watermark.
-        *
-        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-        * and disabled in the descending order
-        *
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled) ||
-           dev_priv->sprite_scaling_enabled)
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM3, note we have to correct the cursor latency */
-       if (!ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.pri_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
-           !ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.cur_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM3_LP_ILK,
-                  WM3_LP_EN |
-                  (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-}
-
 static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
                                    struct drm_crtc *crtc)
 {
@@ -2185,7 +1701,7 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
        return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
 }
 
-struct hsw_pipe_wm_parameters {
+struct ilk_pipe_wm_parameters {
        bool active;
        uint32_t pipe_htotal;
        uint32_t pixel_rate;
@@ -2194,7 +1710,7 @@ struct hsw_pipe_wm_parameters {
        struct intel_plane_wm_parameters cur;
 };
 
-struct hsw_wm_maximums {
+struct ilk_wm_maximums {
        uint16_t pri;
        uint16_t spr;
        uint16_t cur;
@@ -2212,7 +1728,7 @@ struct intel_wm_config {
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_pri_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value,
                                   bool is_lp)
 {
@@ -2241,7 +1757,7 @@ static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_spr_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value)
 {
        uint32_t method1, method2;
@@ -2264,7 +1780,7 @@ static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_cur_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value)
 {
        if (!params->active || !params->cur.enabled)
@@ -2278,7 +1794,7 @@ static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params,
 }
 
 /* Only for WM_LP. */
-static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_fbc_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t pri_val)
 {
        if (!params->active || !params->pri.enabled)
@@ -2383,7 +1899,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
                                    int level,
                                    const struct intel_wm_config *config,
                                    enum intel_ddb_partitioning ddb_partitioning,
-                                   struct hsw_wm_maximums *max)
+                                   struct ilk_wm_maximums *max)
 {
        max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
        max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
@@ -2392,7 +1908,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
 }
 
 static bool ilk_validate_wm_level(int level,
-                                 const struct hsw_wm_maximums *max,
+                                 const struct ilk_wm_maximums *max,
                                  struct intel_wm_level *result)
 {
        bool ret;
@@ -2434,7 +1950,7 @@ static bool ilk_validate_wm_level(int level,
 
 static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
                                 int level,
-                                const struct hsw_pipe_wm_parameters *p,
+                                const struct ilk_pipe_wm_parameters *p,
                                 struct intel_wm_level *result)
 {
        uint16_t pri_latency = dev_priv->wm.pri_latency[level];
@@ -2482,7 +1998,7 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_HASWELL(dev)) {
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                uint64_t sskpd = I915_READ64(MCH_SSKPD);
 
                wm[0] = (sskpd >> 56) & 0xFF;
@@ -2530,7 +2046,7 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
 static int ilk_wm_max_level(const struct drm_device *dev)
 {
        /* how many WM levels are we expecting */
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                return 4;
        else if (INTEL_INFO(dev)->gen >= 6)
                return 3;
@@ -2582,8 +2098,8 @@ static void intel_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
 }
 
-static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
-                                     struct hsw_pipe_wm_parameters *p,
+static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
+                                     struct ilk_pipe_wm_parameters *p,
                                      struct intel_wm_config *config)
 {
        struct drm_device *dev = crtc->dev;
@@ -2593,7 +2109,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 
        p->active = intel_crtc_active(crtc);
        if (p->active) {
-               p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
+               p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
                p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
                p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
                p->cur.bytes_per_pixel = 4;
@@ -2620,7 +2136,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 
 /* Compute new watermarks for the pipe */
 static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
-                                 const struct hsw_pipe_wm_parameters *params,
+                                 const struct ilk_pipe_wm_parameters *params,
                                  struct intel_pipe_wm *pipe_wm)
 {
        struct drm_device *dev = crtc->dev;
@@ -2632,16 +2148,25 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
                .sprites_enabled = params->spr.enabled,
                .sprites_scaled = params->spr.scaled,
        };
-       struct hsw_wm_maximums max;
+       struct ilk_wm_maximums max;
 
        /* LP0 watermarks always use 1/2 DDB partitioning */
        ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
+       /* ILK/SNB: LP2+ watermarks only w/o sprites */
+       if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
+               max_level = 1;
+
+       /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
+       if (params->spr.scaled)
+               max_level = 0;
+
        for (level = 0; level <= max_level; level++)
                ilk_compute_wm_level(dev_priv, level, params,
                                     &pipe_wm->wm[level]);
 
-       pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
        /* At least LP0 must be valid */
        return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
@@ -2676,12 +2201,19 @@ static void ilk_merge_wm_level(struct drm_device *dev,
  * Merge all low power watermarks for all active pipes.
  */
 static void ilk_wm_merge(struct drm_device *dev,
-                        const struct hsw_wm_maximums *max,
+                        const struct intel_wm_config *config,
+                        const struct ilk_wm_maximums *max,
                         struct intel_pipe_wm *merged)
 {
        int level, max_level = ilk_wm_max_level(dev);
 
-       merged->fbc_wm_enabled = true;
+       /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
+       if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
+           config->num_pipes_active > 1)
+               return;
+
+       /* ILK: FBC WM must be disabled always */
+       merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
 
        /* merge each WM1+ level */
        for (level = 1; level <= max_level; level++) {
@@ -2701,6 +2233,20 @@ static void ilk_wm_merge(struct drm_device *dev,
                        wm->fbc_val = 0;
                }
        }
+
+       /* ILK: LP2+ must be disabled when FBC WM is disabled but FBC enabled */
+       /*
+        * FIXME this is racy. FBC might get enabled later.
+        * What we should check here is whether FBC can be
+        * enabled sometime later.
+        */
+       if (IS_GEN5(dev) && !merged->fbc_wm_enabled && intel_fbc_enabled(dev)) {
+               for (level = 2; level <= max_level; level++) {
+                       struct intel_wm_level *wm = &merged->wm[level];
+
+                       wm->enable = false;
+               }
+       }
 }
 
 static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
@@ -2709,10 +2255,21 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
        return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable);
 }
 
-static void hsw_compute_wm_results(struct drm_device *dev,
+/* The value we need to program into the WM_LPx latency field */
+static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               return 2 * level;
+       else
+               return dev_priv->wm.pri_latency[level];
+}
+
+static void ilk_compute_wm_results(struct drm_device *dev,
                                   const struct intel_pipe_wm *merged,
                                   enum intel_ddb_partitioning partitioning,
-                                  struct hsw_wm_values *results)
+                                  struct ilk_wm_values *results)
 {
        struct intel_crtc *intel_crtc;
        int level, wm_lp;
@@ -2731,7 +2288,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
                        break;
 
                results->wm_lp[wm_lp - 1] = WM3_LP_EN |
-                       ((level * 2) << WM1_LP_LATENCY_SHIFT) |
+                       (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
                        (r->pri_val << WM1_LP_SR_SHIFT) |
                        r->cur_val;
 
@@ -2742,7 +2299,11 @@ static void hsw_compute_wm_results(struct drm_device *dev,
                        results->wm_lp[wm_lp - 1] |=
                                r->fbc_val << WM1_LP_FBC_SHIFT;
 
-               results->wm_lp_spr[wm_lp - 1] = r->spr_val;
+               if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
+                       WARN_ON(wm_lp != 1);
+                       results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
+               } else
+                       results->wm_lp_spr[wm_lp - 1] = r->spr_val;
        }
 
        /* LP0 register values */
@@ -2765,7 +2326,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 
 /* Find the result with the highest level enabled. Check for enable_fbc_wm in
  * case both are at the same level. Prefer r1 in case they're the same. */
-static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
+static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
                                                  struct intel_pipe_wm *r1,
                                                  struct intel_pipe_wm *r2)
 {
@@ -2800,8 +2361,8 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
 #define WM_DIRTY_DDB (1 << 25)
 
 static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
-                                        const struct hsw_wm_values *old,
-                                        const struct hsw_wm_values *new)
+                                        const struct ilk_wm_values *old,
+                                        const struct ilk_wm_values *new)
 {
        unsigned int dirty = 0;
        enum pipe pipe;
@@ -2851,27 +2412,53 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
        return dirty;
 }
 
+static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
+                              unsigned int dirty)
+{
+       struct ilk_wm_values *previous = &dev_priv->wm.hw;
+       bool changed = false;
+
+       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM1_LP_SR_EN) {
+               previous->wm_lp[2] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM3_LP_ILK, previous->wm_lp[2]);
+               changed = true;
+       }
+       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] & WM1_LP_SR_EN) {
+               previous->wm_lp[1] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM2_LP_ILK, previous->wm_lp[1]);
+               changed = true;
+       }
+       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] & WM1_LP_SR_EN) {
+               previous->wm_lp[0] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM1_LP_ILK, previous->wm_lp[0]);
+               changed = true;
+       }
+
+       /*
+        * Don't touch WM1S_LP_EN here.
+        * Doing so could cause underruns.
+        */
+
+       return changed;
+}
+
 /*
  * The spec says we shouldn't write when we don't need, because every write
  * causes WMs to be re-evaluated, expending some power.
  */
-static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
-                               struct hsw_wm_values *results)
+static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
+                               struct ilk_wm_values *results)
 {
-       struct hsw_wm_values *previous = &dev_priv->wm.hw;
+       struct drm_device *dev = dev_priv->dev;
+       struct ilk_wm_values *previous = &dev_priv->wm.hw;
        unsigned int dirty;
        uint32_t val;
 
-       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
+       dirty = ilk_compute_wm_dirty(dev, previous, results);
        if (!dirty)
                return;
 
-       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
-               I915_WRITE(WM3_LP_ILK, 0);
-       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
-               I915_WRITE(WM2_LP_ILK, 0);
-       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
-               I915_WRITE(WM1_LP_ILK, 0);
+       _ilk_disable_lp_wm(dev_priv, dirty);
 
        if (dirty & WM_DIRTY_PIPE(PIPE_A))
                I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
@@ -2888,12 +2475,21 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
                I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
        if (dirty & WM_DIRTY_DDB) {
-               val = I915_READ(WM_MISC);
-               if (results->partitioning == INTEL_DDB_PART_1_2)
-                       val &= ~WM_MISC_DATA_PARTITION_5_6;
-               else
-                       val |= WM_MISC_DATA_PARTITION_5_6;
-               I915_WRITE(WM_MISC, val);
+               if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+                       val = I915_READ(WM_MISC);
+                       if (results->partitioning == INTEL_DDB_PART_1_2)
+                               val &= ~WM_MISC_DATA_PARTITION_5_6;
+                       else
+                               val |= WM_MISC_DATA_PARTITION_5_6;
+                       I915_WRITE(WM_MISC, val);
+               } else {
+                       val = I915_READ(DISP_ARB_CTL2);
+                       if (results->partitioning == INTEL_DDB_PART_1_2)
+                               val &= ~DISP_DATA_PARTITION_5_6;
+                       else
+                               val |= DISP_DATA_PARTITION_5_6;
+                       I915_WRITE(DISP_ARB_CTL2, val);
+               }
        }
 
        if (dirty & WM_DIRTY_FBC) {
@@ -2905,37 +2501,48 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
                I915_WRITE(DISP_ARB_CTL, val);
        }
 
-       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
+       if (dirty & WM_DIRTY_LP(1) &&
+           previous->wm_lp_spr[0] != results->wm_lp_spr[0])
                I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
-               I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
-               I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
-       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
+       if (INTEL_INFO(dev)->gen >= 7) {
+               if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
+                       I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
+               if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
+                       I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
+       }
+
+       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != results->wm_lp[0])
                I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
-       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
+       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != results->wm_lp[1])
                I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
-       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
+       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
                I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 
        dev_priv->wm.hw = *results;
 }
 
-static void haswell_update_wm(struct drm_crtc *crtc)
+static bool ilk_disable_lp_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
+}
+
+static void ilk_update_wm(struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_maximums max;
-       struct hsw_pipe_wm_parameters params = {};
-       struct hsw_wm_values results = {};
+       struct ilk_wm_maximums max;
+       struct ilk_pipe_wm_parameters params = {};
+       struct ilk_wm_values results = {};
        enum intel_ddb_partitioning partitioning;
        struct intel_pipe_wm pipe_wm = {};
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct intel_wm_config config = {};
 
-       hsw_compute_wm_parameters(crtc, &params, &config);
+       ilk_compute_wm_parameters(crtc, &params, &config);
 
        intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
@@ -2945,15 +2552,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
        intel_crtc->wm.active = pipe_wm;
 
        ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
-       ilk_wm_merge(dev, &max, &lp_wm_1_2);
+       ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
        if (INTEL_INFO(dev)->gen >= 7 &&
            config.num_pipes_active == 1 && config.sprites_enabled) {
                ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
-               ilk_wm_merge(dev, &max, &lp_wm_5_6);
+               ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
 
-               best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
+               best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
        } else {
                best_lp_wm = &lp_wm_1_2;
        }
@@ -2961,193 +2568,42 @@ static void haswell_update_wm(struct drm_crtc *crtc)
        partitioning = (best_lp_wm == &lp_wm_1_2) ?
                       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
-       hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results);
+       ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
 
-       hsw_write_wm_values(dev_priv, &results);
+       ilk_write_wm_values(dev_priv, &results);
 }
 
-static void haswell_update_sprite_wm(struct drm_plane *plane,
+static void ilk_update_sprite_wm(struct drm_plane *plane,
                                     struct drm_crtc *crtc,
                                     uint32_t sprite_width, int pixel_size,
                                     bool enabled, bool scaled)
-{
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-
-       intel_plane->wm.enabled = enabled;
-       intel_plane->wm.scaled = scaled;
-       intel_plane->wm.horiz_pixels = sprite_width;
-       intel_plane->wm.bytes_per_pixel = pixel_size;
-
-       haswell_update_wm(crtc);
-}
-
-static bool
-sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
-                             uint32_t sprite_width, int pixel_size,
-                             const struct intel_watermark_params *display,
-                             int display_latency_ns, int *sprite_wm)
-{
-       struct drm_crtc *crtc;
-       int clock;
-       int entries, tlb_miss;
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       if (!intel_crtc_active(crtc)) {
-               *sprite_wm = display->guard_size;
-               return false;
-       }
-
-       clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-
-       /* Use the small buffer method to calculate the sprite watermark */
-       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
-       tlb_miss = display->fifo_size*display->cacheline_size -
-               sprite_width * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, display->cacheline_size);
-       *sprite_wm = entries + display->guard_size;
-       if (*sprite_wm > (int)display->max_wm)
-               *sprite_wm = display->max_wm;
-
-       return true;
-}
-
-static bool
-sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
-                               uint32_t sprite_width, int pixel_size,
-                               const struct intel_watermark_params *display,
-                               int latency_ns, int *sprite_wm)
-{
-       struct drm_crtc *crtc;
-       unsigned long line_time_us;
-       int clock;
-       int line_count, line_size;
-       int small, large;
-       int entries;
-
-       if (!latency_ns) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-       if (!clock) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       line_time_us = (sprite_width * 1000) / clock;
-       if (!line_time_us) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = sprite_width * pixel_size;
-
-       /* Use the minimum of the small and large buffer method for primary */
-       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-       large = line_count * line_size;
-
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *sprite_wm = entries + display->guard_size;
-
-       return *sprite_wm > 0x3ff ? false : true;
-}
-
-static void sandybridge_update_sprite_wm(struct drm_plane *plane,
-                                        struct drm_crtc *crtc,
-                                        uint32_t sprite_width, int pixel_size,
-                                        bool enabled, bool scaled)
 {
        struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe = to_intel_plane(plane)->pipe;
-       int latency = dev_priv->wm.spr_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int sprite_wm, reg;
-       int ret;
-
-       if (!enabled)
-               return;
-
-       switch (pipe) {
-       case 0:
-               reg = WM0_PIPEA_ILK;
-               break;
-       case 1:
-               reg = WM0_PIPEB_ILK;
-               break;
-       case 2:
-               reg = WM0_PIPEC_IVB;
-               break;
-       default:
-               return; /* bad pipe */
-       }
-
-       ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size,
-                                           &sandybridge_display_wm_info,
-                                           latency, &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-
-       val = I915_READ(reg);
-       val &= ~WM0_PIPE_SPRITE_MASK;
-       I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
-       DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm);
-
-
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[1] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM1S_LP_ILK, sprite_wm);
+       struct intel_plane *intel_plane = to_intel_plane(plane);
 
-       /* Only IVB has two more LP watermarks for sprite */
-       if (!IS_IVYBRIDGE(dev))
-               return;
+       intel_plane->wm.enabled = enabled;
+       intel_plane->wm.scaled = scaled;
+       intel_plane->wm.horiz_pixels = sprite_width;
+       intel_plane->wm.bytes_per_pixel = pixel_size;
 
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[2] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM2S_LP_IVB, sprite_wm);
+       /*
+        * IVB workaround: must disable low power watermarks for at least
+        * one frame before enabling scaling.  LP watermarks can be re-enabled
+        * when scaling is disabled.
+        *
+        * WaCxSRDisabledForSpriteScaling:ivb
+        */
+       if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
+               intel_wait_for_vblank(dev, intel_plane->pipe);
 
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[3] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM3S_LP_IVB, sprite_wm);
+       ilk_update_wm(crtc);
 }
 
 static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_values *hw = &dev_priv->wm.hw;
+       struct ilk_wm_values *hw = &dev_priv->wm.hw;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_pipe_wm *active = &intel_crtc->wm.active;
        enum pipe pipe = intel_crtc->pipe;
@@ -3158,7 +2614,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
        };
 
        hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
-       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
        if (intel_crtc_active(crtc)) {
                u32 tmp = hw->wm_pipe[pipe];
@@ -3190,7 +2647,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 void ilk_wm_get_hw_state(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_values *hw = &dev_priv->wm.hw;
+       struct ilk_wm_values *hw = &dev_priv->wm.hw;
        struct drm_crtc *crtc;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
@@ -3204,8 +2661,12 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
        hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
        hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
 
-       hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
+                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+       else if (IS_IVYBRIDGE(dev))
+               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
+                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
        hw->enable_fbc_wm =
                !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
@@ -3430,26 +2891,19 @@ static void ironlake_disable_drps(struct drm_device *dev)
  * ourselves, instead of doing a rmw cycle (which might result in us clearing
  * all limits and the gpu stuck at whatever frequency it is at atm).
  */
-static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val)
+static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 {
        u32 limits;
 
-       limits = 0;
-
-       if (*val >= dev_priv->rps.max_delay)
-               *val = dev_priv->rps.max_delay;
-       limits |= dev_priv->rps.max_delay << 24;
-
        /* Only set the down limit when we've reached the lowest level to avoid
         * getting more interrupts, otherwise leave this clear. This prevents a
         * race in the hw when coming out of rc6: There's a tiny window where
         * the hw runs at the minimal clock before selecting the desired
         * frequency, if the down threshold expires in that window we will not
         * receive a down interrupt. */
-       if (*val <= dev_priv->rps.min_delay) {
-               *val = dev_priv->rps.min_delay;
+       limits = dev_priv->rps.max_delay << 24;
+       if (val <= dev_priv->rps.min_delay)
                limits |= dev_priv->rps.min_delay << 16;
-       }
 
        return limits;
 }
@@ -3549,7 +3003,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 limits = gen6_rps_limits(dev_priv, &val);
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
@@ -3572,7 +3025,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
        /* Make sure we continue to get interrupts
         * until we hit the minimum or maximum frequencies.
         */
-       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+                  gen6_rps_limits(dev_priv, val));
 
        POSTING_READ(GEN6_RPNSWREQ);
 
@@ -3583,9 +3037,11 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+
        mutex_lock(&dev_priv->rps.hw_lock);
        if (dev_priv->rps.enabled) {
-               if (dev_priv->info->is_valleyview)
+               if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
                else
                        gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
@@ -3596,9 +3052,11 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 
 void gen6_rps_boost(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+
        mutex_lock(&dev_priv->rps.hw_lock);
        if (dev_priv->rps.enabled) {
-               if (dev_priv->info->is_valleyview)
+               if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
                else
                        gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
@@ -3607,48 +3065,18 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
-/*
- * Wait until the previous freq change has completed,
- * or the timeout elapsed, and then update our notion
- * of the current GPU frequency.
- */
-static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv)
-{
-       u32 pval;
-
-       WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-
-       if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10))
-               DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
-
-       pval >>= 8;
-
-       if (pval != dev_priv->rps.cur_delay)
-               DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n",
-                                vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay),
-                                dev_priv->rps.cur_delay,
-                                vlv_gpu_freq(dev_priv->mem_freq, pval), pval);
-
-       dev_priv->rps.cur_delay = pval;
-}
-
 void valleyview_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       gen6_rps_limits(dev_priv, &val);
-
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
        WARN_ON(val < dev_priv->rps.min_delay);
 
-       vlv_update_rps_cur_delay(dev_priv);
-
        DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay,
-                        vlv_gpu_freq(dev_priv->mem_freq, val), val);
+                        vlv_gpu_freq(dev_priv, val), val);
 
        if (val == dev_priv->rps.cur_delay)
                return;
@@ -3657,7 +3085,7 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 
        dev_priv->rps.cur_delay = val;
 
-       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val));
+       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
@@ -3775,7 +3203,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        /* 1c & 1d: Get forcewake during program sequence. Although the driver
         * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        /* 2a: Disable RC states. */
        I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3832,7 +3260,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 static void gen6_enable_rps(struct drm_device *dev)
@@ -3862,7 +3290,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                I915_WRITE(GTFIFODBG, gtfifodbg);
        }
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
@@ -3954,7 +3382,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                        DRM_ERROR("Couldn't fix incorrect rc6 voltage\n");
        }
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void gen6_update_ring_freq(struct drm_device *dev)
@@ -4116,7 +3544,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
        valleyview_setup_pctx(dev);
 
-       gen6_gt_force_wake_get(dev_priv);
+       /* If VLV, Forcewake all wells, else re-direct to regular path */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
        I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
@@ -4140,7 +3569,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
        for_each_ring(ring, dev_priv, i)
                I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 
-       I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
        /* allows RC6 residency counter to work */
        I915_WRITE(VLV_COUNTER_CONTROL,
@@ -4148,65 +3577,47 @@ static void valleyview_enable_rps(struct drm_device *dev)
                                      VLV_MEDIA_RC6_COUNT_EN |
                                      VLV_RENDER_RC6_COUNT_EN));
        if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
-               rc6_mode = GEN7_RC_CTL_TO_MODE;
+               rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
 
        intel_print_rc6_info(dev, rc6_mode);
 
        I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
 
        val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-       switch ((val >> 6) & 3) {
-       case 0:
-       case 1:
-               dev_priv->mem_freq = 800;
-               break;
-       case 2:
-               dev_priv->mem_freq = 1066;
-               break;
-       case 3:
-               dev_priv->mem_freq = 1333;
-               break;
-       }
-       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
        DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
        dev_priv->rps.cur_delay = (val >> 8) & 0xff;
        DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay);
 
        dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv);
        dev_priv->rps.hw_max = dev_priv->rps.max_delay;
        DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.max_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay),
                         dev_priv->rps.max_delay);
 
        dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
        DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv);
        DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.min_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay),
                         dev_priv->rps.min_delay);
 
        DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void ironlake_teardown_rc6(struct drm_device *dev)
@@ -5019,6 +4430,20 @@ static void g4x_disable_trickle_feed(struct drm_device *dev)
        }
 }
 
+static void ilk_init_lp_watermarks(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN);
+       I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN);
+       I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
+
+       /*
+        * Don't touch WM1S_LP_EN here.
+        * Doing so could cause underruns.
+        */
+}
+
 static void ironlake_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5052,9 +4477,8 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
        I915_WRITE(DISP_ARB_CTL,
                   (I915_READ(DISP_ARB_CTL) |
                    DISP_FBC_WM_DIS));
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+
+       ilk_init_lp_watermarks(dev);
 
        /*
         * Based on the document from hardware guys the following bits
@@ -5161,9 +4585,7 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                I915_WRITE(GEN6_GT_MODE,
                           _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        I915_WRITE(CACHE_MODE_0,
                   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
@@ -5304,28 +4726,40 @@ static void gen8_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
                   _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
 
-       /* WaSwitchSolVfFArbitrationPriority */
+       /* WaSwitchSolVfFArbitrationPriority:bdw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
 
-       /* WaPsrDPAMaskVBlankInSRD */
+       /* WaPsrDPAMaskVBlankInSRD:bdw */
        I915_WRITE(CHICKEN_PAR1_1,
                   I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
 
-       /* WaPsrDPRSUnmaskVBlankInSRD */
+       /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
        for_each_pipe(i) {
                I915_WRITE(CHICKEN_PIPESL_1(i),
                           I915_READ(CHICKEN_PIPESL_1(i) |
                                     DPRS_MASK_VBLANK_SRD));
        }
+
+       /* Use Force Non-Coherent whenever executing a 3D context. This is a
+        * workaround for for a possible hang in the unlikely event a TLB
+        * invalidation occurs during a PSD flush.
+        */
+       I915_WRITE(HDC_CHICKEN0,
+                  I915_READ(HDC_CHICKEN0) |
+                  _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT));
+
+       /* WaVSRefCountFullforceMissDisable:bdw */
+       /* WaDSRefCountFullforceMissDisable:bdw */
+       I915_WRITE(GEN7_FF_THREAD_MODE,
+                  I915_READ(GEN7_FF_THREAD_MODE) &
+                  ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME));
 }
 
 static void haswell_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:hsw workaround.
@@ -5374,9 +4808,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t snpcr;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5463,6 +4895,26 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 static void valleyview_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+       switch ((val >> 6) & 3) {
+       case 0:
+               dev_priv->mem_freq = 800;
+               break;
+       case 1:
+               dev_priv->mem_freq = 1066;
+               break;
+       case 2:
+               dev_priv->mem_freq = 1333;
+               break;
+       case 3:
+               dev_priv->mem_freq = 1333;
+               break;
+       }
+       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5642,50 +5094,133 @@ void intel_suspend_hw(struct drm_device *dev)
                lpt_suspend_hw(dev);
 }
 
-static bool is_always_on_power_domain(struct drm_device *dev,
-                                     enum intel_display_power_domain domain)
-{
-       unsigned long always_on_domains;
-
-       BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK);
-
-       if (IS_BROADWELL(dev)) {
-               always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS;
-       } else if (IS_HASWELL(dev)) {
-               always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS;
-       } else {
-               WARN_ON(1);
-               return true;
-       }
+#define for_each_power_well(i, power_well, domain_mask, power_domains) \
+       for (i = 0;                                                     \
+            i < (power_domains)->power_well_count &&                   \
+                ((power_well) = &(power_domains)->power_wells[i]);     \
+            i++)                                                       \
+               if ((power_well)->domains & (domain_mask))
 
-       return BIT(domain) & always_on_domains;
-}
+#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
+       for (i = (power_domains)->power_well_count - 1;                  \
+            i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
+            i--)                                                        \
+               if ((power_well)->domains & (domain_mask))
 
 /**
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
  * be enabled.
  */
+static bool hsw_power_well_enabled(struct drm_device *dev,
+                                  struct i915_power_well *power_well)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(HSW_PWR_WELL_DRIVER) ==
+                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+}
+
+bool intel_display_power_enabled_sw(struct drm_device *dev,
+                                   enum intel_display_power_domain domain)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+
+       power_domains = &dev_priv->power_domains;
+
+       return power_domains->domain_use_count[domain];
+}
+
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+       struct i915_power_well *power_well;
+       bool is_enabled;
+       int i;
+
+       power_domains = &dev_priv->power_domains;
 
-       if (!HAS_POWER_WELL(dev))
-               return true;
+       is_enabled = true;
 
-       if (is_always_on_power_domain(dev, domain))
-               return true;
+       mutex_lock(&power_domains->lock);
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
+               if (power_well->always_on)
+                       continue;
 
-       return I915_READ(HSW_PWR_WELL_DRIVER) ==
-                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+               if (!power_well->is_enabled(dev, power_well)) {
+                       is_enabled = false;
+                       break;
+               }
+       }
+       mutex_unlock(&power_domains->lock);
+
+       return is_enabled;
+}
+
+static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       unsigned long irqflags;
+
+       /*
+        * After we re-enable the power well, if we touch VGA register 0x3d5
+        * we'll get unclaimed register interrupts. This stops after we write
+        * anything to the VGA MSR register. The vgacon module uses this
+        * register all the time, so if we unbind our driver and, as a
+        * consequence, bind vgacon, we'll get stuck in an infinite loop at
+        * console_unlock(). So make here we touch the VGA MSR register, making
+        * sure vgacon can keep working normally without triggering interrupts
+        * and error messages.
+        */
+       vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+       outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
+       vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+
+       if (IS_BROADWELL(dev)) {
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
+                          dev_priv->de_irq_mask[PIPE_B]);
+               I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
+                          ~dev_priv->de_irq_mask[PIPE_B] |
+                          GEN8_PIPE_VBLANK);
+               I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
+                          dev_priv->de_irq_mask[PIPE_C]);
+               I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
+                          ~dev_priv->de_irq_mask[PIPE_C] |
+                          GEN8_PIPE_VBLANK);
+               POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+       }
+}
+
+static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       enum pipe p;
+       unsigned long irqflags;
+
+       /*
+        * After this, the registers on the pipes that are part of the power
+        * well will become zero, so we have to adjust our counters according to
+        * that.
+        *
+        * FIXME: Should we do this in general in drm_vblank_post_modeset?
+        */
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       for_each_pipe(p)
+               if (p != PIPE_A)
+                       dev->vblank[p].last = 0;
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 
-static void __intel_set_power_well(struct drm_device *dev, bool enable)
+static void hsw_set_power_well(struct drm_device *dev,
+                              struct i915_power_well *power_well, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool is_enabled, enable_requested;
-       unsigned long irqflags;
        uint32_t tmp;
 
        WARN_ON(dev_priv->pc8.enabled);
@@ -5706,42 +5241,14 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
                                DRM_ERROR("Timeout enabling power well\n");
                }
 
-               if (IS_BROADWELL(dev)) {
-                       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
-                                  dev_priv->de_irq_mask[PIPE_B]);
-                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
-                                  ~dev_priv->de_irq_mask[PIPE_B] |
-                                  GEN8_PIPE_VBLANK);
-                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
-                                  dev_priv->de_irq_mask[PIPE_C]);
-                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
-                                  ~dev_priv->de_irq_mask[PIPE_C] |
-                                  GEN8_PIPE_VBLANK);
-                       POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
-                       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-               }
+               hsw_power_well_post_enable(dev_priv);
        } else {
                if (enable_requested) {
-                       enum pipe p;
-
                        I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
                        POSTING_READ(HSW_PWR_WELL_DRIVER);
                        DRM_DEBUG_KMS("Requesting to disable the power well\n");
 
-                       /*
-                        * After this, the registers on the pipes that are part
-                        * of the power well will become zero, so we have to
-                        * adjust our counters according to that.
-                        *
-                        * FIXME: Should we do this in general in
-                        * drm_vblank_post_modeset?
-                        */
-                       spin_lock_irqsave(&dev->vbl_lock, irqflags);
-                       for_each_pipe(p)
-                               if (p != PIPE_A)
-                                       dev->vblank[p].last = 0;
-                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+                       hsw_power_well_post_disable(dev_priv);
                }
        }
 }
@@ -5751,9 +5258,9 @@ static void __intel_power_well_get(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!power_well->count++) {
+       if (!power_well->count++ && power_well->set) {
                hsw_disable_package_c8(dev_priv);
-               __intel_set_power_well(dev, true);
+               power_well->set(dev, power_well, true);
        }
 }
 
@@ -5763,8 +5270,10 @@ static void __intel_power_well_put(struct drm_device *dev,
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well) {
-               __intel_set_power_well(dev, false);
+
+       if (!--power_well->count && power_well->set &&
+           i915_disable_power_well) {
+               power_well->set(dev, power_well, false);
                hsw_enable_package_c8(dev_priv);
        }
 }
@@ -5774,17 +5283,18 @@ void intel_display_power_get(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_get(dev, &power_domains->power_wells[0]);
+
+       for_each_power_well(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_get(dev, power_well);
+
+       power_domains->domain_use_count[domain]++;
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5793,17 +5303,19 @@ void intel_display_power_put(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_put(dev, &power_domains->power_wells[0]);
+
+       WARN_ON(!power_domains->domain_use_count[domain]);
+       power_domains->domain_use_count[domain]--;
+
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_put(dev, power_well);
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5819,10 +5331,7 @@ void i915_request_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_request_power_well);
 
@@ -5836,24 +5345,71 @@ void i915_release_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_release_power_well);
 
+static struct i915_power_well i9xx_always_on_power_well[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = POWER_DOMAIN_MASK,
+       },
+};
+
+static struct i915_power_well hsw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+static struct i915_power_well bdw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+#define set_power_wells(power_domains, __power_wells) ({               \
+       (power_domains)->power_wells = (__power_wells);                 \
+       (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
+})
+
 int intel_power_domains_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
-       struct i915_power_well *power_well;
 
        mutex_init(&power_domains->lock);
-       hsw_pwr = power_domains;
 
-       power_well = &power_domains->power_wells[0];
-       power_well->count = 0;
+       /*
+        * The enabling order will be from lower to higher indexed wells,
+        * the disabling order is reversed.
+        */
+       if (IS_HASWELL(dev)) {
+               set_power_wells(power_domains, hsw_power_wells);
+               hsw_pwr = power_domains;
+       } else if (IS_BROADWELL(dev)) {
+               set_power_wells(power_domains, bdw_power_wells);
+               hsw_pwr = power_domains;
+       } else {
+               set_power_wells(power_domains, i9xx_always_on_power_well);
+       }
 
        return 0;
 }
@@ -5868,15 +5424,13 @@ static void intel_power_domains_resume(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
        struct i915_power_well *power_well;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
+       int i;
 
        mutex_lock(&power_domains->lock);
-
-       power_well = &power_domains->power_wells[0];
-       __intel_set_power_well(dev, power_well->count > 0);
-
+       for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+               if (power_well->set)
+                       power_well->set(dev, power_well, power_well->count > 0);
+       }
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5890,13 +5444,13 @@ void intel_power_domains_init_hw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!HAS_POWER_WELL(dev))
-               return;
-
        /* For now, we need the power well to be always enabled. */
        intel_display_set_init_power(dev, true);
        intel_power_domains_resume(dev);
 
+       if (!(IS_HASWELL(dev) || IS_BROADWELL(dev)))
+               return;
+
        /* We're taking over the BIOS, so clear any requests made by it since
         * the driver is in charge now. */
        if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
@@ -5914,31 +5468,86 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
        hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_get_sync(device);
+       WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       dev_priv->pm.suspended = false;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_set_active(device);
+
+       pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       /* Make sure we're not suspended first. */
+       pm_runtime_get_sync(device);
+       pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (I915_HAS_FBC(dev)) {
-               if (HAS_PCH_SPLIT(dev)) {
+       if (HAS_FBC(dev)) {
+               if (INTEL_INFO(dev)->gen >= 7) {
                        dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
-                       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-                               dev_priv->display.enable_fbc =
-                                       gen7_enable_fbc;
-                       else
-                               dev_priv->display.enable_fbc =
-                                       ironlake_enable_fbc;
+                       dev_priv->display.enable_fbc = gen7_enable_fbc;
+                       dev_priv->display.disable_fbc = ironlake_disable_fbc;
+               } else if (INTEL_INFO(dev)->gen >= 5) {
+                       dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
+                       dev_priv->display.enable_fbc = ironlake_enable_fbc;
                        dev_priv->display.disable_fbc = ironlake_disable_fbc;
                } else if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
                        dev_priv->display.enable_fbc = g4x_enable_fbc;
                        dev_priv->display.disable_fbc = g4x_disable_fbc;
-               } else if (IS_CRESTLINE(dev)) {
+               } else {
                        dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
                        dev_priv->display.enable_fbc = i8xx_enable_fbc;
                        dev_priv->display.disable_fbc = i8xx_disable_fbc;
+
+                       /* This value was pulled out of someone's hat */
+                       I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
                }
-               /* 855GM needs testing */
        }
 
        /* For cxsr */
@@ -5951,58 +5560,27 @@ void intel_init_pm(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                intel_setup_wm_latency(dev);
 
-               if (IS_GEN5(dev)) {
-                       if (dev_priv->wm.pri_latency[1] &&
-                           dev_priv->wm.spr_latency[1] &&
-                           dev_priv->wm.cur_latency[1])
-                               dev_priv->display.update_wm = ironlake_update_wm;
-                       else {
-                               DRM_DEBUG_KMS("Failed to get proper latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] &&
+                    dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
+                   (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
+                    dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
+                       dev_priv->display.update_wm = ilk_update_wm;
+                       dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
+               } else {
+                       DRM_DEBUG_KMS("Failed to read display plane latency. "
+                                     "Disable CxSR\n");
+               }
+
+               if (IS_GEN5(dev))
                        dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
-               } else if (IS_GEN6(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = sandybridge_update_wm;
-                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_GEN6(dev))
                        dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-               } else if (IS_IVYBRIDGE(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = ivybridge_update_wm;
-                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_IVYBRIDGE(dev))
                        dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-               } else if (IS_HASWELL(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = haswell_update_wm;
-                               dev_priv->display.update_sprite_wm =
-                                       haswell_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_HASWELL(dev))
                        dev_priv->display.init_clock_gating = haswell_init_clock_gating;
-               } else if (INTEL_INFO(dev)->gen == 8) {
+               else if (INTEL_INFO(dev)->gen == 8)
                        dev_priv->display.init_clock_gating = gen8_init_clock_gating;
-               } else
-                       dev_priv->display.update_wm = NULL;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.update_wm = valleyview_update_wm;
                dev_priv->display.init_clock_gating =
@@ -6036,21 +5614,21 @@ void intel_init_pm(struct drm_device *dev)
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
                dev_priv->display.init_clock_gating = gen3_init_clock_gating;
-       } else if (IS_I865G(dev)) {
-               dev_priv->display.update_wm = i830_update_wm;
-               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-               dev_priv->display.get_fifo_size = i830_get_fifo_size;
-       } else if (IS_I85X(dev)) {
-               dev_priv->display.update_wm = i9xx_update_wm;
-               dev_priv->display.get_fifo_size = i85x_get_fifo_size;
-               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-       } else {
-               dev_priv->display.update_wm = i830_update_wm;
-               dev_priv->display.init_clock_gating = i830_init_clock_gating;
-               if (IS_845G(dev))
+       } else if (IS_GEN2(dev)) {
+               if (INTEL_INFO(dev)->num_pipes == 1) {
+                       dev_priv->display.update_wm = i845_update_wm;
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
-               else
+               } else {
+                       dev_priv->display.update_wm = i9xx_update_wm;
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
+               }
+
+               if (IS_I85X(dev) || IS_I865G(dev))
+                       dev_priv->display.init_clock_gating = i85x_init_clock_gating;
+               else
+                       dev_priv->display.init_clock_gating = i830_init_clock_gating;
+       } else {
+               DRM_ERROR("unexpected fall-through in intel_init_pm\n");
        }
 }
 
@@ -6101,59 +5679,48 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
        return 0;
 }
 
-int vlv_gpu_freq(int ddr_freq, int val)
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int div;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               div = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               div = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               div = 16;
                break;
        default:
                return -1;
        }
 
-       return ((val - 0xbd) * mult) + base;
+       return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div);
 }
 
-int vlv_freq_opcode(int ddr_freq, int val)
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int mul;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               mul = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               mul = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               mul = 16;
                break;
        default:
                return -1;
        }
 
-       val /= mult;
-       val -= base / mult;
-       val += 0xbd;
-
-       if (val > 0xea)
-               val = 0xea;
-
-       return val;
+       return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6;
 }
 
 void intel_pm_setup(struct drm_device *dev)
index c2f09d4563008ff7e32238675dab1b4da02ec967..8fcb32a02cb40564bf9f6aab5efb6c4cbe38ad97 100644 (file)
@@ -285,14 +285,16 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
        if (!ring->fbc_dirty)
                return 0;
 
-       ret = intel_ring_begin(ring, 4);
+       ret = intel_ring_begin(ring, 6);
        if (ret)
                return ret;
-       intel_ring_emit(ring, MI_NOOP);
        /* WaFbcNukeOn3DBlt:ivb/hsw */
        intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
        intel_ring_emit(ring, MSG_FBC_REND_STATE);
        intel_ring_emit(ring, value);
+       intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT);
+       intel_ring_emit(ring, MSG_FBC_REND_STATE);
+       intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        intel_ring_advance(ring);
 
        ring->fbc_dirty = false;
@@ -354,7 +356,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring,
        intel_ring_emit(ring, 0);
        intel_ring_advance(ring);
 
-       if (flush_domains)
+       if (!invalidate_domains && flush_domains)
                return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
 
        return 0;
@@ -436,7 +438,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        int ret = 0;
        u32 head;
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (I915_NEED_GFX_HWS(dev))
                intel_ring_setup_status_page(ring);
@@ -509,7 +511,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
 
 out:
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        return ret;
 }
@@ -661,14 +663,15 @@ gen6_add_request(struct intel_ring_buffer *ring)
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *useless;
-       int i, ret;
+       int i, ret, num_dwords = 4;
 
-       ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) *
-                                     MBOX_UPDATE_DWORDS) +
-                                     4);
+       if (i915_semaphore_is_enabled(dev))
+               num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
+#undef MBOX_UPDATE_DWORDS
+
+       ret = intel_ring_begin(ring, num_dwords);
        if (ret)
                return ret;
-#undef MBOX_UPDATE_DWORDS
 
        for_each_ring(useless, dev_priv, i) {
                u32 mbox_reg = ring->signal_mbox[i];
@@ -1030,11 +1033,6 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
        if (!dev->irq_enabled)
               return false;
 
-       /* It looks like we need to prevent the gt from suspending while waiting
-        * for an notifiy irq, otherwise irqs seem to get lost on at least the
-        * blt/bsd rings on ivb. */
-       gen6_gt_force_wake_get(dev_priv);
-
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
                if (HAS_L3_DPF(dev) && ring->id == RCS)
@@ -1066,8 +1064,6 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
                ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
-
-       gen6_gt_force_wake_put(dev_priv);
 }
 
 static bool
@@ -1611,8 +1607,8 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
        return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
 }
 
-static int __intel_ring_begin(struct intel_ring_buffer *ring,
-                             int bytes)
+static int __intel_ring_prepare(struct intel_ring_buffer *ring,
+                               int bytes)
 {
        int ret;
 
@@ -1628,7 +1624,6 @@ static int __intel_ring_begin(struct intel_ring_buffer *ring,
                        return ret;
        }
 
-       ring->space -= bytes;
        return 0;
 }
 
@@ -1643,12 +1638,17 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
+       ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
+       if (ret)
+               return ret;
+
        /* Preallocate the olr before touching the ring */
        ret = intel_ring_alloc_seqno(ring);
        if (ret)
                return ret;
 
-       return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t));
+       ring->space -= num_dwords * sizeof(uint32_t);
+       return 0;
 }
 
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
@@ -1838,7 +1838,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring,
        }
        intel_ring_advance(ring);
 
-       if (IS_GEN7(dev) && flush)
+       if (IS_GEN7(dev) && !invalidate && flush)
                return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
 
        return 0;
index a583e8f718a7f0f4b87b4fe724336c73ad1a8198..95bdfb3c431c8467b105c616f6d5f9567505804f 100644 (file)
@@ -413,23 +413,34 @@ static const struct _sdvo_cmd_name {
 static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
                                   const void *args, int args_len)
 {
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
+
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
 
-       DRM_DEBUG_KMS("%s: W: %02X ",
-                               SDVO_NAME(intel_sdvo), cmd);
-       for (i = 0; i < args_len; i++)
-               DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
-       for (; i < 8; i++)
-               DRM_LOG_KMS("   ");
+       for (i = 0; i < args_len; i++) {
+               BUF_PRINT("%02X ", ((u8 *)args)[i]);
+       }
+       for (; i < 8; i++) {
+               BUF_PRINT("   ");
+       }
        for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
                if (cmd == sdvo_cmd_names[i].cmd) {
-                       DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
+                       BUF_PRINT("(%s)", sdvo_cmd_names[i].name);
                        break;
                }
        }
-       if (i == ARRAY_SIZE(sdvo_cmd_names))
-               DRM_LOG_KMS("(%02X)", cmd);
-       DRM_LOG_KMS("\n");
+       if (i == ARRAY_SIZE(sdvo_cmd_names)) {
+               BUF_PRINT("(%02X)", cmd);
+       }
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer);
 }
 
 static const char *cmd_status_names[] = {
@@ -512,9 +523,10 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
 {
        u8 retry = 15; /* 5 quick checks, followed by 10 long checks */
        u8 status;
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
 
-       DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
 
        /*
         * The documentation states that all commands will be
@@ -551,10 +563,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                        goto log_fail;
        }
 
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
        if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-               DRM_LOG_KMS("(%s)", cmd_status_names[status]);
+               BUF_PRINT("(%s)", cmd_status_names[status]);
        else
-               DRM_LOG_KMS("(??? %d)", status);
+               BUF_PRINT("(??? %d)", status);
 
        if (status != SDVO_CMD_STATUS_SUCCESS)
                goto log_fail;
@@ -565,13 +580,17 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                                          SDVO_I2C_RETURN_0 + i,
                                          &((u8 *)response)[i]))
                        goto log_fail;
-               DRM_LOG_KMS(" %02X", ((u8 *)response)[i]);
+               BUF_PRINT(" %02X", ((u8 *)response)[i]);
        }
-       DRM_LOG_KMS("\n");
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer);
        return true;
 
 log_fail:
-       DRM_LOG_KMS("... failed\n");
+       DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo));
        return false;
 }
 
@@ -933,7 +952,7 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 
 static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
                                       unsigned if_index, uint8_t tx_rate,
-                                      uint8_t *data, unsigned length)
+                                      const uint8_t *data, unsigned length)
 {
        uint8_t set_buf_index[2] = { if_index, 0 };
        uint8_t hbuf_size, tmp[8];
@@ -1517,8 +1536,9 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_sdvo_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_sdvo_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 
index 770bdd6ecd9fb96b46365bbadd97ba3011c0ef96..2e2d4eb4a00d190b24c03c1998b4e9f0cd9f06c5 100644 (file)
@@ -59,7 +59,7 @@ struct intel_sdvo_caps {
        unsigned int stall_support:1;
        unsigned int pad:1;
        u16 output_flags;
-} __attribute__((packed));
+} __packed;
 
 /* Note: SDVO detailed timing flags match EDID misc flags. */
 #define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
@@ -94,12 +94,12 @@ struct intel_sdvo_dtd {
                u8 v_sync_off_high;
                u8 reserved;
        } part2;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_pixel_clock_range {
        u16 min;        /**< pixel clock, in 10kHz units */
        u16 max;        /**< pixel clock, in 10kHz units */
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_preferred_input_timing_args {
        u16 clock;
@@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args {
        u8      interlace:1;
        u8      scaled:1;
        u8      pad:6;
-} __attribute__((packed));
+} __packed;
 
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0                         0x07
@@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response {
        unsigned int input0_trained:1;
        unsigned int input1_trained:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /** Returns a struct intel_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS                    0x04
@@ -219,7 +219,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
        unsigned int ambient_light_interrupt:1;
        unsigned int hdmi_audio_encrypt_change:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Selects which input is affected by future input commands.
@@ -232,7 +232,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
 struct intel_sdvo_set_target_input_args {
        unsigned int target_1:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Takes a struct intel_sdvo_output_flags of which outputs are targeted by
@@ -370,7 +370,7 @@ struct intel_sdvo_tv_format {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:3;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_TV_FORMAT                         0x28
 
@@ -401,7 +401,7 @@ struct intel_sdvo_sdtv_resolution_request {
        unsigned int secam_l:1;
        unsigned int secam_60:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_320x200:1;
@@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_1024x768:1;
        unsigned int res_1280x1024:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported resolution with squire pixel aspect ratio that can be
    scaled for the requested HDTV format */
@@ -463,7 +463,7 @@ struct intel_sdvo_hdtv_resolution_request {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_hdtv_resolution_reply {
        unsigned int res_640x480:1;
@@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply {
 
        unsigned int res_1280x768:1;
        unsigned int pad5:7;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported power state returns info for encoder and monitor, rely on
    last SetTargetInput and SetTargetOutput calls */
@@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing {
 
        unsigned int t4_high:2;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL               0x30
 struct sdvo_max_backlight_reply {
        u8 max_value;
        u8 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_BACKLIGHT_LEVEL                   0x31
 #define SDVO_CMD_SET_BACKLIGHT_LEVEL                   0x32
@@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        u16 value;
-} __attribute__((packed));
+} __packed;
 #define SDVO_CMD_SET_AMBIENT_LIGHT                     0x34
 struct sdvo_set_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        unsigned int enable:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /* Set display power state */
 #define SDVO_CMD_SET_DISPLAY_POWER_STATE               0x7d
@@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply {
        unsigned int dither:1;
        unsigned int tv_chroma_filter:1;
        unsigned int tv_luma_filter:1;
-} __attribute__((packed));
+} __packed;
 
 /* Picture enhancement limits below are dependent on the current TV format,
  * and thus need to be queried and set after it.
@@ -630,7 +630,7 @@ struct intel_sdvo_enhancements_reply {
 struct intel_sdvo_enhancement_limits_reply {
        u16 max_value;
        u16 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION            0x7f
 #define SDVO_CMD_SET_LVDS_PANEL_INFORMATION            0x80
@@ -671,7 +671,7 @@ struct intel_sdvo_enhancement_limits_reply {
 #define SDVO_CMD_SET_TV_LUMA_FILTER                    0x79
 struct intel_sdvo_enhancements_arg {
        u16 value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_DOT_CRAWL                         0x70
 #define SDVO_CMD_SET_DOT_CRAWL                         0x71
@@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg {
 struct intel_sdvo_encode {
        u8 dvi_rev;
        u8 hdmi_rev;
-} __attribute__ ((packed));
+} __packed;
index 9944d8135e87f88215d5d07d54a5fd87fcf4dc60..0954f132726ea0ae15593364ef976168fc2c909f 100644 (file)
@@ -90,6 +90,22 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
+u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_READ, reg, &val);
+
+       return val;
+}
+
+void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
 {
        u32 val = 0;
@@ -160,27 +176,18 @@ void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
                        PUNIT_OPCODE_REG_WRITE, reg, &val);
 }
 
-static u32 vlv_get_phy_port(enum pipe pipe)
-{
-       u32 port = IOSF_PORT_DPIO;
-
-       WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B));
-
-       return port;
-}
-
 u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg)
 {
        u32 val = 0;
 
-       vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_READ, reg, &val);
        return val;
 }
 
 void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val)
 {
-       vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_WRITE, reg, &val);
 }
 
@@ -242,3 +249,17 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                return;
        }
 }
+
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_READ, reg, &val);
+       return val;
+}
+
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_WRITE, reg, &val);
+}
index b9fabf826f7de71f224bd9b808780f81ba1c9027..fe4de89c374ceb69f75f650d7a5e0212841c22eb 100644 (file)
@@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                break;
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SP_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SP_TILED;
 
@@ -224,7 +230,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        u32 sprctl, sprscale = 0;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
 
        sprctl = I915_READ(SPRCTL(pipe));
 
@@ -257,6 +262,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SPRITE_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SPRITE_TILED;
 
@@ -279,21 +290,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        crtc_w--;
        crtc_h--;
 
-       /*
-        * IVB workaround: must disable low power watermarks for at least
-        * one frame before enabling scaling.  LP watermarks can be re-enabled
-        * when scaling is disabled.
-        */
-       if (crtc_w != src_w || crtc_h != src_h) {
-               dev_priv->sprite_scaling_enabled |= 1 << pipe;
-
-               if (!scaling_was_enabled) {
-                       intel_update_watermarks(crtc);
-                       intel_wait_for_vblank(dev, pipe);
-               }
+       if (crtc_w != src_w || crtc_h != src_h)
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
-       } else
-               dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
        I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
@@ -320,10 +318,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        I915_MODIFY_DISPBASE(SPRSURF(pipe),
                             i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
        POSTING_READ(SPRSURF(pipe));
-
-       /* potentially re-enable LP watermarks */
-       if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(crtc);
 }
 
 static void
@@ -333,7 +327,6 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        int pipe = intel_plane->pipe;
-       bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
 
        I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
        /* Can't leave the scaler enabled... */
@@ -343,13 +336,13 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
        POSTING_READ(SPRSURF(pipe));
 
-       dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
+       /*
+        * Avoid underruns when disabling the sprite.
+        * FIXME remove once watermark updates are done properly.
+        */
+       intel_wait_for_vblank(dev, pipe);
 
        intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
-
-       /* potentially re-enable LP watermarks */
-       if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(crtc);
 }
 
 static int
@@ -453,6 +446,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       dvscntr |= DVS_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                dvscntr |= DVS_TILED;
 
@@ -470,7 +469,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        crtc_h--;
 
        dvsscale = 0;
-       if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
+       if (crtc_w != src_w || crtc_h != src_h)
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
@@ -510,6 +509,12 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
        POSTING_READ(DVSSURF(pipe));
 
+       /*
+        * Avoid underruns when disabling the sprite.
+        * FIXME remove once watermark updates are done properly.
+        */
+       intel_wait_for_vblank(dev, pipe);
+
        intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 }
 
@@ -643,6 +648,15 @@ format_is_yuv(uint32_t format)
        }
 }
 
+static bool colorkey_enabled(struct intel_plane *intel_plane)
+{
+       struct drm_intel_sprite_colorkey key;
+
+       intel_plane->get_colorkey(&intel_plane->base, &key);
+
+       return key.flags != I915_SET_COLORKEY_NONE;
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -828,7 +842,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * If the sprite is completely covering the primary plane,
         * we can disable the primary and save power.
         */
-       disable_primary = drm_rect_equals(&dst, &clip);
+       disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane);
        WARN_ON(disable_primary && !visible && intel_crtc->active);
 
        mutex_lock(&dev->struct_mutex);
index 25cbe073c388a3185d1a32afeb805993e43d12d3..2c8143c37de350b153572242b0586838432e0e6c 100644 (file)
@@ -64,7 +64,8 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0,
                            FORCEWAKE_ACK_TIMEOUT_MS))
@@ -89,7 +90,8 @@ static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        u32 forcewake_ack;
 
@@ -121,12 +123,12 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
        u32 gtfifodbg;
 
        gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG);
-       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
-            "MMIO read or write has been dropped %x\n", gtfifodbg))
-               __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+       if (WARN(gtfifodbg, "GT wake FIFO error 0x%x\n", gtfifodbg))
+               __raw_i915_write32(dev_priv, GTFIFODBG, gtfifodbg);
 }
 
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE, 0);
        /* something from same cacheline, but !FORCEWAKE */
@@ -134,7 +136,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
        gen6_gt_check_fifodbg(dev_priv);
 }
 
-static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE_MT,
                           _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
@@ -147,12 +150,19 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
        int ret = 0;
 
+       /* On VLV, FIFO will be shared by both SW and HW.
+        * So, we need to read the FREE_ENTRIES everytime */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               dev_priv->uncore.fifo_count =
+                       __raw_i915_read32(dev_priv, GTFIFOCTL) &
+                                               GT_FIFO_FREE_ENTRIES_MASK;
+
        if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
                int loop = 500;
-               u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+               u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
                        udelay(10);
-                       fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+                       fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                }
                if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
                        ++ret;
@@ -171,38 +181,112 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
 }
 
-static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
 {
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Render forcewake old ack to clear.\n");
 
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for Render to ack.\n");
+       }
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) &
-                            FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Media forcewake old ack to clear.\n");
+
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for media to ack.\n");
+       }
 
        /* WaRsForcewakeWaitTC0:vlv */
        __gen6_gt_wait_for_thread_c0(dev_priv);
+
 }
 
-static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                       int fw_engine)
 {
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                       _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                               _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
        /* The below doubles as a POSTING_READ */
        gen6_gt_check_fifodbg(dev_priv);
+
+}
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (dev_priv->uncore.fw_rendercount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (dev_priv->uncore.fw_mediacount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+void vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+       if (FORCEWAKE_RENDER & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_rendercount == 0);
+               if (--dev_priv->uncore.fw_rendercount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_mediacount == 0);
+               if (--dev_priv->uncore.fw_mediacount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void gen6_force_wake_work(struct work_struct *work)
@@ -213,7 +297,7 @@ static void gen6_force_wake_work(struct work_struct *work)
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0)
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
@@ -248,6 +332,11 @@ void intel_uncore_early_sanitize(struct drm_device *dev)
                DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
        }
 
+       /* clear out old GT FIFO errors */
+       if (IS_GEN6(dev) || IS_GEN7(dev))
+               __raw_i915_write32(dev_priv, GTFIFODBG,
+                                  __raw_i915_read32(dev_priv, GTFIFODBG));
+
        intel_uncore_forcewake_reset(dev);
 }
 
@@ -256,8 +345,6 @@ void intel_uncore_sanitize(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 reg_val;
 
-       intel_uncore_forcewake_reset(dev);
-
        /* BIOS often leaves RC6 enabled, but disable it for hw init */
        intel_disable_gt_powersave(dev);
 
@@ -281,29 +368,40 @@ void intel_uncore_sanitize(struct drm_device *dev)
  * be called at the beginning of the sequence followed by a call to
  * gen6_gt_force_wake_put() at the end of the sequence.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_get)
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_get(dev_priv, fw_engine);
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (dev_priv->uncore.forcewake_count++ == 0)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 /*
  * see gen6_gt_force_wake_get()
  */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_put)
                return;
 
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_put(dev_priv, fw_engine);
+
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0) {
                dev_priv->uncore.forcewake_count++;
@@ -312,6 +410,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
                                 1);
        }
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 /* We give fast paths for the really cool registers */
@@ -346,6 +446,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
        }
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+       WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+            "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
        unsigned long irqflags; \
        u##x val = 0; \
@@ -379,16 +486,51 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
        REG_READ_HEADER(x); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
                val = __raw_i915_read##x(dev_priv, reg); \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } else { \
                val = __raw_i915_read##x(dev_priv, reg); \
        } \
        REG_READ_FOOTER; \
 }
 
+#define __vlv_read(x) \
+static u##x \
+vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+       unsigned fwengine = 0; \
+       unsigned *fwcount; \
+       REG_READ_HEADER(x); \
+       if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) {   \
+               fwengine = FORCEWAKE_RENDER;            \
+               fwcount = &dev_priv->uncore.fw_rendercount;    \
+       }                                               \
+       else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) {       \
+               fwengine = FORCEWAKE_MEDIA;             \
+               fwcount = &dev_priv->uncore.fw_mediacount;     \
+       }  \
+       if (fwengine != 0) {            \
+               if ((*fwcount)++ == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+                                                               fwengine); \
+               val = __raw_i915_read##x(dev_priv, reg); \
+               if (--(*fwcount) == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+                                                       fwengine); \
+       } else { \
+               val = __raw_i915_read##x(dev_priv, reg); \
+       } \
+       REG_READ_FOOTER; \
+}
+
+
+__vlv_read(8)
+__vlv_read(16)
+__vlv_read(32)
+__vlv_read(64)
 __gen6_read(8)
 __gen6_read(16)
 __gen6_read(32)
@@ -402,6 +544,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
 #undef __gen4_read
@@ -413,12 +556,15 @@ __gen4_read(64)
        trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
+#define REG_WRITE_FOOTER \
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
+
 #define __gen4_write(x) \
 static void \
 gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
        REG_WRITE_HEADER; \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen5_write(x) \
@@ -427,7 +573,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        REG_WRITE_HEADER; \
        ilk_dummy_write(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen6_write(x) \
@@ -438,11 +584,12 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __hsw_write(x) \
@@ -453,13 +600,14 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        hsw_unclaimed_reg_clear(dev_priv, reg); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
        hsw_unclaimed_reg_check(dev_priv, reg); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 static const u32 gen8_shadowed_regs[] = {
@@ -486,16 +634,18 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
 #define __gen8_write(x) \
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
-       bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
+       bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
        REG_WRITE_HEADER; \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 __gen8_write(8)
@@ -524,6 +674,7 @@ __gen4_write(64)
 #undef __gen6_write
 #undef __gen5_write
 #undef __gen4_write
+#undef REG_WRITE_FOOTER
 #undef REG_WRITE_HEADER
 
 void intel_uncore_init(struct drm_device *dev)
@@ -534,8 +685,8 @@ void intel_uncore_init(struct drm_device *dev)
                          gen6_force_wake_work);
 
        if (IS_VALLEYVIEW(dev)) {
-               dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
-               dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
+               dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
+               dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put;
        } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
                dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get;
                dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put;
@@ -552,9 +703,9 @@ void intel_uncore_init(struct drm_device *dev)
                 * forcewake being disabled.
                 */
                mutex_lock(&dev->struct_mutex);
-               __gen6_gt_force_wake_mt_get(dev_priv);
+               __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL);
                ecobus = __raw_i915_read32(dev_priv, ECOBUS);
-               __gen6_gt_force_wake_mt_put(dev_priv);
+               __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                if (ecobus & FORCEWAKE_MT_ENABLE) {
@@ -601,10 +752,18 @@ void intel_uncore_init(struct drm_device *dev)
                        dev_priv->uncore.funcs.mmio_writel  = gen6_write32;
                        dev_priv->uncore.funcs.mmio_writeq  = gen6_write64;
                }
-               dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-               dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-               dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-               dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+
+               if (IS_VALLEYVIEW(dev)) {
+                       dev_priv->uncore.funcs.mmio_readb  = vlv_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = vlv_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = vlv_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = vlv_read64;
+               } else {
+                       dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+               }
                break;
        case 5:
                dev_priv->uncore.funcs.mmio_writeb  = gen5_write8;
@@ -687,6 +846,43 @@ int i915_reg_read_ioctl(struct drm_device *dev,
        return 0;
 }
 
+int i915_get_reset_stats_ioctl(struct drm_device *dev,
+                              void *data, struct drm_file *file)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_reset_stats *args = data;
+       struct i915_ctx_hang_stats *hs;
+       int ret;
+
+       if (args->flags || args->pad)
+               return -EINVAL;
+
+       if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id);
+       if (IS_ERR(hs)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(hs);
+       }
+
+       if (capable(CAP_SYS_ADMIN))
+               args->reset_count = i915_reset_count(&dev_priv->gpu_error);
+       else
+               args->reset_count = 0;
+
+       args->batch_active = hs->batch_active;
+       args->batch_pending = hs->batch_pending;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
 static int i965_reset_complete(struct drm_device *dev)
 {
        u8 gdrst;
@@ -770,12 +966,12 @@ static int gen6_do_reset(struct drm_device *dev)
 
        /* If reset with a user forcewake, try to restore, otherwise turn it off */
        if (dev_priv->uncore.forcewake_count)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        else
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        /* Restore fifo count */
-       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
        return ret;
@@ -793,15 +989,6 @@ int intel_gpu_reset(struct drm_device *dev)
        }
 }
 
-void intel_uncore_clear_errors(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       /* XXX needs spinlock around caller's grouping */
-       if (HAS_FPGA_DBG_UNCLAIMED(dev))
-               __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-}
-
 void intel_uncore_check_errors(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index 087db33f6cff19f8cdaa32f390c6c4dd52a8c79d..c3bf059ba720569540145f225222e0f2b444827c 100644 (file)
@@ -1075,10 +1075,10 @@ static int mga_dma_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
+               if (copy_to_user(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+               if (copy_to_user(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
                        return -EFAULT;
 
index ca4bc54ea2146303f4cedf7bdd879b3c3bc812fd..fe453213600ab728e57385e40b272e4e8b8ebc49 100644 (file)
@@ -186,14 +186,14 @@ extern void mga_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t mga_driver_irq_handler(int irq, void *arg);
 extern void mga_driver_irq_preinstall(struct drm_device *dev);
 extern int mga_driver_irq_postinstall(struct drm_device *dev);
 extern void mga_driver_irq_uninstall(struct drm_device *dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
-#define mga_flush_write_combine()      DRM_WRITEMEMORYBARRIER()
+#define mga_flush_write_combine()      wmb()
 
 #define MGA_READ8(reg)         DRM_READ8(dev_priv->mmio, (reg))
 #define MGA_READ(reg)          DRM_READ32(dev_priv->mmio, (reg))
index 709e90db8c4087dfcb782a51deab776271a7feb0..86b4bb80485200e1067c47574117fa1c46c17b8f 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <drm/drmP.h>
 #include <drm/mga_drm.h>
+#include "mga_drv.h"
 
 typedef struct drm32_mga_init {
        int func;
index 2b0ceb8dc11b8dce6894cf056998714603087a3d..1b071b8ff9dccec81e1d93376d0b6b09bc58521b 100644 (file)
@@ -47,7 +47,7 @@ u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
 }
 
 
-irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t mga_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -79,7 +79,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
                        MGA_WRITE(MGA_PRIMEND, prim_end);
 
                atomic_inc(&dev_priv->last_fence_retired);
-               DRM_WAKEUP(&dev_priv->fence_queue);
+               wake_up(&dev_priv->fence_queue);
                handled = 1;
        }
 
@@ -128,7 +128,7 @@ int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
         * by about a day rather than she wants to wait for years
         * using fences.
         */
-       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * HZ,
                    (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
                      - *sequence) <= (1 << 23)));
 
@@ -151,7 +151,7 @@ int mga_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-       DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+       init_waitqueue_head(&dev_priv->fence_queue);
 
        /* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
         * in mga_enable_vblank.
index 37cc2fb4eadd9a033316f5951eddc81f8fb072e0..314685b7f41fc4acb21a2c9c0cad86ecbd1ccad2 100644 (file)
@@ -1029,7 +1029,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index 801731aeab61cddf3db56419dea57f5240ed5994..9f9780b7ddf0be7d3a82ba77205d21d29984b02f 100644 (file)
@@ -22,8 +22,10 @@ static void mga_hide_cursor(struct mga_device *mdev)
 {
        WREG8(MGA_CURPOSXL, 0);
        WREG8(MGA_CURPOSXH, 0);
-       mgag200_bo_unpin(mdev->cursor.pixels_1);
-       mgag200_bo_unpin(mdev->cursor.pixels_2);
+       if (mdev->cursor.pixels_1->pin_count)
+               mgag200_bo_unpin(mdev->cursor.pixels_1);
+       if (mdev->cursor.pixels_2->pin_count)
+               mgag200_bo_unpin(mdev->cursor.pixels_2);
 }
 
 int mga_crtc_cursor_set(struct drm_crtc *crtc,
@@ -32,7 +34,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
                        uint32_t width,
                        uint32_t height)
 {
-       struct drm_device *dev = (struct drm_device *)file_priv->minor->dev;
+       struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = (struct mga_device *)dev->dev_private;
        struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;
        struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;
index 964f58cee5ea67b37f02e680b0f1ab7ebb3e5ed3..005b60aa2a004c45317002a2dcf509e567206622 100644 (file)
@@ -282,6 +282,11 @@ int mgag200_fbdev_init(struct mga_device *mdev)
 {
        struct mga_fbdev *mfbdev;
        int ret;
+       int bpp_sel = 32;
+
+       /* prefer 16bpp on low end gpus with limited VRAM */
+       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+               bpp_sel = 16;
 
        mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL);
        if (!mfbdev)
@@ -301,7 +306,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)
        /* disable all the possible outputs/crtcs before entering KMS mode */
        drm_helper_disable_unused_functions(mdev->dev);
 
-       drm_fb_helper_initial_config(&mfbdev->helper, 32);
+       drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
 
        return 0;
 }
index b1120cb1db6d76b76fd38afd3279a3684e6b188b..26868e5c55b076352188d34962b928a87a64d1a9 100644 (file)
@@ -217,7 +217,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
        dev->mode_config.funcs = (void *)&mga_mode_funcs;
-       dev->mode_config.preferred_depth = 24;
+       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+               dev->mode_config.preferred_depth = 16;
+       else
+               dev->mode_config.preferred_depth = 24;
        dev->mode_config.prefer_shadow = 1;
 
        r = mgag200_modeset_init(mdev);
@@ -310,7 +313,7 @@ int mgag200_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void mgag200_bo_unref(struct mgag200_bo **bo)
+static void mgag200_bo_unref(struct mgag200_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index ee6ed633b7b1c1bb34ac6b59ec85db52c69a4f27..b8583f275e80519dd46d922d1f5c1a0ed9c8bcbf 100644 (file)
@@ -691,7 +691,7 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
    CRTCEXT0 has to be programmed last to trigger an update and make the
    new addr variable take effect.
  */
-void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
+static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
 {
        struct mga_device *mdev = crtc->dev->dev_private;
        u32 addr;
@@ -1398,7 +1398,7 @@ static void mga_encoder_commit(struct drm_encoder *encoder)
 {
 }
 
-void mga_encoder_destroy(struct drm_encoder *encoder)
+static void mga_encoder_destroy(struct drm_encoder *encoder)
 {
        struct mga_encoder *mga_encoder = to_mga_encoder(encoder);
        drm_encoder_cleanup(encoder);
@@ -1558,7 +1558,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-struct drm_encoder *mga_connector_best_encoder(struct drm_connector
+static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
                                                  *connector)
 {
        int enc_id = connector->encoder_ids[0];
index 07b192fe15c6c6f9d0c23434280972616693ca48..adb5166a5dfdbe3a77e4e7154411e5162df1abd3 100644 (file)
@@ -80,7 +80,7 @@ static int mgag200_ttm_global_init(struct mga_device *ast)
        return 0;
 }
 
-void
+static void
 mgag200_ttm_global_release(struct mga_device *ast)
 {
        if (ast->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
+static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &mgag200_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func mgag200_tt_backend_func = {
 };
 
 
-struct ttm_tt *mgag200_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
index f39ab7554fc992175630831acf28bbf223cd9f50..bb103fb4519ead8c9c1e698a341d50273fc5da94 100644 (file)
@@ -2,8 +2,7 @@
 config DRM_MSM
        tristate "MSM DRM"
        depends on DRM
-       depends on ARCH_MSM
-       depends on ARCH_MSM8960
+       depends on (ARCH_MSM && ARCH_MSM8960) || (ARM && COMPILE_TEST)
        select DRM_KMS_HELPER
        select SHMEM
        select TMPFS
index e5fa12b0d21eca645a2cc5efa8f74bef595ad2bb..4f977a593bea13334aebca905c87be43223b2e06 100644 (file)
@@ -12,18 +12,27 @@ msm-y := \
        hdmi/hdmi_i2c.o \
        hdmi/hdmi_phy_8960.o \
        hdmi/hdmi_phy_8x60.o \
-       mdp4/mdp4_crtc.o \
-       mdp4/mdp4_dtv_encoder.o \
-       mdp4/mdp4_format.o \
-       mdp4/mdp4_irq.o \
-       mdp4/mdp4_kms.o \
-       mdp4/mdp4_plane.o \
+       hdmi/hdmi_phy_8x74.o \
+       mdp/mdp_format.o \
+       mdp/mdp_kms.o \
+       mdp/mdp4/mdp4_crtc.o \
+       mdp/mdp4/mdp4_dtv_encoder.o \
+       mdp/mdp4/mdp4_irq.o \
+       mdp/mdp4/mdp4_kms.o \
+       mdp/mdp4/mdp4_plane.o \
+       mdp/mdp5/mdp5_crtc.o \
+       mdp/mdp5/mdp5_encoder.o \
+       mdp/mdp5/mdp5_irq.o \
+       mdp/mdp5/mdp5_kms.o \
+       mdp/mdp5/mdp5_plane.o \
+       mdp/mdp5/mdp5_smp.o \
        msm_drv.o \
        msm_fb.o \
        msm_gem.o \
        msm_gem_prime.o \
        msm_gem_submit.o \
        msm_gpu.o \
+       msm_iommu.o \
        msm_ringbuffer.o
 
 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
index e036f6c1db9447180ddca1a518174ec692d94738..9c4255b980218c229ae5f40a7c89c8445435d43a 100644 (file)
@@ -4,7 +4,7 @@ In the current snapdragon SoC's, we have (at least) 3 different
 display controller blocks at play:
  + MDP3 - ?? seems to be what is on geeksphone peak device
  + MDP4 - S3 (APQ8060, touchpad), S4-pro (APQ8064, nexus4 & ifc6410)
- + MDSS - snapdragon 800
+ + MDP5 - snapdragon 800
 
 (I don't have a completely clear picture on which display controller
 maps to which part #)
@@ -46,6 +46,24 @@ and treat the MDP4 block's irq as "the" irq.  Even though the connectors
 may have their own irqs which they install themselves.  For this reason
 the display controller is the "master" device.
 
+For MDP5, the mapping is:
+
+  plane   -> PIPE{RGBn,VIGn}             \
+  crtc    -> LM (layer mixer)            |-> MDP "device"
+  encoder -> INTF                        /
+  connector -> HDMI/DSI/eDP/etc          --> other device(s)
+
+Unlike MDP4, it appears we can get by with a single encoder, rather
+than needing a different implementation for DTV, DSI, etc.  (Ie. the
+register interface is same, just different bases.)
+
+Also unlike MDP4, with MDP5 all the IRQs for other blocks (HDMI, DSI,
+etc) are routed through MDP.
+
+And finally, MDP5 has this "Shared Memory Pool" (called "SMP"), from
+which blocks need to be allocated to the active pipes based on fetch
+stride.
+
 Each connector probably ends up being a separate device, just for the
 logistics of finding/mapping io region, irq, etc.  Idealy we would
 have a better way than just stashing the platform device in a global
index 9588098741b5b7f76e379d715eb358bfa78d92f0..85d615e7d62fb75789a127fcc021c111a0baa74e 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -202,6 +203,12 @@ enum a2xx_rb_copy_sample_select {
        SAMPLE_0123 = 6,
 };
 
+enum adreno_mmu_clnt_beh {
+       BEH_NEVR = 0,
+       BEH_TRAN_RNG = 1,
+       BEH_TRAN_FLT = 2,
+};
+
 enum sq_tex_clamp {
        SQ_TEX_WRAP = 0,
        SQ_TEX_MIRROR = 1,
@@ -238,6 +245,92 @@ enum sq_tex_filter {
 
 #define REG_A2XX_CP_PFP_UCODE_DATA                             0x000000c1
 
+#define REG_A2XX_MH_MMU_CONFIG                                 0x00000040
+#define A2XX_MH_MMU_CONFIG_MMU_ENABLE                          0x00000001
+#define A2XX_MH_MMU_CONFIG_SPLIT_MODE_ENABLE                   0x00000002
+#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK            0x00000030
+#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT           4
+static inline uint32_t A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK            0x000000c0
+#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT           6
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK           0x00000300
+#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT          8
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK           0x00000c00
+#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT          10
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK           0x00003000
+#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT          12
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK           0x0000c000
+#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT          14
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK           0x00030000
+#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT          16
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK          0x000c0000
+#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT         18
+static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK          0x00300000
+#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT         20
+static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK            0x00c00000
+#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT           22
+static inline uint32_t A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK            0x03000000
+#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT           24
+static inline uint32_t A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK;
+}
+
+#define REG_A2XX_MH_MMU_VA_RANGE                               0x00000041
+
+#define REG_A2XX_MH_MMU_PT_BASE                                        0x00000042
+
+#define REG_A2XX_MH_MMU_PAGE_FAULT                             0x00000043
+
+#define REG_A2XX_MH_MMU_TRAN_ERROR                             0x00000044
+
+#define REG_A2XX_MH_MMU_INVALIDATE                             0x00000045
+
+#define REG_A2XX_MH_MMU_MPU_BASE                               0x00000046
+
+#define REG_A2XX_MH_MMU_MPU_END                                        0x00000047
+
+#define REG_A2XX_NQWAIT_UNTIL                                  0x00000394
+
 #define REG_A2XX_RBBM_PERFCOUNTER1_SELECT                      0x00000395
 
 #define REG_A2XX_RBBM_PERFCOUNTER1_LO                          0x00000397
@@ -276,20 +369,6 @@ enum sq_tex_filter {
 
 #define REG_A2XX_CP_PERFCOUNTER_HI                             0x00000447
 
-#define REG_A2XX_CP_ST_BASE                                    0x0000044d
-
-#define REG_A2XX_CP_ST_BUFSZ                                   0x0000044e
-
-#define REG_A2XX_CP_IB1_BASE                                   0x00000458
-
-#define REG_A2XX_CP_IB1_BUFSZ                                  0x00000459
-
-#define REG_A2XX_CP_IB2_BASE                                   0x0000045a
-
-#define REG_A2XX_CP_IB2_BUFSZ                                  0x0000045b
-
-#define REG_A2XX_CP_STAT                                       0x0000047f
-
 #define REG_A2XX_RBBM_STATUS                                   0x000005d0
 #define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__MASK                   0x0000001f
 #define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__SHIFT                  0
@@ -808,6 +887,12 @@ static inline uint32_t A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(uint32_t val)
 
 #define REG_A2XX_SQ_VS_PROGRAM                                 0x000021f7
 
+#define REG_A2XX_VGT_EVENT_INITIATOR                           0x000021f9
+
+#define REG_A2XX_VGT_DRAW_INITIATOR                            0x000021fc
+
+#define REG_A2XX_VGT_IMMED_DATA                                        0x000021fd
+
 #define REG_A2XX_RB_DEPTHCONTROL                               0x00002200
 #define A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE                    0x00000001
 #define A2XX_RB_DEPTHCONTROL_Z_ENABLE                          0x00000002
index d4afdf6575597f0dd4d06ed2eac5fc09b2cad076..a7be56163d2324f4a24ae7e4836168f95db967a2 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -292,6 +293,8 @@ enum a3xx_tex_type {
 #define A3XX_RBBM_STATUS_GPU_BUSY_NOHC                         0x40000000
 #define A3XX_RBBM_STATUS_GPU_BUSY                              0x80000000
 
+#define REG_A3XX_RBBM_NQWAIT_UNTIL                             0x00000040
+
 #define REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL                     0x00000033
 
 #define REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL                   0x00000050
@@ -304,6 +307,8 @@ enum a3xx_tex_type {
 
 #define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL3                 0x0000005a
 
+#define REG_A3XX_RBBM_INT_SET_CMD                              0x00000060
+
 #define REG_A3XX_RBBM_INT_CLEAR_CMD                            0x00000061
 
 #define REG_A3XX_RBBM_INT_0_MASK                               0x00000063
@@ -937,13 +942,13 @@ static inline uint32_t A3XX_RB_BLEND_ALPHA_FLOAT(float val)
        return ((util_float_to_half(val)) << A3XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A3XX_RB_BLEND_ALPHA_FLOAT__MASK;
 }
 
-#define REG_A3XX_UNKNOWN_20E8                                  0x000020e8
+#define REG_A3XX_RB_CLEAR_COLOR_DW0                            0x000020e8
 
-#define REG_A3XX_UNKNOWN_20E9                                  0x000020e9
+#define REG_A3XX_RB_CLEAR_COLOR_DW1                            0x000020e9
 
-#define REG_A3XX_UNKNOWN_20EA                                  0x000020ea
+#define REG_A3XX_RB_CLEAR_COLOR_DW2                            0x000020ea
 
-#define REG_A3XX_UNKNOWN_20EB                                  0x000020eb
+#define REG_A3XX_RB_CLEAR_COLOR_DW3                            0x000020eb
 
 #define REG_A3XX_RB_COPY_CONTROL                               0x000020ec
 #define A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK                        0x00000003
@@ -1026,7 +1031,7 @@ static inline uint32_t A3XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
 #define A3XX_RB_DEPTH_CONTROL_BF_ENABLE                                0x00000080
 #define A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE                    0x80000000
 
-#define REG_A3XX_UNKNOWN_2101                                  0x00002101
+#define REG_A3XX_RB_DEPTH_CLEAR                                        0x00002101
 
 #define REG_A3XX_RB_DEPTH_INFO                                 0x00002102
 #define A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK                  0x00000001
@@ -1103,11 +1108,11 @@ static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op v
        return ((val) << A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
 }
 
-#define REG_A3XX_UNKNOWN_2105                                  0x00002105
+#define REG_A3XX_RB_STENCIL_CLEAR                              0x00002105
 
-#define REG_A3XX_UNKNOWN_2106                                  0x00002106
+#define REG_A3XX_RB_STENCIL_BUF_INFO                           0x00002106
 
-#define REG_A3XX_UNKNOWN_2107                                  0x00002107
+#define REG_A3XX_RB_STENCIL_BUF_PITCH                          0x00002107
 
 #define REG_A3XX_RB_STENCILREFMASK                             0x00002108
 #define A3XX_RB_STENCILREFMASK_STENCILREF__MASK                        0x000000ff
@@ -1149,20 +1154,31 @@ static inline uint32_t A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(uint32_t val)
        return ((val) << A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT) & A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK;
 }
 
-#define REG_A3XX_PA_SC_WINDOW_OFFSET                           0x0000210e
-#define A3XX_PA_SC_WINDOW_OFFSET_X__MASK                       0x0000ffff
-#define A3XX_PA_SC_WINDOW_OFFSET_X__SHIFT                      0
-static inline uint32_t A3XX_PA_SC_WINDOW_OFFSET_X(uint32_t val)
+#define REG_A3XX_RB_LRZ_VSC_CONTROL                            0x0000210c
+#define A3XX_RB_LRZ_VSC_CONTROL_BINNING_ENABLE                 0x00000002
+
+#define REG_A3XX_RB_WINDOW_OFFSET                              0x0000210e
+#define A3XX_RB_WINDOW_OFFSET_X__MASK                          0x0000ffff
+#define A3XX_RB_WINDOW_OFFSET_X__SHIFT                         0
+static inline uint32_t A3XX_RB_WINDOW_OFFSET_X(uint32_t val)
 {
-       return ((val) << A3XX_PA_SC_WINDOW_OFFSET_X__SHIFT) & A3XX_PA_SC_WINDOW_OFFSET_X__MASK;
+       return ((val) << A3XX_RB_WINDOW_OFFSET_X__SHIFT) & A3XX_RB_WINDOW_OFFSET_X__MASK;
 }
-#define A3XX_PA_SC_WINDOW_OFFSET_Y__MASK                       0xffff0000
-#define A3XX_PA_SC_WINDOW_OFFSET_Y__SHIFT                      16
-static inline uint32_t A3XX_PA_SC_WINDOW_OFFSET_Y(uint32_t val)
+#define A3XX_RB_WINDOW_OFFSET_Y__MASK                          0xffff0000
+#define A3XX_RB_WINDOW_OFFSET_Y__SHIFT                         16
+static inline uint32_t A3XX_RB_WINDOW_OFFSET_Y(uint32_t val)
 {
-       return ((val) << A3XX_PA_SC_WINDOW_OFFSET_Y__SHIFT) & A3XX_PA_SC_WINDOW_OFFSET_Y__MASK;
+       return ((val) << A3XX_RB_WINDOW_OFFSET_Y__SHIFT) & A3XX_RB_WINDOW_OFFSET_Y__MASK;
 }
 
+#define REG_A3XX_RB_SAMPLE_COUNT_CONTROL                       0x00002110
+
+#define REG_A3XX_RB_SAMPLE_COUNT_ADDR                          0x00002111
+
+#define REG_A3XX_RB_Z_CLAMP_MIN                                        0x00002114
+
+#define REG_A3XX_RB_Z_CLAMP_MAX                                        0x00002115
+
 #define REG_A3XX_PC_VSTREAM_CONTROL                            0x000021e4
 
 #define REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL                    0x000021ea
@@ -1309,6 +1325,8 @@ static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
 
 #define REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG                    0x00002215
 
+#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG                    0x00002216
+
 #define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG                    0x00002217
 
 #define REG_A3XX_HLSQ_CL_WG_OFFSET_REG                         0x0000221a
@@ -1491,12 +1509,13 @@ static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0
 
 #define REG_A3XX_SP_SP_CTRL_REG                                        0x000022c0
 #define A3XX_SP_SP_CTRL_REG_RESOLVE                            0x00010000
-#define A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK                    0x000c0000
+#define A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK                    0x00040000
 #define A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT                   18
 static inline uint32_t A3XX_SP_SP_CTRL_REG_CONSTMODE(uint32_t val)
 {
        return ((val) << A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK;
 }
+#define A3XX_SP_SP_CTRL_REG_BINNING                            0x00080000
 #define A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK                    0x00300000
 #define A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT                   20
 static inline uint32_t A3XX_SP_SP_CTRL_REG_SLEEPMODE(uint32_t val)
@@ -1669,7 +1688,7 @@ static inline uint32_t A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 
 #define REG_A3XX_SP_VS_OBJ_START_REG                           0x000022d5
 
-#define REG_A3XX_SP_VS_PVT_MEM_CTRL_REG                                0x000022d6
+#define REG_A3XX_SP_VS_PVT_MEM_PARAM_REG                       0x000022d6
 
 #define REG_A3XX_SP_VS_PVT_MEM_ADDR_REG                                0x000022d7
 
@@ -1772,7 +1791,7 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 
 #define REG_A3XX_SP_FS_OBJ_START_REG                           0x000022e3
 
-#define REG_A3XX_SP_FS_PVT_MEM_CTRL_REG                                0x000022e4
+#define REG_A3XX_SP_FS_PVT_MEM_PARAM_REG                       0x000022e4
 
 #define REG_A3XX_SP_FS_PVT_MEM_ADDR_REG                                0x000022e5
 
@@ -1943,6 +1962,9 @@ static inline uint32_t REG_A3XX_VSC_PIPE_DATA_ADDRESS(uint32_t i0) { return 0x00
 
 static inline uint32_t REG_A3XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x00000c08 + 0x3*i0; }
 
+#define REG_A3XX_VSC_BIN_CONTROL                               0x00000c3c
+#define A3XX_VSC_BIN_CONTROL_BINNING_ENABLE                    0x00000001
+
 #define REG_A3XX_UNKNOWN_0C3D                                  0x00000c3d
 
 #define REG_A3XX_PC_PERFCOUNTER0_SELECT                                0x00000c48
@@ -1953,7 +1975,7 @@ static inline uint32_t REG_A3XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x000
 
 #define REG_A3XX_PC_PERFCOUNTER3_SELECT                                0x00000c4b
 
-#define REG_A3XX_UNKNOWN_0C81                                  0x00000c81
+#define REG_A3XX_GRAS_TSE_DEBUG_ECO                            0x00000c81
 
 #define REG_A3XX_GRAS_PERFCOUNTER0_SELECT                      0x00000c88
 
@@ -1975,22 +1997,24 @@ static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_W(uint32_t i0) { return 0x000
 
 #define REG_A3XX_RB_GMEM_BASE_ADDR                             0x00000cc0
 
+#define REG_A3XX_RB_DEBUG_ECO_CONTROLS_ADDR                    0x00000cc1
+
 #define REG_A3XX_RB_PERFCOUNTER0_SELECT                                0x00000cc6
 
 #define REG_A3XX_RB_PERFCOUNTER1_SELECT                                0x00000cc7
 
-#define REG_A3XX_RB_WINDOW_SIZE                                        0x00000ce0
-#define A3XX_RB_WINDOW_SIZE_WIDTH__MASK                                0x00003fff
-#define A3XX_RB_WINDOW_SIZE_WIDTH__SHIFT                       0
-static inline uint32_t A3XX_RB_WINDOW_SIZE_WIDTH(uint32_t val)
+#define REG_A3XX_RB_FRAME_BUFFER_DIMENSION                     0x00000ce0
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK             0x00003fff
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT            0
+static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(uint32_t val)
 {
-       return ((val) << A3XX_RB_WINDOW_SIZE_WIDTH__SHIFT) & A3XX_RB_WINDOW_SIZE_WIDTH__MASK;
+       return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK;
 }
-#define A3XX_RB_WINDOW_SIZE_HEIGHT__MASK                       0x0fffc000
-#define A3XX_RB_WINDOW_SIZE_HEIGHT__SHIFT                      14
-static inline uint32_t A3XX_RB_WINDOW_SIZE_HEIGHT(uint32_t val)
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK            0x0fffc000
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT           14
+static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(uint32_t val)
 {
-       return ((val) << A3XX_RB_WINDOW_SIZE_HEIGHT__SHIFT) & A3XX_RB_WINDOW_SIZE_HEIGHT__MASK;
+       return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK;
 }
 
 #define REG_A3XX_HLSQ_PERFCOUNTER0_SELECT                      0x00000e00
@@ -2088,6 +2112,14 @@ static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(enum a3xx_cache_op
 
 #define REG_A3XX_TP_PERFCOUNTER5_SELECT                                0x00000f09
 
+#define REG_A3XX_VGT_CL_INITIATOR                              0x000021f0
+
+#define REG_A3XX_VGT_EVENT_INITIATOR                           0x000021f9
+
+#define REG_A3XX_VGT_DRAW_INITIATOR                            0x000021fc
+
+#define REG_A3XX_VGT_IMMED_DATA                                        0x000021fd
+
 #define REG_A3XX_TEX_SAMP_0                                    0x00000000
 #define A3XX_TEX_SAMP_0_MIPFILTER_LINEAR                       0x00000002
 #define A3XX_TEX_SAMP_0_XY_MAG__MASK                           0x0000000c
@@ -2123,6 +2155,18 @@ static inline uint32_t A3XX_TEX_SAMP_0_WRAP_R(enum a3xx_tex_clamp val)
 #define A3XX_TEX_SAMP_0_UNNORM_COORDS                          0x80000000
 
 #define REG_A3XX_TEX_SAMP_1                                    0x00000001
+#define A3XX_TEX_SAMP_1_MAX_LOD__MASK                          0x003ff000
+#define A3XX_TEX_SAMP_1_MAX_LOD__SHIFT                         12
+static inline uint32_t A3XX_TEX_SAMP_1_MAX_LOD(float val)
+{
+       return ((((uint32_t)(val * 12.0))) << A3XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A3XX_TEX_SAMP_1_MAX_LOD__MASK;
+}
+#define A3XX_TEX_SAMP_1_MIN_LOD__MASK                          0xffc00000
+#define A3XX_TEX_SAMP_1_MIN_LOD__SHIFT                         22
+static inline uint32_t A3XX_TEX_SAMP_1_MIN_LOD(float val)
+{
+       return ((((uint32_t)(val * 12.0))) << A3XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A3XX_TEX_SAMP_1_MIN_LOD__MASK;
+}
 
 #define REG_A3XX_TEX_CONST_0                                   0x00000000
 #define A3XX_TEX_CONST_0_TILED                                 0x00000001
index 035bd13dc8bdc3ab039bc2f1bab291cbf4c9bf17..461df93e825edf81e98d22683cfbf4fe7b4404aa 100644 (file)
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef CONFIG_MSM_OCMEM
+#  include <mach/ocmem.h>
+#endif
+
 #include "a3xx_gpu.h"
 
 #define A3XX_INT0_MASK \
@@ -63,6 +67,7 @@ static void a3xx_me_init(struct msm_gpu *gpu)
 static int a3xx_hw_init(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+       struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
        uint32_t *ptr, len;
        int i, ret;
 
@@ -105,6 +110,21 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
 
+       } else if (adreno_is_a330v2(adreno_gpu)) {
+               /*
+                * Most of the VBIF registers on 8974v2 have the correct
+                * values at power on, so we won't modify those if we don't
+                * need to
+                */
+               /* Enable 1k sort: */
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
+               /* Enable WR-REQ: */
+               gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
+               gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
+               /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
+               gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
+
        } else if (adreno_is_a330(adreno_gpu)) {
                /* Set up 16 deep read/write request queues: */
                gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
@@ -121,10 +141,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
                /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
                gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
                /* Set up AOOO: */
-               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000ffff);
-               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0xffffffff);
+               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
+               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
                /* Enable 1K sort: */
-               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001ffff);
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
                /* Disable VBIF clock gating. This is to enable AXI running
                 * higher frequency than GPU:
@@ -162,14 +182,23 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
 
        /* Enable Clock gating: */
-       gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
-
-       /* Set the OCMEM base address for A330 */
-//TODO:
-//     if (adreno_is_a330(adreno_gpu)) {
-//             gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
-//                     (unsigned int)(a3xx_gpu->ocmem_base >> 14));
-//     }
+       if (adreno_is_a320(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
+       else if (adreno_is_a330v2(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
+       else if (adreno_is_a330(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
+
+       if (adreno_is_a330v2(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
+       else if (adreno_is_a330(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
+
+       /* Set the OCMEM base address for A330, etc */
+       if (a3xx_gpu->ocmem_hdl) {
+               gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
+                       (unsigned int)(a3xx_gpu->ocmem_base >> 14));
+       }
 
        /* Turn on performance counters: */
        gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
@@ -219,7 +248,7 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        /* Load PM4: */
        ptr = (uint32_t *)(adreno_gpu->pm4->data);
        len = adreno_gpu->pm4->size / 4;
-       DBG("loading PM4 ucode version: %u", ptr[0]);
+       DBG("loading PM4 ucode version: %x", ptr[1]);
 
        gpu_write(gpu, REG_AXXX_CP_DEBUG,
                        AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
@@ -231,19 +260,26 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        /* Load PFP: */
        ptr = (uint32_t *)(adreno_gpu->pfp->data);
        len = adreno_gpu->pfp->size / 4;
-       DBG("loading PFP ucode version: %u", ptr[0]);
+       DBG("loading PFP ucode version: %x", ptr[5]);
 
        gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
        for (i = 1; i < len; i++)
                gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
 
        /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
-       if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu))
+       if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
                gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
-
+       } else if (adreno_is_a330(adreno_gpu)) {
+               /* NOTE: this (value take from downstream android driver)
+                * includes some bits outside of the known bitfields.  But
+                * A330 has this "MERCIU queue" thing too, which might
+                * explain a new bitfield or reshuffling:
+                */
+               gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
+       }
 
        /* clear ME_HALT to start micro engine */
        gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
@@ -253,6 +289,14 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        return 0;
 }
 
+static void a3xx_recover(struct msm_gpu *gpu)
+{
+       gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
+       gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
+       gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
+       adreno_recover(gpu);
+}
+
 static void a3xx_destroy(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -261,6 +305,12 @@ static void a3xx_destroy(struct msm_gpu *gpu)
        DBG("%s", gpu->name);
 
        adreno_gpu_cleanup(adreno_gpu);
+
+#ifdef CONFIG_MSM_OCMEM
+       if (a3xx_gpu->ocmem_base)
+               ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
+#endif
+
        put_device(&a3xx_gpu->pdev->dev);
        kfree(a3xx_gpu);
 }
@@ -371,7 +421,7 @@ static const struct adreno_gpu_funcs funcs = {
                .hw_init = a3xx_hw_init,
                .pm_suspend = msm_gpu_pm_suspend,
                .pm_resume = msm_gpu_pm_resume,
-               .recover = adreno_recover,
+               .recover = a3xx_recover,
                .last_fence = adreno_last_fence,
                .submit = adreno_submit,
                .flush = adreno_flush,
@@ -387,6 +437,7 @@ static const struct adreno_gpu_funcs funcs = {
 struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
 {
        struct a3xx_gpu *a3xx_gpu = NULL;
+       struct adreno_gpu *adreno_gpu;
        struct msm_gpu *gpu;
        struct platform_device *pdev = a3xx_pdev;
        struct adreno_platform_config *config;
@@ -406,7 +457,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
                goto fail;
        }
 
-       gpu = &a3xx_gpu->base.base;
+       adreno_gpu = &a3xx_gpu->base;
+       gpu = &adreno_gpu->base;
 
        get_device(&pdev->dev);
        a3xx_gpu->pdev = pdev;
@@ -414,16 +466,46 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
        gpu->fast_rate = config->fast_rate;
        gpu->slow_rate = config->slow_rate;
        gpu->bus_freq  = config->bus_freq;
+#ifdef CONFIG_MSM_BUS_SCALING
+       gpu->bus_scale_table = config->bus_scale_table;
+#endif
 
        DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
                        gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
 
-       ret = adreno_gpu_init(dev, pdev, &a3xx_gpu->base,
-                       &funcs, config->rev);
+       ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev);
        if (ret)
                goto fail;
 
-       return &a3xx_gpu->base.base;
+       /* if needed, allocate gmem: */
+       if (adreno_is_a330(adreno_gpu)) {
+#ifdef CONFIG_MSM_OCMEM
+               /* TODO this is different/missing upstream: */
+               struct ocmem_buf *ocmem_hdl =
+                               ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
+
+               a3xx_gpu->ocmem_hdl = ocmem_hdl;
+               a3xx_gpu->ocmem_base = ocmem_hdl->addr;
+               adreno_gpu->gmem = ocmem_hdl->len;
+               DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
+                               a3xx_gpu->ocmem_base);
+#endif
+       }
+
+       if (!gpu->mmu) {
+               /* TODO we think it is possible to configure the GPU to
+                * restrict access to VRAM carveout.  But the required
+                * registers are unknown.  For now just bail out and
+                * limp along with just modesetting.  If it turns out
+                * to not be possible to restrict access, then we must
+                * implement a cmdstream validator.
+                */
+               dev_err(dev->dev, "No memory protection without IOMMU\n");
+               ret = -ENXIO;
+               goto fail;
+       }
+
+       return gpu;
 
 fail:
        if (a3xx_gpu)
@@ -436,19 +518,59 @@ fail:
  * The a3xx device:
  */
 
+#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
+#  include <mach/kgsl.h>
+#endif
+
 static int a3xx_probe(struct platform_device *pdev)
 {
        static struct adreno_platform_config config = {};
 #ifdef CONFIG_OF
-       /* TODO */
+       struct device_node *child, *node = pdev->dev.of_node;
+       u32 val;
+       int ret;
+
+       ret = of_property_read_u32(node, "qcom,chipid", &val);
+       if (ret) {
+               dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
+               return ret;
+       }
+
+       config.rev = ADRENO_REV((val >> 24) & 0xff,
+                       (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
+
+       /* find clock rates: */
+       config.fast_rate = 0;
+       config.slow_rate = ~0;
+       for_each_child_of_node(node, child) {
+               if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
+                       struct device_node *pwrlvl;
+                       for_each_child_of_node(child, pwrlvl) {
+                               ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
+                               if (ret) {
+                                       dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
+                                       return ret;
+                               }
+                               config.fast_rate = max(config.fast_rate, val);
+                               config.slow_rate = min(config.slow_rate, val);
+                       }
+               }
+       }
+
+       if (!config.fast_rate) {
+               dev_err(&pdev->dev, "could not find clk rates\n");
+               return -ENXIO;
+       }
+
 #else
+       struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
        uint32_t version = socinfo_get_version();
        if (cpu_is_apq8064ab()) {
                config.fast_rate = 450000000;
                config.slow_rate = 27000000;
                config.bus_freq  = 4;
                config.rev = ADRENO_REV(3, 2, 1, 0);
-       } else if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+       } else if (cpu_is_apq8064()) {
                config.fast_rate = 400000000;
                config.slow_rate = 27000000;
                config.bus_freq  = 4;
@@ -461,6 +583,16 @@ static int a3xx_probe(struct platform_device *pdev)
                else
                        config.rev = ADRENO_REV(3, 2, 0, 0);
 
+       } else if (cpu_is_msm8960ab()) {
+               config.fast_rate = 400000000;
+               config.slow_rate = 320000000;
+               config.bus_freq  = 4;
+
+               if (SOCINFO_VERSION_MINOR(version) == 0)
+                       config.rev = ADRENO_REV(3, 2, 1, 0);
+               else
+                       config.rev = ADRENO_REV(3, 2, 1, 1);
+
        } else if (cpu_is_msm8930()) {
                config.fast_rate = 400000000;
                config.slow_rate = 27000000;
@@ -473,6 +605,9 @@ static int a3xx_probe(struct platform_device *pdev)
                        config.rev = ADRENO_REV(3, 0, 5, 0);
 
        }
+#  ifdef CONFIG_MSM_BUS_SCALING
+       config.bus_scale_table = pdata->bus_scale_table;
+#  endif
 #endif
        pdev->dev.platform_data = &config;
        a3xx_pdev = pdev;
@@ -485,10 +620,19 @@ static int a3xx_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,kgsl-3d0" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver a3xx_driver = {
        .probe = a3xx_probe,
        .remove = a3xx_remove,
-       .driver.name = "kgsl-3d0",
+       .driver = {
+               .name = "kgsl-3d0",
+               .of_match_table = dt_match,
+       },
 };
 
 void __init a3xx_register(void)
index 32c398c2d00a7103a64a0e76f248b0ce4a712db0..bb9a8ca0507b3cdf4a16be9d59383459d6ff4c13 100644 (file)
 struct a3xx_gpu {
        struct adreno_gpu base;
        struct platform_device *pdev;
+
+       /* if OCMEM is used for GMEM: */
+       uint32_t ocmem_base;
+       void *ocmem_hdl;
 };
 #define to_a3xx_gpu(x) container_of(x, struct a3xx_gpu, base)
 
index 33dcc606c7c556a55a8e463d87bf56a0368c6363..d6e6ce2d1abde84742d02a0e950911fb1a401f8d 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -115,96 +116,6 @@ enum adreno_rb_depth_format {
        DEPTHX_24_8 = 1,
 };
 
-enum adreno_mmu_clnt_beh {
-       BEH_NEVR = 0,
-       BEH_TRAN_RNG = 1,
-       BEH_TRAN_FLT = 2,
-};
-
-#define REG_AXXX_MH_MMU_CONFIG                                 0x00000040
-#define AXXX_MH_MMU_CONFIG_MMU_ENABLE                          0x00000001
-#define AXXX_MH_MMU_CONFIG_SPLIT_MODE_ENABLE                   0x00000002
-#define AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK            0x00000030
-#define AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT           4
-static inline uint32_t AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK            0x000000c0
-#define AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT           6
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK           0x00000300
-#define AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT          8
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK           0x00000c00
-#define AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT          10
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK           0x00003000
-#define AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT          12
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK           0x0000c000
-#define AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT          14
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK           0x00030000
-#define AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT          16
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK          0x000c0000
-#define AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT         18
-static inline uint32_t AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK          0x00300000
-#define AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT         20
-static inline uint32_t AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK            0x00c00000
-#define AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT           22
-static inline uint32_t AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK            0x03000000
-#define AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT           24
-static inline uint32_t AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK;
-}
-
-#define REG_AXXX_MH_MMU_VA_RANGE                               0x00000041
-
-#define REG_AXXX_MH_MMU_PT_BASE                                        0x00000042
-
-#define REG_AXXX_MH_MMU_PAGE_FAULT                             0x00000043
-
-#define REG_AXXX_MH_MMU_TRAN_ERROR                             0x00000044
-
-#define REG_AXXX_MH_MMU_INVALIDATE                             0x00000045
-
-#define REG_AXXX_MH_MMU_MPU_BASE                               0x00000046
-
-#define REG_AXXX_MH_MMU_MPU_END                                        0x00000047
-
 #define REG_AXXX_CP_RB_BASE                                    0x000001c0
 
 #define REG_AXXX_CP_RB_CNTL                                    0x000001c1
@@ -275,6 +186,18 @@ static inline uint32_t AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(uint32_t val)
 }
 
 #define REG_AXXX_CP_MEQ_THRESHOLDS                             0x000001d6
+#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK                   0x001f0000
+#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT                  16
+static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_MEQ_END(uint32_t val)
+{
+       return ((val) << AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK;
+}
+#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK                   0x1f000000
+#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT                  24
+static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_ROQ_END(uint32_t val)
+{
+       return ((val) << AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK;
+}
 
 #define REG_AXXX_CP_CSQ_AVAIL                                  0x000001d7
 #define AXXX_CP_CSQ_AVAIL_RING__MASK                           0x0000007f
@@ -402,6 +325,36 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
        return ((val) << AXXX_CP_CSQ_IB2_STAT_WPTR__SHIFT) & AXXX_CP_CSQ_IB2_STAT_WPTR__MASK;
 }
 
+#define REG_AXXX_CP_NON_PREFETCH_CNTRS                         0x00000440
+
+#define REG_AXXX_CP_STQ_ST_STAT                                        0x00000443
+
+#define REG_AXXX_CP_ST_BASE                                    0x0000044d
+
+#define REG_AXXX_CP_ST_BUFSZ                                   0x0000044e
+
+#define REG_AXXX_CP_MEQ_STAT                                   0x0000044f
+
+#define REG_AXXX_CP_MIU_TAG_STAT                               0x00000452
+
+#define REG_AXXX_CP_BIN_MASK_LO                                        0x00000454
+
+#define REG_AXXX_CP_BIN_MASK_HI                                        0x00000455
+
+#define REG_AXXX_CP_BIN_SELECT_LO                              0x00000456
+
+#define REG_AXXX_CP_BIN_SELECT_HI                              0x00000457
+
+#define REG_AXXX_CP_IB1_BASE                                   0x00000458
+
+#define REG_AXXX_CP_IB1_BUFSZ                                  0x00000459
+
+#define REG_AXXX_CP_IB2_BASE                                   0x0000045a
+
+#define REG_AXXX_CP_IB2_BUFSZ                                  0x0000045b
+
+#define REG_AXXX_CP_STAT                                       0x0000047f
+
 #define REG_AXXX_CP_SCRATCH_REG0                               0x00000578
 
 #define REG_AXXX_CP_SCRATCH_REG1                               0x00000579
@@ -418,6 +371,26 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
 
 #define REG_AXXX_CP_SCRATCH_REG7                               0x0000057f
 
+#define REG_AXXX_CP_ME_VS_EVENT_SRC                            0x00000600
+
+#define REG_AXXX_CP_ME_VS_EVENT_ADDR                           0x00000601
+
+#define REG_AXXX_CP_ME_VS_EVENT_DATA                           0x00000602
+
+#define REG_AXXX_CP_ME_VS_EVENT_ADDR_SWM                       0x00000603
+
+#define REG_AXXX_CP_ME_VS_EVENT_DATA_SWM                       0x00000604
+
+#define REG_AXXX_CP_ME_PS_EVENT_SRC                            0x00000605
+
+#define REG_AXXX_CP_ME_PS_EVENT_ADDR                           0x00000606
+
+#define REG_AXXX_CP_ME_PS_EVENT_DATA                           0x00000607
+
+#define REG_AXXX_CP_ME_PS_EVENT_ADDR_SWM                       0x00000608
+
+#define REG_AXXX_CP_ME_PS_EVENT_DATA_SWM                       0x00000609
+
 #define REG_AXXX_CP_ME_CF_EVENT_SRC                            0x0000060a
 
 #define REG_AXXX_CP_ME_CF_EVENT_ADDR                           0x0000060b
@@ -428,5 +401,11 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
 
 #define REG_AXXX_CP_ME_NRT_DATA                                        0x0000060e
 
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_SRC                       0x00000612
+
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_ADDR                      0x00000613
+
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_DATA                      0x00000614
+
 
 #endif /* ADRENO_COMMON_XML */
index a0b9d8a95b16c17ad6b11ae1b6da662e80484b04..d321099abdd45ac17b37bc32ae8399ce95bc6f32 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "adreno_gpu.h"
 #include "msm_gem.h"
+#include "msm_mmu.h"
 
 struct adreno_info {
        struct adreno_rev rev;
@@ -44,7 +45,7 @@ static const struct adreno_info gpulist[] = {
                .pfpfw = "a300_pfp.fw",
                .gmem  = SZ_512K,
        }, {
-               .rev   = ADRENO_REV(3, 3, 0, 0),
+               .rev   = ADRENO_REV(3, 3, 0, ANY_ID),
                .revn  = 330,
                .name  = "A330",
                .pm4fw = "a330_pm4.fw",
@@ -53,6 +54,11 @@ static const struct adreno_info gpulist[] = {
        },
 };
 
+MODULE_FIRMWARE("a300_pm4.fw");
+MODULE_FIRMWARE("a300_pfp.fw");
+MODULE_FIRMWARE("a330_pm4.fw");
+MODULE_FIRMWARE("a330_pfp.fw");
+
 #define RB_SIZE    SZ_32K
 #define RB_BLKSIZE 16
 
@@ -65,7 +71,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
                *value = adreno_gpu->info->revn;
                return 0;
        case MSM_PARAM_GMEM_SIZE:
-               *value = adreno_gpu->info->gmem;
+               *value = adreno_gpu->gmem;
                return 0;
        default:
                DBG("%s: invalid param: %u", gpu->name, param);
@@ -86,7 +92,7 @@ int adreno_hw_init(struct msm_gpu *gpu)
        gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
                        /* size is log2(quad-words): */
                        AXXX_CP_RB_CNTL_BUFSZ(ilog2(gpu->rb->size / 8)) |
-                       AXXX_CP_RB_CNTL_BLKSZ(RB_BLKSIZE));
+                       AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8)));
 
        /* Setup ringbuffer address: */
        gpu_write(gpu, REG_AXXX_CP_RB_BASE, gpu->rb_iova);
@@ -286,6 +292,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs,
                struct adreno_rev rev)
 {
+       struct msm_mmu *mmu;
        int i, ret;
 
        /* identify gpu: */
@@ -311,6 +318,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                        rev.core, rev.major, rev.minor, rev.patchid);
 
        gpu->funcs = funcs;
+       gpu->gmem = gpu->info->gmem;
        gpu->rev = rev;
 
        ret = request_firmware(&gpu->pm4, gpu->info->pm4fw, drm->dev);
@@ -333,10 +341,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        if (ret)
                return ret;
 
-       ret = msm_iommu_attach(drm, gpu->base.iommu,
-                       iommu_ports, ARRAY_SIZE(iommu_ports));
-       if (ret)
-               return ret;
+       mmu = gpu->base.mmu;
+       if (mmu) {
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       return ret;
+       }
 
        gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs),
                        MSM_BO_UNCACHED);
index f73abfba7c22eb03b4aa0c7f1e962ade219edf1f..ca11ea4da165082fd3ab2f2ecae981d5cd7543ad 100644 (file)
@@ -51,6 +51,7 @@ struct adreno_gpu {
        struct msm_gpu base;
        struct adreno_rev rev;
        const struct adreno_info *info;
+       uint32_t gmem;  /* actual gmem size */
        uint32_t revn;  /* numeric revision name */
        const struct adreno_gpu_funcs *funcs;
 
@@ -70,6 +71,9 @@ struct adreno_gpu {
 struct adreno_platform_config {
        struct adreno_rev rev;
        uint32_t fast_rate, slow_rate, bus_freq;
+#ifdef CONFIG_MSM_BUS_SCALING
+       struct msm_bus_scale_pdata *bus_scale_table;
+#endif
 };
 
 #define ADRENO_IDLE_TIMEOUT (20 * 1000)
@@ -94,6 +98,11 @@ static inline bool adreno_is_a330(struct adreno_gpu *gpu)
        return gpu->revn == 330;
 }
 
+static inline bool adreno_is_a330v2(struct adreno_gpu *gpu)
+{
+       return adreno_is_a330(gpu) && (gpu->rev.patchid > 0);
+}
+
 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
 int adreno_hw_init(struct msm_gpu *gpu);
 uint32_t adreno_last_fence(struct msm_gpu *gpu);
index 259ad709b0cc0467d1a4e6a55435e63ea4cb3415..ae992c71703f1ccc5151b1cf72b904c89e1cd8ec 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -66,13 +67,15 @@ enum vgt_event_type {
 
 enum pc_di_primtype {
        DI_PT_NONE = 0,
-       DI_PT_POINTLIST = 1,
+       DI_PT_POINTLIST_A2XX = 1,
        DI_PT_LINELIST = 2,
        DI_PT_LINESTRIP = 3,
        DI_PT_TRILIST = 4,
        DI_PT_TRIFAN = 5,
        DI_PT_TRISTRIP = 6,
+       DI_PT_LINELOOP = 7,
        DI_PT_RECTLIST = 8,
+       DI_PT_POINTLIST_A3XX = 9,
        DI_PT_QUADLIST = 13,
        DI_PT_QUADSTRIP = 14,
        DI_PT_POLYGON = 15,
@@ -119,7 +122,7 @@ enum adreno_pm4_type3_packets {
        CP_WAIT_FOR_IDLE = 38,
        CP_WAIT_REG_MEM = 60,
        CP_WAIT_REG_EQ = 82,
-       CP_WAT_REG_GTE = 83,
+       CP_WAIT_REG_GTE = 83,
        CP_WAIT_UNTIL_READ = 92,
        CP_WAIT_IB_PFD_COMPLETE = 93,
        CP_REG_RMW = 33,
@@ -151,7 +154,6 @@ enum adreno_pm4_type3_packets {
        CP_CONTEXT_UPDATE = 94,
        CP_INTERRUPT = 64,
        CP_IM_STORE = 44,
-       CP_SET_BIN_BASE_OFFSET = 75,
        CP_SET_DRAW_INIT_FLAGS = 75,
        CP_SET_PROTECTED_MODE = 95,
        CP_LOAD_STATE = 48,
@@ -159,6 +161,16 @@ enum adreno_pm4_type3_packets {
        CP_COND_INDIRECT_BUFFER_PFD = 50,
        CP_INDIRECT_BUFFER_PFE = 63,
        CP_SET_BIN = 76,
+       CP_TEST_TWO_MEMS = 113,
+       CP_WAIT_FOR_ME = 19,
+       IN_IB_PREFETCH_END = 23,
+       IN_SUBBLK_PREFETCH = 31,
+       IN_INSTR_PREFETCH = 32,
+       IN_INSTR_MATCH = 71,
+       IN_CONST_PREFETCH = 73,
+       IN_INCR_UPDT_STATE = 85,
+       IN_INCR_UPDT_CONST = 86,
+       IN_INCR_UPDT_INSTR = 87,
 };
 
 enum adreno_state_block {
index 6d4c62bf70dc482cf9f38ea1739046cb19732943..87be647e3825f0ad96491f5df5b8cf271158f848 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index d1df38bf574783bf98c39253315e3810527d1377..747a6ef4211f71748e759343213ce7ecdc5fb335 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index 0030a111302dae44c6a4ecc0e21d5aa9e7364032..48e03acf19bf5bdf61659c96acd4444e6c716c73 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index 50d11df35b21f1cac9ac15d41f649015a664cfbf..6f1588aa9071f8db8642dcb8b32e46642381b38d 100644 (file)
@@ -41,7 +41,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
                        power_on ? "Enable" : "Disable", ctrl);
 }
 
-static irqreturn_t hdmi_irq(int irq, void *dev_id)
+irqreturn_t hdmi_irq(int irq, void *dev_id)
 {
        struct hdmi *hdmi = dev_id;
 
@@ -71,13 +71,13 @@ void hdmi_destroy(struct kref *kref)
 }
 
 /* initialize connector */
-int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
+struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 {
        struct hdmi *hdmi = NULL;
        struct msm_drm_private *priv = dev->dev_private;
        struct platform_device *pdev = hdmi_pdev;
        struct hdmi_platform_config *config;
-       int ret;
+       int i, ret;
 
        if (!pdev) {
                dev_err(dev->dev, "no hdmi device\n");
@@ -99,6 +99,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 
        hdmi->dev = dev;
        hdmi->pdev = pdev;
+       hdmi->config = config;
        hdmi->encoder = encoder;
 
        /* not sure about which phy maps to which msm.. probably I miss some */
@@ -114,44 +115,70 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
                goto fail;
        }
 
-       hdmi->mmio = msm_ioremap(pdev, "hdmi_msm_hdmi_addr", "HDMI");
+       hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
        if (IS_ERR(hdmi->mmio)) {
                ret = PTR_ERR(hdmi->mmio);
                goto fail;
        }
 
-       hdmi->mvs = devm_regulator_get(&pdev->dev, "8901_hdmi_mvs");
-       if (IS_ERR(hdmi->mvs))
-               hdmi->mvs = devm_regulator_get(&pdev->dev, "hdmi_mvs");
-       if (IS_ERR(hdmi->mvs)) {
-               ret = PTR_ERR(hdmi->mvs);
-               dev_err(dev->dev, "failed to get mvs regulator: %d\n", ret);
-               goto fail;
+       BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs));
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               struct regulator *reg;
+
+               reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]);
+               if (IS_ERR(reg)) {
+                       ret = PTR_ERR(reg);
+                       dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->hpd_regs[i] = reg;
        }
 
-       hdmi->mpp0 = devm_regulator_get(&pdev->dev, "8901_mpp0");
-       if (IS_ERR(hdmi->mpp0))
-               hdmi->mpp0 = NULL;
+       BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs));
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               struct regulator *reg;
 
-       hdmi->clk = devm_clk_get(&pdev->dev, "core_clk");
-       if (IS_ERR(hdmi->clk)) {
-               ret = PTR_ERR(hdmi->clk);
-               dev_err(dev->dev, "failed to get 'clk': %d\n", ret);
-               goto fail;
+               reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]);
+               if (IS_ERR(reg)) {
+                       ret = PTR_ERR(reg);
+                       dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->pwr_regs[i] = reg;
        }
 
-       hdmi->m_pclk = devm_clk_get(&pdev->dev, "master_iface_clk");
-       if (IS_ERR(hdmi->m_pclk)) {
-               ret = PTR_ERR(hdmi->m_pclk);
-               dev_err(dev->dev, "failed to get 'm_pclk': %d\n", ret);
-               goto fail;
+       BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks));
+       for (i = 0; i < config->hpd_clk_cnt; i++) {
+               struct clk *clk;
+
+               clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n",
+                                       config->hpd_clk_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->hpd_clks[i] = clk;
        }
 
-       hdmi->s_pclk = devm_clk_get(&pdev->dev, "slave_iface_clk");
-       if (IS_ERR(hdmi->s_pclk)) {
-               ret = PTR_ERR(hdmi->s_pclk);
-               dev_err(dev->dev, "failed to get 's_pclk': %d\n", ret);
-               goto fail;
+       BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks));
+       for (i = 0; i < config->pwr_clk_cnt; i++) {
+               struct clk *clk;
+
+               clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n",
+                                       config->pwr_clk_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->pwr_clks[i] = clk;
        }
 
        hdmi->i2c = hdmi_i2c_init(hdmi);
@@ -178,20 +205,22 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
                goto fail;
        }
 
-       hdmi->irq = platform_get_irq(pdev, 0);
-       if (hdmi->irq < 0) {
-               ret = hdmi->irq;
-               dev_err(dev->dev, "failed to get irq: %d\n", ret);
-               goto fail;
-       }
+       if (!config->shared_irq) {
+               hdmi->irq = platform_get_irq(pdev, 0);
+               if (hdmi->irq < 0) {
+                       ret = hdmi->irq;
+                       dev_err(dev->dev, "failed to get irq: %d\n", ret);
+                       goto fail;
+               }
 
-       ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
-                       NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-                       "hdmi_isr", hdmi);
-       if (ret < 0) {
-               dev_err(dev->dev, "failed to request IRQ%u: %d\n",
-                               hdmi->irq, ret);
-               goto fail;
+               ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
+                               NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                               "hdmi_isr", hdmi);
+               if (ret < 0) {
+                       dev_err(dev->dev, "failed to request IRQ%u: %d\n",
+                                       hdmi->irq, ret);
+                       goto fail;
+               }
        }
 
        encoder->bridge = hdmi->bridge;
@@ -199,7 +228,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
        priv->bridges[priv->num_bridges++]       = hdmi->bridge;
        priv->connectors[priv->num_connectors++] = hdmi->connector;
 
-       return 0;
+       return hdmi;
 
 fail:
        if (hdmi) {
@@ -211,37 +240,100 @@ fail:
                hdmi_destroy(&hdmi->refcount);
        }
 
-       return ret;
+       return ERR_PTR(ret);
 }
 
 /*
  * The hdmi device:
  */
 
+#include <linux/of_gpio.h>
+
 static int hdmi_dev_probe(struct platform_device *pdev)
 {
        static struct hdmi_platform_config config = {};
 #ifdef CONFIG_OF
-       /* TODO */
+       struct device_node *of_node = pdev->dev.of_node;
+
+       int get_gpio(const char *name)
+       {
+               int gpio = of_get_named_gpio(of_node, name, 0);
+               if (gpio < 0) {
+                       dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n",
+                                       name, gpio);
+                       gpio = -1;
+               }
+               return gpio;
+       }
+
+       /* TODO actually use DT.. */
+       static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
+       static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
+       static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
+       static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+
+       config.phy_init      = hdmi_phy_8x74_init;
+       config.mmio_name     = "core_physical";
+       config.hpd_reg_names = hpd_reg_names;
+       config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+       config.pwr_reg_names = pwr_reg_names;
+       config.pwr_reg_cnt   = ARRAY_SIZE(pwr_reg_names);
+       config.hpd_clk_names = hpd_clk_names;
+       config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
+       config.pwr_clk_names = pwr_clk_names;
+       config.pwr_clk_cnt   = ARRAY_SIZE(pwr_clk_names);
+       config.ddc_clk_gpio  = get_gpio("qcom,hdmi-tx-ddc-clk");
+       config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
+       config.hpd_gpio      = get_gpio("qcom,hdmi-tx-hpd");
+       config.mux_en_gpio   = get_gpio("qcom,hdmi-tx-mux-en");
+       config.mux_sel_gpio  = get_gpio("qcom,hdmi-tx-mux-sel");
+       config.shared_irq    = true;
+
 #else
+       static const char *hpd_clk_names[] = {
+                       "core_clk", "master_iface_clk", "slave_iface_clk",
+       };
        if (cpu_is_apq8064()) {
+               static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
                config.phy_init      = hdmi_phy_8960_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 70;
                config.ddc_data_gpio = 71;
                config.hpd_gpio      = 72;
-               config.pmic_gpio     = 13 + NR_GPIO_IRQS;
-       } else if (cpu_is_msm8960()) {
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = 13 + NR_GPIO_IRQS;
+       } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
+               static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
                config.phy_init      = hdmi_phy_8960_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 100;
                config.ddc_data_gpio = 101;
                config.hpd_gpio      = 102;
-               config.pmic_gpio     = -1;
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = -1;
        } else if (cpu_is_msm8x60()) {
+               static const char *hpd_reg_names[] = {
+                               "8901_hdmi_mvs", "8901_mpp0"
+               };
                config.phy_init      = hdmi_phy_8x60_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 170;
                config.ddc_data_gpio = 171;
                config.hpd_gpio      = 172;
-               config.pmic_gpio     = -1;
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = -1;
        }
 #endif
        pdev->dev.platform_data = &config;
@@ -255,10 +347,19 @@ static int hdmi_dev_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,hdmi-tx" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver hdmi_driver = {
        .probe = hdmi_dev_probe,
        .remove = hdmi_dev_remove,
-       .driver.name = "hdmi_msm",
+       .driver = {
+               .name = "hdmi_msm",
+               .of_match_table = dt_match,
+       },
 };
 
 void __init hdmi_register(void)
index 2c2ec566394c7ac314c9bf3e97b70071bfce4d48..41b29add70b1be7a19b480d5a84ba25aeb79518b 100644 (file)
@@ -28,6 +28,7 @@
 
 
 struct hdmi_phy;
+struct hdmi_platform_config;
 
 struct hdmi {
        struct kref refcount;
@@ -35,14 +36,14 @@ struct hdmi {
        struct drm_device *dev;
        struct platform_device *pdev;
 
-       void __iomem *mmio;
+       const struct hdmi_platform_config *config;
 
-       struct regulator *mvs;        /* HDMI_5V */
-       struct regulator *mpp0;       /* External 5V */
+       void __iomem *mmio;
 
-       struct clk *clk;
-       struct clk *m_pclk;
-       struct clk *s_pclk;
+       struct regulator *hpd_regs[2];
+       struct regulator *pwr_regs[2];
+       struct clk *hpd_clks[3];
+       struct clk *pwr_clks[2];
 
        struct hdmi_phy *phy;
        struct i2c_adapter *i2c;
@@ -60,7 +61,29 @@ struct hdmi {
 /* platform config data (ie. from DT, or pdata) */
 struct hdmi_platform_config {
        struct hdmi_phy *(*phy_init)(struct hdmi *hdmi);
-       int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, pmic_gpio;
+       const char *mmio_name;
+
+       /* regulators that need to be on for hpd: */
+       const char **hpd_reg_names;
+       int hpd_reg_cnt;
+
+       /* regulators that need to be on for screen pwr: */
+       const char **pwr_reg_names;
+       int pwr_reg_cnt;
+
+       /* clks that need to be on for hpd: */
+       const char **hpd_clk_names;
+       int hpd_clk_cnt;
+
+       /* clks that need to be on for screen pwr (ie pixel clk): */
+       const char **pwr_clk_names;
+       int pwr_clk_cnt;
+
+       /* gpio's: */
+       int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
+
+       /* older devices had their own irq, mdp5+ it is shared w/ mdp: */
+       bool shared_irq;
 };
 
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
@@ -106,6 +129,7 @@ struct hdmi_phy {
 
 struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi);
 struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);
+struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi);
 
 /*
  * hdmi bridge:
index 4e939f82918c68daee08cc95253eeb25f31c24b8..e2636582cfd753bc2443659ee615db428530e2dc 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -212,6 +214,20 @@ static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state
 #define REG_HDMI_HDCP_RESET                                    0x00000130
 #define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE                   0x00000001
 
+#define REG_HDMI_VENSPEC_INFO0                                 0x0000016c
+
+#define REG_HDMI_VENSPEC_INFO1                                 0x00000170
+
+#define REG_HDMI_VENSPEC_INFO2                                 0x00000174
+
+#define REG_HDMI_VENSPEC_INFO3                                 0x00000178
+
+#define REG_HDMI_VENSPEC_INFO4                                 0x0000017c
+
+#define REG_HDMI_VENSPEC_INFO5                                 0x00000180
+
+#define REG_HDMI_VENSPEC_INFO6                                 0x00000184
+
 #define REG_HDMI_AUDIO_CFG                                     0x000001d0
 #define HDMI_AUDIO_CFG_ENGINE_ENABLE                           0x00000001
 #define HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK                    0x000000f0
@@ -235,6 +251,9 @@ static inline uint32_t HDMI_DDC_CTRL_TRANSACTION_CNT(uint32_t val)
        return ((val) << HDMI_DDC_CTRL_TRANSACTION_CNT__SHIFT) & HDMI_DDC_CTRL_TRANSACTION_CNT__MASK;
 }
 
+#define REG_HDMI_DDC_ARBITRATION                               0x00000210
+#define HDMI_DDC_ARBITRATION_HW_ARBITRATION                    0x00000010
+
 #define REG_HDMI_DDC_INT_CTRL                                  0x00000214
 #define HDMI_DDC_INT_CTRL_SW_DONE_INT                          0x00000001
 #define HDMI_DDC_INT_CTRL_SW_DONE_ACK                          0x00000002
@@ -340,6 +359,20 @@ static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
        return ((val) << HDMI_DDC_REF_REFTIMER__SHIFT) & HDMI_DDC_REF_REFTIMER__MASK;
 }
 
+#define REG_HDMI_CEC_STATUS                                    0x00000298
+
+#define REG_HDMI_CEC_INT                                       0x0000029c
+
+#define REG_HDMI_CEC_ADDR                                      0x000002a0
+
+#define REG_HDMI_CEC_TIME                                      0x000002a4
+
+#define REG_HDMI_CEC_REFTIMER                                  0x000002a8
+
+#define REG_HDMI_CEC_RD_DATA                                   0x000002ac
+
+#define REG_HDMI_CEC_RD_FILTER                                 0x000002b0
+
 #define REG_HDMI_ACTIVE_HSYNC                                  0x000002b4
 #define HDMI_ACTIVE_HSYNC_START__MASK                          0x00000fff
 #define HDMI_ACTIVE_HSYNC_START__SHIFT                         0
@@ -410,17 +443,33 @@ static inline uint32_t HDMI_VSYNC_TOTAL_F2_V_TOTAL(uint32_t val)
 #define HDMI_FRAME_CTRL_HSYNC_LOW                              0x20000000
 #define HDMI_FRAME_CTRL_INTERLACED_EN                          0x80000000
 
+#define REG_HDMI_AUD_INT                                       0x000002cc
+#define HDMI_AUD_INT_AUD_FIFO_URUN_INT                         0x00000001
+#define HDMI_AUD_INT_AUD_FIFO_URAN_MASK                                0x00000002
+#define HDMI_AUD_INT_AUD_SAM_DROP_INT                          0x00000004
+#define HDMI_AUD_INT_AUD_SAM_DROP_MASK                         0x00000008
+
 #define REG_HDMI_PHY_CTRL                                      0x000002d4
 #define HDMI_PHY_CTRL_SW_RESET_PLL                             0x00000001
 #define HDMI_PHY_CTRL_SW_RESET_PLL_LOW                         0x00000002
 #define HDMI_PHY_CTRL_SW_RESET                                 0x00000004
 #define HDMI_PHY_CTRL_SW_RESET_LOW                             0x00000008
 
-#define REG_HDMI_AUD_INT                                       0x000002cc
-#define HDMI_AUD_INT_AUD_FIFO_URUN_INT                         0x00000001
-#define HDMI_AUD_INT_AUD_FIFO_URAN_MASK                                0x00000002
-#define HDMI_AUD_INT_AUD_SAM_DROP_INT                          0x00000004
-#define HDMI_AUD_INT_AUD_SAM_DROP_MASK                         0x00000008
+#define REG_HDMI_CEC_WR_RANGE                                  0x000002dc
+
+#define REG_HDMI_CEC_RD_RANGE                                  0x000002e0
+
+#define REG_HDMI_VERSION                                       0x000002e4
+
+#define REG_HDMI_CEC_COMPL_CTL                                 0x00000360
+
+#define REG_HDMI_CEC_RD_START_RANGE                            0x00000364
+
+#define REG_HDMI_CEC_RD_TOTAL_RANGE                            0x00000368
+
+#define REG_HDMI_CEC_RD_ERR_RESP_LO                            0x0000036c
+
+#define REG_HDMI_CEC_WR_CHECK_CONFIG                           0x00000370
 
 #define REG_HDMI_8x60_PHY_REG0                                 0x00000300
 #define HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK                        0x0000001c
@@ -504,5 +553,23 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
 
 #define REG_HDMI_8960_PHY_REG12                                        0x00000430
 
+#define REG_HDMI_8x74_ANA_CFG0                                 0x00000000
+
+#define REG_HDMI_8x74_ANA_CFG1                                 0x00000004
+
+#define REG_HDMI_8x74_PD_CTRL0                                 0x00000010
+
+#define REG_HDMI_8x74_PD_CTRL1                                 0x00000014
+
+#define REG_HDMI_8x74_BIST_CFG0                                        0x00000034
+
+#define REG_HDMI_8x74_BIST_PATN0                               0x0000003c
+
+#define REG_HDMI_8x74_BIST_PATN1                               0x00000040
+
+#define REG_HDMI_8x74_BIST_PATN2                               0x00000044
+
+#define REG_HDMI_8x74_BIST_PATN3                               0x00000048
+
 
 #endif /* HDMI_XML */
index 5a8ee3473cf5e0e229ec5c94743e4f7749950ea7..7d10e55403c61da733c1e60c7922799063eef79f 100644 (file)
@@ -21,6 +21,7 @@ struct hdmi_bridge {
        struct drm_bridge base;
 
        struct hdmi *hdmi;
+       bool power_on;
 
        unsigned long int pixclock;
 };
@@ -34,6 +35,65 @@ static void hdmi_bridge_destroy(struct drm_bridge *bridge)
        kfree(hdmi_bridge);
 }
 
+static void power_on(struct drm_bridge *bridge)
+{
+       struct drm_device *dev = bridge->dev;
+       struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+       struct hdmi *hdmi = hdmi_bridge->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
+       int i, ret;
+
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               ret = regulator_enable(hdmi->pwr_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+               }
+       }
+
+       if (config->pwr_clk_cnt > 0) {
+               DBG("pixclock: %lu", hdmi_bridge->pixclock);
+               ret = clk_set_rate(hdmi->pwr_clks[0], hdmi_bridge->pixclock);
+               if (ret) {
+                       dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
+                                       config->pwr_clk_names[0], ret);
+               }
+       }
+
+       for (i = 0; i < config->pwr_clk_cnt; i++) {
+               ret = clk_prepare_enable(hdmi->pwr_clks[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable pwr clk: %s (%d)\n",
+                                       config->pwr_clk_names[i], ret);
+               }
+       }
+}
+
+static void power_off(struct drm_bridge *bridge)
+{
+       struct drm_device *dev = bridge->dev;
+       struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+       struct hdmi *hdmi = hdmi_bridge->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
+       int i, ret;
+
+       /* TODO do we need to wait for final vblank somewhere before
+        * cutting the clocks?
+        */
+       mdelay(16 + 4);
+
+       for (i = 0; i < config->pwr_clk_cnt; i++)
+               clk_disable_unprepare(hdmi->pwr_clks[i]);
+
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               ret = regulator_disable(hdmi->pwr_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+               }
+       }
+}
+
 static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
@@ -41,6 +101,12 @@ static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
        struct hdmi_phy *phy = hdmi->phy;
 
        DBG("power up");
+
+       if (!hdmi_bridge->power_on) {
+               power_on(bridge);
+               hdmi_bridge->power_on = true;
+       }
+
        phy->funcs->powerup(phy, hdmi_bridge->pixclock);
        hdmi_set_mode(hdmi, true);
 }
@@ -62,6 +128,11 @@ static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
        DBG("power down");
        hdmi_set_mode(hdmi, false);
        phy->funcs->powerdown(phy);
+
+       if (hdmi_bridge->power_on) {
+               power_off(bridge);
+               hdmi_bridge->power_on = false;
+       }
 }
 
 static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
index 823eee521a31b523e04e7470ab01612cdeb0887e..7dedfdd120759d51c7bd5a940bb01e874b87f579 100644 (file)
 
 #include <linux/gpio.h>
 
+#include "msm_kms.h"
 #include "hdmi.h"
 
 struct hdmi_connector {
        struct drm_connector base;
        struct hdmi *hdmi;
+       struct work_struct hpd_work;
 };
 #define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
 
 static int gpio_config(struct hdmi *hdmi, bool on)
 {
        struct drm_device *dev = hdmi->dev;
-       struct hdmi_platform_config *config =
-                       hdmi->pdev->dev.platform_data;
+       const struct hdmi_platform_config *config = hdmi->config;
        int ret;
 
        if (on) {
@@ -39,26 +40,43 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                                "HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
                        goto error1;
                }
+               gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
+
                ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
                if (ret) {
                        dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
                                "HDMI_DDC_DATA", config->ddc_data_gpio, ret);
                        goto error2;
                }
+               gpio_set_value_cansleep(config->ddc_data_gpio, 1);
+
                ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
                if (ret) {
                        dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
                                "HDMI_HPD", config->hpd_gpio, ret);
                        goto error3;
                }
-               if (config->pmic_gpio != -1) {
-                       ret = gpio_request(config->pmic_gpio, "PMIC_HDMI_MUX_SEL");
+               gpio_direction_input(config->hpd_gpio);
+               gpio_set_value_cansleep(config->hpd_gpio, 1);
+
+               if (config->mux_en_gpio != -1) {
+                       ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
                        if (ret) {
                                dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
-                                       "PMIC_HDMI_MUX_SEL", config->pmic_gpio, ret);
+                                       "HDMI_MUX_SEL", config->mux_en_gpio, ret);
                                goto error4;
                        }
-                       gpio_set_value_cansleep(config->pmic_gpio, 0);
+                       gpio_set_value_cansleep(config->mux_en_gpio, 1);
+               }
+
+               if (config->mux_sel_gpio != -1) {
+                       ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
+                       if (ret) {
+                               dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+                                       "HDMI_MUX_SEL", config->mux_sel_gpio, ret);
+                               goto error5;
+                       }
+                       gpio_set_value_cansleep(config->mux_sel_gpio, 0);
                }
                DBG("gpio on");
        } else {
@@ -66,15 +84,23 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                gpio_free(config->ddc_data_gpio);
                gpio_free(config->hpd_gpio);
 
-               if (config->pmic_gpio != -1) {
-                       gpio_set_value_cansleep(config->pmic_gpio, 1);
-                       gpio_free(config->pmic_gpio);
+               if (config->mux_en_gpio != -1) {
+                       gpio_set_value_cansleep(config->mux_en_gpio, 0);
+                       gpio_free(config->mux_en_gpio);
+               }
+
+               if (config->mux_sel_gpio != -1) {
+                       gpio_set_value_cansleep(config->mux_sel_gpio, 1);
+                       gpio_free(config->mux_sel_gpio);
                }
                DBG("gpio off");
        }
 
        return 0;
 
+error5:
+       if (config->mux_en_gpio != -1)
+               gpio_free(config->mux_en_gpio);
 error4:
        gpio_free(config->hpd_gpio);
 error3:
@@ -88,10 +114,11 @@ error1:
 static int hpd_enable(struct hdmi_connector *hdmi_connector)
 {
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct drm_device *dev = hdmi_connector->base.dev;
        struct hdmi_phy *phy = hdmi->phy;
        uint32_t hpd_ctrl;
-       int ret;
+       int i, ret;
 
        ret = gpio_config(hdmi, true);
        if (ret) {
@@ -99,31 +126,22 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
                goto fail;
        }
 
-       ret = clk_prepare_enable(hdmi->clk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 'clk': %d\n", ret);
-               goto fail;
-       }
-
-       ret = clk_prepare_enable(hdmi->m_pclk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 'm_pclk': %d\n", ret);
-               goto fail;
-       }
-
-       ret = clk_prepare_enable(hdmi->s_pclk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 's_pclk': %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_clk_cnt; i++) {
+               ret = clk_prepare_enable(hdmi->hpd_clks[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n",
+                                       config->hpd_clk_names[i], ret);
+                       goto fail;
+               }
        }
 
-       if (hdmi->mpp0)
-               ret = regulator_enable(hdmi->mpp0);
-       if (!ret)
-               ret = regulator_enable(hdmi->mvs);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable regulators: %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               ret = regulator_enable(hdmi->hpd_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
        }
 
        hdmi_set_mode(hdmi, false);
@@ -156,26 +174,26 @@ fail:
 static int hdp_disable(struct hdmi_connector *hdmi_connector)
 {
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct drm_device *dev = hdmi_connector->base.dev;
-       int ret = 0;
+       int i, ret = 0;
 
        /* Disable HPD interrupt */
        hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
 
        hdmi_set_mode(hdmi, false);
 
-       if (hdmi->mpp0)
-               ret = regulator_disable(hdmi->mpp0);
-       if (!ret)
-               ret = regulator_disable(hdmi->mvs);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable regulators: %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               ret = regulator_disable(hdmi->hpd_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
        }
 
-       clk_disable_unprepare(hdmi->clk);
-       clk_disable_unprepare(hdmi->m_pclk);
-       clk_disable_unprepare(hdmi->s_pclk);
+       for (i = 0; i < config->hpd_clk_cnt; i++)
+               clk_disable_unprepare(hdmi->hpd_clks[i]);
 
        ret = gpio_config(hdmi, false);
        if (ret) {
@@ -189,9 +207,19 @@ fail:
        return ret;
 }
 
+static void
+hotplug_work(struct work_struct *work)
+{
+       struct hdmi_connector *hdmi_connector =
+               container_of(work, struct hdmi_connector, hpd_work);
+       struct drm_connector *connector = &hdmi_connector->base;
+       drm_helper_hpd_irq_event(connector->dev);
+}
+
 void hdmi_connector_irq(struct drm_connector *connector)
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
+       struct msm_drm_private *priv = connector->dev->dev_private;
        struct hdmi *hdmi = hdmi_connector->hdmi;
        uint32_t hpd_int_status, hpd_int_ctrl;
 
@@ -209,13 +237,13 @@ void hdmi_connector_irq(struct drm_connector *connector)
                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
                                hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK);
 
-               drm_helper_hpd_irq_event(connector->dev);
-
                /* detect disconnect if we are connected or visa versa: */
                hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
                if (!detected)
                        hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
+
+               queue_work(priv->wq, &hdmi_connector->hpd_work);
        }
 }
 
@@ -224,6 +252,7 @@ static enum drm_connector_status hdmi_connector_detect(
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        uint32_t hpd_int_status;
        int retry = 20;
 
@@ -233,6 +262,14 @@ static enum drm_connector_status hdmi_connector_detect(
         * let that trick us into thinking the monitor is gone:
         */
        while (retry-- && !(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED)) {
+               /* hdmi debounce logic seems to get stuck sometimes,
+                * read directly the gpio to get a second opinion:
+                */
+               if (gpio_get_value(config->hpd_gpio)) {
+                       DBG("gpio tells us we are connected!");
+                       hpd_int_status |= HDMI_HPD_INT_STATUS_CABLE_DETECTED;
+                       break;
+               }
                mdelay(10);
                hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
                DBG("status=%08x", hpd_int_status);
@@ -285,6 +322,8 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
+       struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct msm_drm_private *priv = connector->dev->dev_private;
        struct msm_kms *kms = priv->kms;
        long actual, requested;
@@ -293,6 +332,13 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector,
        actual = kms->funcs->round_pixclk(kms,
                        requested, hdmi_connector->hdmi->encoder);
 
+       /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
+        * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
+        * instead):
+        */
+       if (config->pwr_clk_cnt > 0)
+               actual = clk_round_rate(hdmi->pwr_clks[0], actual);
+
        DBG("requested=%ld, actual=%ld", requested, actual);
 
        if (actual != requested)
@@ -335,6 +381,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
        }
 
        hdmi_connector->hdmi = hdmi_reference(hdmi);
+       INIT_WORK(&hdmi_connector->hpd_work, hotplug_work);
 
        connector = &hdmi_connector->base;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c
new file mode 100644 (file)
index 0000000..59fa6cd
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "hdmi.h"
+
+struct hdmi_phy_8x74 {
+       struct hdmi_phy base;
+       struct hdmi *hdmi;
+       void __iomem *mmio;
+};
+#define to_hdmi_phy_8x74(x) container_of(x, struct hdmi_phy_8x74, base)
+
+
+static void phy_write(struct hdmi_phy_8x74 *phy, u32 reg, u32 data)
+{
+       msm_writel(data, phy->mmio + reg);
+}
+
+//static u32 phy_read(struct hdmi_phy_8x74 *phy, u32 reg)
+//{
+//     return msm_readl(phy->mmio + reg);
+//}
+
+static void hdmi_phy_8x74_destroy(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       kfree(phy_8x74);
+}
+
+static void hdmi_phy_8x74_reset(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       struct hdmi *hdmi = phy_8x74->hdmi;
+       unsigned int val;
+
+       /* NOTE that HDMI_PHY_CTL is in core mmio, not phy mmio: */
+
+       val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+
+       msleep(100);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+}
+
+static void hdmi_phy_8x74_powerup(struct hdmi_phy *phy,
+               unsigned long int pixclock)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+
+       phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG0,   0x1b);
+       phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG1,   0xf2);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_CFG0,  0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN0, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN1, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN2, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN3, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL1,   0x20);
+}
+
+static void hdmi_phy_8x74_powerdown(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL0, 0x7f);
+}
+
+static const struct hdmi_phy_funcs hdmi_phy_8x74_funcs = {
+               .destroy = hdmi_phy_8x74_destroy,
+               .reset = hdmi_phy_8x74_reset,
+               .powerup = hdmi_phy_8x74_powerup,
+               .powerdown = hdmi_phy_8x74_powerdown,
+};
+
+struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi)
+{
+       struct hdmi_phy_8x74 *phy_8x74;
+       struct hdmi_phy *phy = NULL;
+       int ret;
+
+       phy_8x74 = kzalloc(sizeof(*phy_8x74), GFP_KERNEL);
+       if (!phy_8x74) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       phy = &phy_8x74->base;
+
+       phy->funcs = &hdmi_phy_8x74_funcs;
+
+       phy_8x74->hdmi = hdmi;
+
+       /* for 8x74, the phy mmio is mapped separately: */
+       phy_8x74->mmio = msm_ioremap(hdmi->pdev,
+                       "phy_physical", "HDMI_8x74");
+       if (IS_ERR(phy_8x74->mmio)) {
+               ret = PTR_ERR(phy_8x74->mmio);
+               goto fail;
+       }
+
+       return phy;
+
+fail:
+       if (phy)
+               hdmi_phy_8x74_destroy(phy);
+       return ERR_PTR(ret);
+}
index dbde4f6339b9f82b257c2d3ba24cc534d066760e..d591567173c405226eea5fc9d06b4591887f29d1 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
similarity index 94%
rename from drivers/gpu/drm/msm/mdp4/mdp4.xml.h
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 9908ffe1c3ad093f7f73bdac19cd34a9abc6e450..416a26e1e58d1f7cdbbf401220a9928a80721a9e 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -42,27 +44,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
 
-enum mdp4_bpc {
-       BPC1 = 0,
-       BPC5 = 1,
-       BPC6 = 2,
-       BPC8 = 3,
-};
-
-enum mdp4_bpc_alpha {
-       BPC1A = 0,
-       BPC4A = 1,
-       BPC6A = 2,
-       BPC8A = 3,
-};
-
-enum mdp4_alpha_type {
-       FG_CONST = 0,
-       BG_CONST = 1,
-       FG_PIXEL = 2,
-       BG_PIXEL = 3,
-};
-
 enum mdp4_pipe {
        VG1 = 0,
        VG2 = 1,
@@ -79,15 +60,6 @@ enum mdp4_mixer {
        MIXER2 = 2,
 };
 
-enum mdp4_mixer_stage_id {
-       STAGE_UNUSED = 0,
-       STAGE_BASE = 1,
-       STAGE0 = 2,
-       STAGE1 = 3,
-       STAGE2 = 4,
-       STAGE3 = 5,
-};
-
 enum mdp4_intf {
        INTF_LCDC_DTV = 0,
        INTF_DSI_VIDEO = 1,
@@ -194,56 +166,56 @@ static inline uint32_t MDP4_DISP_INTF_SEL_EXT(enum mdp4_intf val)
 #define REG_MDP4_LAYERMIXER2_IN_CFG                            0x000100f0
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK                    0x00000007
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT                   0
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE0(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE0(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE0_MIXER1                   0x00000008
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK                    0x00000070
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT                   4
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE1(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE1(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE1_MIXER1                   0x00000080
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK                    0x00000700
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT                   8
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE2(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE2(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE2_MIXER1                   0x00000800
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK                    0x00007000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT                   12
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE3(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE3(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE3_MIXER1                   0x00008000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK                    0x00070000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT                   16
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE4(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE4(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE4_MIXER1                   0x00080000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK                    0x00700000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT                   20
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE5(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE5(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE5_MIXER1                   0x00800000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK                    0x07000000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT                   24
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE6(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE6(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK;
 }
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE6_MIXER1                   0x08000000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK                    0x70000000
 #define MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT                   28
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE7(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE7(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK;
 }
@@ -254,56 +226,56 @@ static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE7(enum mdp4_mixer_stage_id va
 #define REG_MDP4_LAYERMIXER_IN_CFG                             0x00010100
 #define MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK                     0x00000007
 #define MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT                    0
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE0(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE0(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1                    0x00000008
 #define MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK                     0x00000070
 #define MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT                    4
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE1(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE1(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1                    0x00000080
 #define MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK                     0x00000700
 #define MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT                    8
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE2(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE2(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1                    0x00000800
 #define MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK                     0x00007000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT                    12
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE3(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE3(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1                    0x00008000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK                     0x00070000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT                    16
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE4(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE4(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1                    0x00080000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK                     0x00700000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT                    20
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE5(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE5(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1                    0x00800000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK                     0x07000000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT                    24
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE6(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE6(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK;
 }
 #define MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1                    0x08000000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK                     0x70000000
 #define MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT                    28
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE7(enum mdp4_mixer_stage_id val)
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE7(enum mdp_mixer_stage_id val)
 {
        return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK;
 }
@@ -369,7 +341,7 @@ static inline uint32_t REG_MDP4_OVLP_STAGE(uint32_t i0, uint32_t i1) { return 0x
 static inline uint32_t REG_MDP4_OVLP_STAGE_OP(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE(i1); }
 #define MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK                      0x00000003
 #define MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT                     0
-static inline uint32_t MDP4_OVLP_STAGE_OP_FG_ALPHA(enum mdp4_alpha_type val)
+static inline uint32_t MDP4_OVLP_STAGE_OP_FG_ALPHA(enum mdp_alpha_type val)
 {
        return ((val) << MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK;
 }
@@ -377,7 +349,7 @@ static inline uint32_t MDP4_OVLP_STAGE_OP_FG_ALPHA(enum mdp4_alpha_type val)
 #define MDP4_OVLP_STAGE_OP_FG_MOD_ALPHA                                0x00000008
 #define MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK                      0x00000030
 #define MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT                     4
-static inline uint32_t MDP4_OVLP_STAGE_OP_BG_ALPHA(enum mdp4_alpha_type val)
+static inline uint32_t MDP4_OVLP_STAGE_OP_BG_ALPHA(enum mdp_alpha_type val)
 {
        return ((val) << MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK;
 }
@@ -472,19 +444,19 @@ static inline uint32_t REG_MDP4_DMA(enum mdp4_dma i0) { return 0x00000000 + __of
 static inline uint32_t REG_MDP4_DMA_CONFIG(enum mdp4_dma i0) { return 0x00000000 + __offset_DMA(i0); }
 #define MDP4_DMA_CONFIG_G_BPC__MASK                            0x00000003
 #define MDP4_DMA_CONFIG_G_BPC__SHIFT                           0
-static inline uint32_t MDP4_DMA_CONFIG_G_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_DMA_CONFIG_G_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_DMA_CONFIG_G_BPC__SHIFT) & MDP4_DMA_CONFIG_G_BPC__MASK;
 }
 #define MDP4_DMA_CONFIG_B_BPC__MASK                            0x0000000c
 #define MDP4_DMA_CONFIG_B_BPC__SHIFT                           2
-static inline uint32_t MDP4_DMA_CONFIG_B_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_DMA_CONFIG_B_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_DMA_CONFIG_B_BPC__SHIFT) & MDP4_DMA_CONFIG_B_BPC__MASK;
 }
 #define MDP4_DMA_CONFIG_R_BPC__MASK                            0x00000030
 #define MDP4_DMA_CONFIG_R_BPC__SHIFT                           4
-static inline uint32_t MDP4_DMA_CONFIG_R_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_DMA_CONFIG_R_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_DMA_CONFIG_R_BPC__SHIFT) & MDP4_DMA_CONFIG_R_BPC__MASK;
 }
@@ -710,25 +682,25 @@ static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val)
 static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; }
 #define MDP4_PIPE_SRC_FORMAT_G_BPC__MASK                       0x00000003
 #define MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT                      0
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_G_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_G_BPC__MASK;
 }
 #define MDP4_PIPE_SRC_FORMAT_B_BPC__MASK                       0x0000000c
 #define MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT                      2
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_B_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_B_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_B_BPC__MASK;
 }
 #define MDP4_PIPE_SRC_FORMAT_R_BPC__MASK                       0x00000030
 #define MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT                      4
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_R_BPC(enum mdp4_bpc val)
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_R_BPC(enum mdp_bpc val)
 {
        return ((val) << MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_R_BPC__MASK;
 }
 #define MDP4_PIPE_SRC_FORMAT_A_BPC__MASK                       0x000000c0
 #define MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT                      6
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_A_BPC(enum mdp4_bpc_alpha val)
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_A_BPC(enum mdp_bpc_alpha val)
 {
        return ((val) << MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_A_BPC__MASK;
 }
similarity index 96%
rename from drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 019d530187ff2c52a0523790047b216d51baed16..1964f4f0d452377c87d2e2db4bd218a1f0451ff5 100644 (file)
@@ -66,15 +66,15 @@ struct mdp4_crtc {
        /* for unref'ing cursor bo's after scanout completes: */
        struct drm_flip_work unref_cursor_work;
 
-       struct mdp4_irq vblank;
-       struct mdp4_irq err;
+       struct mdp_irq vblank;
+       struct mdp_irq err;
 };
 #define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)
 
 static struct mdp4_kms *get_kms(struct drm_crtc *crtc)
 {
        struct msm_drm_private *priv = crtc->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
 static void update_fb(struct drm_crtc *crtc, bool async,
@@ -93,7 +93,7 @@ static void update_fb(struct drm_crtc *crtc, bool async,
 
        if (!async) {
                /* enable vblank to pick up the old_fb */
-               mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank);
+               mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
        }
 }
 
@@ -145,7 +145,7 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
 
        atomic_or(pending, &mdp4_crtc->pending);
-       mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank);
+       mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
 }
 
 static void pageflip_cb(struct msm_fence_cb *cb)
@@ -210,9 +210,9 @@ static void mdp4_crtc_dpms(struct drm_crtc *crtc, int mode)
        if (enabled != mdp4_crtc->enabled) {
                if (enabled) {
                        mdp4_enable(mdp4_kms);
-                       mdp4_irq_register(mdp4_kms, &mdp4_crtc->err);
+                       mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err);
                } else {
-                       mdp4_irq_unregister(mdp4_kms, &mdp4_crtc->err);
+                       mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
                        mdp4_disable(mdp4_kms);
                }
                mdp4_crtc->enabled = enabled;
@@ -232,7 +232,7 @@ static void blend_setup(struct drm_crtc *crtc)
        struct mdp4_kms *mdp4_kms = get_kms(crtc);
        int i, ovlp = mdp4_crtc->ovlp;
        uint32_t mixer_cfg = 0;
-       static const enum mdp4_mixer_stage_id stages[] = {
+       static const enum mdp_mixer_stage_id stages[] = {
                        STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
        };
        /* statically (for now) map planes to mixer stage (z-order): */
@@ -262,8 +262,8 @@ static void blend_setup(struct drm_crtc *crtc)
                        enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
                        int idx = idxs[pipe_id];
                        if (idx > 0) {
-                               const struct mdp4_format *format =
-                                       to_mdp4_format(msm_framebuffer_format(plane->fb));
+                               const struct mdp_format *format =
+                                       to_mdp_format(msm_framebuffer_format(plane->fb));
                                alpha[idx-1] = format->alpha_enable;
                        }
                        mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]);
@@ -571,14 +571,14 @@ static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = {
        .load_lut = mdp4_crtc_load_lut,
 };
 
-static void mdp4_crtc_vblank_irq(struct mdp4_irq *irq, uint32_t irqstatus)
+static void mdp4_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
 {
        struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, vblank);
        struct drm_crtc *crtc = &mdp4_crtc->base;
        struct msm_drm_private *priv = crtc->dev->dev_private;
        unsigned pending;
 
-       mdp4_irq_unregister(get_kms(crtc), &mdp4_crtc->vblank);
+       mdp_irq_unregister(&get_kms(crtc)->base, &mdp4_crtc->vblank);
 
        pending = atomic_xchg(&mdp4_crtc->pending, 0);
 
@@ -593,7 +593,7 @@ static void mdp4_crtc_vblank_irq(struct mdp4_irq *irq, uint32_t irqstatus)
        }
 }
 
-static void mdp4_crtc_err_irq(struct mdp4_irq *irq, uint32_t irqstatus)
+static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
 {
        struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, err);
        struct drm_crtc *crtc = &mdp4_crtc->base;
similarity index 98%
rename from drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
index 5e0dcae70ab5d14999e2991c113a5835adda3900..067ed03b35fef964f530746a877efb77bf9fcbe5 100644 (file)
@@ -15,8 +15,6 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <mach/clk.h>
-
 #include "mdp4_kms.h"
 
 #include "drm_crtc.h"
@@ -37,7 +35,7 @@ struct mdp4_dtv_encoder {
 static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
 {
        struct msm_drm_private *priv = encoder->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
 #ifdef CONFIG_MSM_BUS_SCALING
@@ -139,7 +137,7 @@ static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
                 * the settings changes for the new modeset (like new
                 * scanout buffer) don't latch properly..
                 */
-               mdp4_irq_wait(mdp4_kms, MDP4_IRQ_EXTERNAL_VSYNC);
+               mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC);
 
                clk_disable_unprepare(mdp4_dtv_encoder->src_clk);
                clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
new file mode 100644 (file)
index 0000000..c740ccd
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
+#include "mdp4_kms.h"
+
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask);
+}
+
+static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+void mdp4_irq_preinstall(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
+}
+
+int mdp4_irq_postinstall(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(mdp_kms);
+       struct mdp_irq *error_handler = &mdp4_kms->error_handler;
+
+       error_handler->irq = mdp4_irq_error_handler;
+       error_handler->irqmask = MDP4_IRQ_PRIMARY_INTF_UDERRUN |
+                       MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
+
+       mdp_irq_register(mdp_kms, error_handler);
+
+       return 0;
+}
+
+void mdp4_irq_uninstall(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
+}
+
+irqreturn_t mdp4_irq(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(mdp_kms);
+       struct drm_device *dev = mdp4_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       unsigned int id;
+       uint32_t status;
+
+       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS);
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);
+
+       VERB("status=%08x", status);
+
+       for (id = 0; id < priv->num_crtcs; id++)
+               if (status & mdp4_crtc_vblank(priv->crtcs[id]))
+                       drm_handle_vblank(dev, id);
+
+       mdp_dispatch_irqs(mdp_kms, status);
+
+       return IRQ_HANDLED;
+}
+
+int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp4_crtc_vblank(crtc), true);
+       return 0;
+}
+
+void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp4_crtc_vblank(crtc), false);
+}
similarity index 89%
rename from drivers/gpu/drm/msm/mdp4/mdp4_kms.c
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 8972ac35a43dab9f1006641e69734d1c9c0c40d4..272e707c948704e6ff36cc8df263723fdbbd2a71 100644 (file)
 
 
 #include "msm_drv.h"
+#include "msm_mmu.h"
 #include "mdp4_kms.h"
 
 static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev);
 
 static int mdp4_hw_init(struct msm_kms *kms)
 {
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
        struct drm_device *dev = mdp4_kms->dev;
        uint32_t version, major, minor, dmap_cfg, vg_cfg;
        unsigned long clk;
@@ -31,12 +32,14 @@ static int mdp4_hw_init(struct msm_kms *kms)
 
        pm_runtime_get_sync(dev->dev);
 
+       mdp4_enable(mdp4_kms);
        version = mdp4_read(mdp4_kms, REG_MDP4_VERSION);
+       mdp4_disable(mdp4_kms);
 
        major = FIELD(version, MDP4_VERSION_MAJOR);
        minor = FIELD(version, MDP4_VERSION_MINOR);
 
-       DBG("found MDP version v%d.%d", major, minor);
+       DBG("found MDP4 version v%d.%d", major, minor);
 
        if (major != 4) {
                dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
@@ -130,7 +133,7 @@ static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
 
 static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
 {
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
        struct msm_drm_private *priv = mdp4_kms->dev->dev_private;
        unsigned i;
 
@@ -140,11 +143,12 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
 
 static void mdp4_destroy(struct msm_kms *kms)
 {
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
        kfree(mdp4_kms);
 }
 
-static const struct msm_kms_funcs kms_funcs = {
+static const struct mdp_kms_funcs kms_funcs = {
+       .base = {
                .hw_init         = mdp4_hw_init,
                .irq_preinstall  = mdp4_irq_preinstall,
                .irq_postinstall = mdp4_irq_postinstall,
@@ -152,10 +156,12 @@ static const struct msm_kms_funcs kms_funcs = {
                .irq             = mdp4_irq,
                .enable_vblank   = mdp4_enable_vblank,
                .disable_vblank  = mdp4_disable_vblank,
-               .get_format      = mdp4_get_format,
+               .get_format      = mdp_get_format,
                .round_pixclk    = mdp4_round_pixclk,
                .preclose        = mdp4_preclose,
                .destroy         = mdp4_destroy,
+       },
+       .set_irqmask         = mdp4_set_irqmask,
 };
 
 int mdp4_disable(struct mdp4_kms *mdp4_kms)
@@ -189,6 +195,7 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
        struct drm_plane *plane;
        struct drm_crtc *crtc;
        struct drm_encoder *encoder;
+       struct hdmi *hdmi;
        int ret;
 
        /*
@@ -238,9 +245,10 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
        encoder->possible_crtcs = 0x1;     /* DTV can be hooked to DMA_E */
        priv->encoders[priv->num_encoders++] = encoder;
 
-       ret = hdmi_init(dev, encoder);
-       if (ret) {
-               dev_err(dev->dev, "failed to initialize HDMI\n");
+       hdmi = hdmi_init(dev, encoder);
+       if (IS_ERR(hdmi)) {
+               ret = PTR_ERR(hdmi);
+               dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
                goto fail;
        }
 
@@ -260,6 +268,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
        struct mdp4_platform_config *config = mdp4_get_config(pdev);
        struct mdp4_kms *mdp4_kms;
        struct msm_kms *kms = NULL;
+       struct msm_mmu *mmu;
        int ret;
 
        mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
@@ -269,8 +278,9 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
                goto fail;
        }
 
-       kms = &mdp4_kms->base;
-       kms->funcs = &kms_funcs;
+       mdp_kms_init(&mdp4_kms->base, &kms_funcs);
+
+       kms = &mdp4_kms->base.base;
 
        mdp4_kms->dev = dev;
 
@@ -322,27 +332,34 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
        clk_set_rate(mdp4_kms->clk, config->max_clk);
        clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
 
-       if (!config->iommu) {
-               dev_err(dev->dev, "no iommu\n");
-               ret = -ENXIO;
-               goto fail;
-       }
-
        /* make sure things are off before attaching iommu (bootloader could
         * have left things on, in which case we'll start getting faults if
         * we don't disable):
         */
+       mdp4_enable(mdp4_kms);
        mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
        mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
        mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0);
+       mdp4_disable(mdp4_kms);
        mdelay(16);
 
-       ret = msm_iommu_attach(dev, config->iommu,
-                       iommu_ports, ARRAY_SIZE(iommu_ports));
-       if (ret)
-               goto fail;
+       if (config->iommu) {
+               mmu = msm_iommu_new(dev, config->iommu);
+               if (IS_ERR(mmu)) {
+                       ret = PTR_ERR(mmu);
+                       goto fail;
+               }
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       goto fail;
+       } else {
+               dev_info(dev->dev, "no iommu, fallback to phys "
+                               "contig buffers for scanout\n");
+               mmu = NULL;
+       }
 
-       mdp4_kms->id = msm_register_iommu(dev, config->iommu);
+       mdp4_kms->id = msm_register_mmu(dev, mmu);
        if (mdp4_kms->id < 0) {
                ret = mdp4_kms->id;
                dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
similarity index 79%
rename from drivers/gpu/drm/msm/mdp4/mdp4_kms.h
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index eb015c834087c00189f9afcbe843ae1b0f0a14db..66a4d31aec80e010e5f5914705f05f7f346dc68c 100644 (file)
 #ifndef __MDP4_KMS_H__
 #define __MDP4_KMS_H__
 
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-
 #include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp/mdp_kms.h"
 #include "mdp4.xml.h"
 
-
-/* For transiently registering for different MDP4 irqs that various parts
- * of the KMS code need during setup/configuration.  We these are not
- * necessarily the same as what drm_vblank_get/put() are requesting, and
- * the hysteresis in drm_vblank_put() is not necessarily desirable for
- * internal housekeeping related irq usage.
- */
-struct mdp4_irq {
-       struct list_head node;
-       uint32_t irqmask;
-       bool registered;
-       void (*irq)(struct mdp4_irq *irq, uint32_t irqstatus);
-};
-
 struct mdp4_kms {
-       struct msm_kms base;
+       struct mdp_kms base;
 
        struct drm_device *dev;
 
@@ -59,11 +43,7 @@ struct mdp4_kms {
        struct clk *pclk;
        struct clk *lut_clk;
 
-       /* irq handling: */
-       bool in_irq;
-       struct list_head irq_list;    /* list of mdp4_irq */
-       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
-       struct mdp4_irq error_handler;
+       struct mdp_irq error_handler;
 };
 #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
 
@@ -73,16 +53,6 @@ struct mdp4_platform_config {
        uint32_t max_clk;
 };
 
-struct mdp4_format {
-       struct msm_format base;
-       enum mdp4_bpc bpc_r, bpc_g, bpc_b;
-       enum mdp4_bpc_alpha bpc_a;
-       uint8_t unpack[4];
-       bool alpha_enable, unpack_tight;
-       uint8_t cpp, unpack_count;
-};
-#define to_mdp4_format(x) container_of(x, struct mdp4_format, base)
-
 static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data)
 {
        msm_writel(data, mdp4_kms->mmio + reg);
@@ -134,7 +104,7 @@ static inline uint32_t dma2err(enum mdp4_dma dma)
 }
 
 static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe,
-               enum mdp4_mixer_stage_id stage)
+               enum mdp_mixer_stage_id stage)
 {
        uint32_t mixer_cfg = 0;
 
@@ -178,19 +148,23 @@ static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe,
 int mdp4_disable(struct mdp4_kms *mdp4_kms);
 int mdp4_enable(struct mdp4_kms *mdp4_kms);
 
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
 void mdp4_irq_preinstall(struct msm_kms *kms);
 int mdp4_irq_postinstall(struct msm_kms *kms);
 void mdp4_irq_uninstall(struct msm_kms *kms);
 irqreturn_t mdp4_irq(struct msm_kms *kms);
-void mdp4_irq_wait(struct mdp4_kms *mdp4_kms, uint32_t irqmask);
-void mdp4_irq_register(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq);
-void mdp4_irq_unregister(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq);
 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 
-uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *formats,
-               uint32_t max_formats);
-const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format);
+static inline
+uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
+               uint32_t max_formats)
+{
+       /* TODO when we have YUV, we need to filter supported formats
+        * based on pipe_id..
+        */
+       return mdp_get_formats(pixel_formats, max_formats);
+}
 
 void mdp4_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj);
similarity index 98%
rename from drivers/gpu/drm/msm/mdp4/mdp4_plane.c
rename to drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 0f0af243f6fc41cb030f40985cf3466aed945aa6..2406027200ec597e5d6a10674e82db82f122adff 100644 (file)
@@ -34,7 +34,7 @@ struct mdp4_plane {
 static struct mdp4_kms *get_kms(struct drm_plane *plane)
 {
        struct msm_drm_private *priv = plane->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
 static int mdp4_plane_update(struct drm_plane *plane,
@@ -132,7 +132,7 @@ int mdp4_plane_mode_set(struct drm_plane *plane,
        struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
        struct mdp4_kms *mdp4_kms = get_kms(plane);
        enum mdp4_pipe pipe = mdp4_plane->pipe;
-       const struct mdp4_format *format;
+       const struct mdp_format *format;
        uint32_t op_mode = 0;
        uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
        uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
@@ -175,7 +175,7 @@ int mdp4_plane_mode_set(struct drm_plane *plane,
 
        mdp4_plane_set_scanout(plane, fb);
 
-       format = to_mdp4_format(msm_framebuffer_format(fb));
+       format = to_mdp_format(msm_framebuffer_format(fb));
 
        mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
                        MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
new file mode 100644 (file)
index 0000000..0aa5151
--- /dev/null
@@ -0,0 +1,1036 @@
+#ifndef MDP5_XML
+#define MDP5_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+
+Copyright (C) 2013 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum mdp5_intf {
+       INTF_DSI = 1,
+       INTF_HDMI = 3,
+       INTF_LCDC = 5,
+       INTF_eDP = 9,
+};
+
+enum mdp5_intfnum {
+       NO_INTF = 0,
+       INTF0 = 1,
+       INTF1 = 2,
+       INTF2 = 3,
+       INTF3 = 4,
+};
+
+enum mdp5_pipe {
+       SSPP_VIG0 = 0,
+       SSPP_VIG1 = 1,
+       SSPP_VIG2 = 2,
+       SSPP_RGB0 = 3,
+       SSPP_RGB1 = 4,
+       SSPP_RGB2 = 5,
+       SSPP_DMA0 = 6,
+       SSPP_DMA1 = 7,
+};
+
+enum mdp5_ctl_mode {
+       MODE_NONE = 0,
+       MODE_ROT0 = 1,
+       MODE_ROT1 = 2,
+       MODE_WB0 = 3,
+       MODE_WB1 = 4,
+       MODE_WFD = 5,
+};
+
+enum mdp5_pack_3d {
+       PACK_3D_FRAME_INT = 0,
+       PACK_3D_H_ROW_INT = 1,
+       PACK_3D_V_ROW_INT = 2,
+       PACK_3D_COL_INT = 3,
+};
+
+enum mdp5_chroma_samp_type {
+       CHROMA_RGB = 0,
+       CHROMA_H2V1 = 1,
+       CHROMA_H1V2 = 2,
+       CHROMA_420 = 3,
+};
+
+enum mdp5_scale_filter {
+       SCALE_FILTER_NEAREST = 0,
+       SCALE_FILTER_BIL = 1,
+       SCALE_FILTER_PCMN = 2,
+       SCALE_FILTER_CA = 3,
+};
+
+enum mdp5_pipe_bwc {
+       BWC_LOSSLESS = 0,
+       BWC_Q_HIGH = 1,
+       BWC_Q_MED = 2,
+};
+
+enum mdp5_client_id {
+       CID_UNUSED = 0,
+       CID_VIG0_Y = 1,
+       CID_VIG0_CR = 2,
+       CID_VIG0_CB = 3,
+       CID_VIG1_Y = 4,
+       CID_VIG1_CR = 5,
+       CID_VIG1_CB = 6,
+       CID_VIG2_Y = 7,
+       CID_VIG2_CR = 8,
+       CID_VIG2_CB = 9,
+       CID_DMA0_Y = 10,
+       CID_DMA0_CR = 11,
+       CID_DMA0_CB = 12,
+       CID_DMA1_Y = 13,
+       CID_DMA1_CR = 14,
+       CID_DMA1_CB = 15,
+       CID_RGB0 = 16,
+       CID_RGB1 = 17,
+       CID_RGB2 = 18,
+       CID_MAX = 19,
+};
+
+enum mdp5_igc_type {
+       IGC_VIG = 0,
+       IGC_RGB = 1,
+       IGC_DMA = 2,
+       IGC_DSPP = 3,
+};
+
+#define MDP5_IRQ_INTF0_WB_ROT_COMP                             0x00000001
+#define MDP5_IRQ_INTF1_WB_ROT_COMP                             0x00000002
+#define MDP5_IRQ_INTF2_WB_ROT_COMP                             0x00000004
+#define MDP5_IRQ_INTF3_WB_ROT_COMP                             0x00000008
+#define MDP5_IRQ_INTF0_WB_WFD                                  0x00000010
+#define MDP5_IRQ_INTF1_WB_WFD                                  0x00000020
+#define MDP5_IRQ_INTF2_WB_WFD                                  0x00000040
+#define MDP5_IRQ_INTF3_WB_WFD                                  0x00000080
+#define MDP5_IRQ_INTF0_PING_PONG_COMP                          0x00000100
+#define MDP5_IRQ_INTF1_PING_PONG_COMP                          0x00000200
+#define MDP5_IRQ_INTF2_PING_PONG_COMP                          0x00000400
+#define MDP5_IRQ_INTF3_PING_PONG_COMP                          0x00000800
+#define MDP5_IRQ_INTF0_PING_PONG_RD_PTR                                0x00001000
+#define MDP5_IRQ_INTF1_PING_PONG_RD_PTR                                0x00002000
+#define MDP5_IRQ_INTF2_PING_PONG_RD_PTR                                0x00004000
+#define MDP5_IRQ_INTF3_PING_PONG_RD_PTR                                0x00008000
+#define MDP5_IRQ_INTF0_PING_PONG_WR_PTR                                0x00010000
+#define MDP5_IRQ_INTF1_PING_PONG_WR_PTR                                0x00020000
+#define MDP5_IRQ_INTF2_PING_PONG_WR_PTR                                0x00040000
+#define MDP5_IRQ_INTF3_PING_PONG_WR_PTR                                0x00080000
+#define MDP5_IRQ_INTF0_PING_PONG_AUTO_REF                      0x00100000
+#define MDP5_IRQ_INTF1_PING_PONG_AUTO_REF                      0x00200000
+#define MDP5_IRQ_INTF2_PING_PONG_AUTO_REF                      0x00400000
+#define MDP5_IRQ_INTF3_PING_PONG_AUTO_REF                      0x00800000
+#define MDP5_IRQ_INTF0_UNDER_RUN                               0x01000000
+#define MDP5_IRQ_INTF0_VSYNC                                   0x02000000
+#define MDP5_IRQ_INTF1_UNDER_RUN                               0x04000000
+#define MDP5_IRQ_INTF1_VSYNC                                   0x08000000
+#define MDP5_IRQ_INTF2_UNDER_RUN                               0x10000000
+#define MDP5_IRQ_INTF2_VSYNC                                   0x20000000
+#define MDP5_IRQ_INTF3_UNDER_RUN                               0x40000000
+#define MDP5_IRQ_INTF3_VSYNC                                   0x80000000
+#define REG_MDP5_HW_VERSION                                    0x00000000
+
+#define REG_MDP5_HW_INTR_STATUS                                        0x00000010
+#define MDP5_HW_INTR_STATUS_INTR_MDP                           0x00000001
+#define MDP5_HW_INTR_STATUS_INTR_DSI0                          0x00000010
+#define MDP5_HW_INTR_STATUS_INTR_DSI1                          0x00000020
+#define MDP5_HW_INTR_STATUS_INTR_HDMI                          0x00000100
+#define MDP5_HW_INTR_STATUS_INTR_EDP                           0x00001000
+
+#define REG_MDP5_MDP_VERSION                                   0x00000100
+#define MDP5_MDP_VERSION_MINOR__MASK                           0x00ff0000
+#define MDP5_MDP_VERSION_MINOR__SHIFT                          16
+static inline uint32_t MDP5_MDP_VERSION_MINOR(uint32_t val)
+{
+       return ((val) << MDP5_MDP_VERSION_MINOR__SHIFT) & MDP5_MDP_VERSION_MINOR__MASK;
+}
+#define MDP5_MDP_VERSION_MAJOR__MASK                           0xf0000000
+#define MDP5_MDP_VERSION_MAJOR__SHIFT                          28
+static inline uint32_t MDP5_MDP_VERSION_MAJOR(uint32_t val)
+{
+       return ((val) << MDP5_MDP_VERSION_MAJOR__SHIFT) & MDP5_MDP_VERSION_MAJOR__MASK;
+}
+
+#define REG_MDP5_DISP_INTF_SEL                                 0x00000104
+#define MDP5_DISP_INTF_SEL_INTF0__MASK                         0x000000ff
+#define MDP5_DISP_INTF_SEL_INTF0__SHIFT                                0
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF0(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF0__SHIFT) & MDP5_DISP_INTF_SEL_INTF0__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF1__MASK                         0x0000ff00
+#define MDP5_DISP_INTF_SEL_INTF1__SHIFT                                8
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF1(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF1__SHIFT) & MDP5_DISP_INTF_SEL_INTF1__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF2__MASK                         0x00ff0000
+#define MDP5_DISP_INTF_SEL_INTF2__SHIFT                                16
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF2(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF2__SHIFT) & MDP5_DISP_INTF_SEL_INTF2__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF3__MASK                         0xff000000
+#define MDP5_DISP_INTF_SEL_INTF3__SHIFT                                24
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF3(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF3__SHIFT) & MDP5_DISP_INTF_SEL_INTF3__MASK;
+}
+
+#define REG_MDP5_INTR_EN                                       0x00000110
+
+#define REG_MDP5_INTR_STATUS                                   0x00000114
+
+#define REG_MDP5_INTR_CLEAR                                    0x00000118
+
+#define REG_MDP5_HIST_INTR_EN                                  0x0000011c
+
+#define REG_MDP5_HIST_INTR_STATUS                              0x00000120
+
+#define REG_MDP5_HIST_INTR_CLEAR                               0x00000124
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_W(uint32_t i0) { return 0x00000180 + 0x4*i0; }
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_W_REG(uint32_t i0) { return 0x00000180 + 0x4*i0; }
+#define MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK                     0x000000ff
+#define MDP5_SMP_ALLOC_W_REG_CLIENT0__SHIFT                    0
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT0(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT0__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK;
+}
+#define MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK                     0x0000ff00
+#define MDP5_SMP_ALLOC_W_REG_CLIENT1__SHIFT                    8
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT1(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT1__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK;
+}
+#define MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK                     0x00ff0000
+#define MDP5_SMP_ALLOC_W_REG_CLIENT2__SHIFT                    16
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT2(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT2__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK;
+}
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_R(uint32_t i0) { return 0x00000230 + 0x4*i0; }
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_R_REG(uint32_t i0) { return 0x00000230 + 0x4*i0; }
+#define MDP5_SMP_ALLOC_R_REG_CLIENT0__MASK                     0x000000ff
+#define MDP5_SMP_ALLOC_R_REG_CLIENT0__SHIFT                    0
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT0(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT0__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT0__MASK;
+}
+#define MDP5_SMP_ALLOC_R_REG_CLIENT1__MASK                     0x0000ff00
+#define MDP5_SMP_ALLOC_R_REG_CLIENT1__SHIFT                    8
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT1(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT1__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT1__MASK;
+}
+#define MDP5_SMP_ALLOC_R_REG_CLIENT2__MASK                     0x00ff0000
+#define MDP5_SMP_ALLOC_R_REG_CLIENT2__SHIFT                    16
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT2(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT2__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT2__MASK;
+}
+
+static inline uint32_t __offset_IGC(enum mdp5_igc_type idx)
+{
+       switch (idx) {
+               case IGC_VIG: return 0x00000300;
+               case IGC_RGB: return 0x00000310;
+               case IGC_DMA: return 0x00000320;
+               case IGC_DSPP: return 0x00000400;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP5_IGC(enum mdp5_igc_type i0) { return 0x00000000 + __offset_IGC(i0); }
+
+static inline uint32_t REG_MDP5_IGC_LUT(enum mdp5_igc_type i0, uint32_t i1) { return 0x00000000 + __offset_IGC(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_IGC_LUT_REG(enum mdp5_igc_type i0, uint32_t i1) { return 0x00000000 + __offset_IGC(i0) + 0x4*i1; }
+#define MDP5_IGC_LUT_REG_VAL__MASK                             0x00000fff
+#define MDP5_IGC_LUT_REG_VAL__SHIFT                            0
+static inline uint32_t MDP5_IGC_LUT_REG_VAL(uint32_t val)
+{
+       return ((val) << MDP5_IGC_LUT_REG_VAL__SHIFT) & MDP5_IGC_LUT_REG_VAL__MASK;
+}
+#define MDP5_IGC_LUT_REG_INDEX_UPDATE                          0x02000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_0                                0x10000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_1                                0x20000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_2                                0x40000000
+
+static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000600 + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+#define MDP5_CTL_LAYER_REG_VIG0__MASK                          0x00000007
+#define MDP5_CTL_LAYER_REG_VIG0__SHIFT                         0
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG0__SHIFT) & MDP5_CTL_LAYER_REG_VIG0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_VIG1__MASK                          0x00000038
+#define MDP5_CTL_LAYER_REG_VIG1__SHIFT                         3
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG1__SHIFT) & MDP5_CTL_LAYER_REG_VIG1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_VIG2__MASK                          0x000001c0
+#define MDP5_CTL_LAYER_REG_VIG2__SHIFT                         6
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG2__SHIFT) & MDP5_CTL_LAYER_REG_VIG2__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB0__MASK                          0x00000e00
+#define MDP5_CTL_LAYER_REG_RGB0__SHIFT                         9
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB0__SHIFT) & MDP5_CTL_LAYER_REG_RGB0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB1__MASK                          0x00007000
+#define MDP5_CTL_LAYER_REG_RGB1__SHIFT                         12
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB1__SHIFT) & MDP5_CTL_LAYER_REG_RGB1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB2__MASK                          0x00038000
+#define MDP5_CTL_LAYER_REG_RGB2__SHIFT                         15
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB2__SHIFT) & MDP5_CTL_LAYER_REG_RGB2__MASK;
+}
+#define MDP5_CTL_LAYER_REG_DMA0__MASK                          0x001c0000
+#define MDP5_CTL_LAYER_REG_DMA0__SHIFT                         18
+static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_DMA0__SHIFT) & MDP5_CTL_LAYER_REG_DMA0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_DMA1__MASK                          0x00e00000
+#define MDP5_CTL_LAYER_REG_DMA1__SHIFT                         21
+static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_DMA1__SHIFT) & MDP5_CTL_LAYER_REG_DMA1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_BORDER_COLOR                                0x01000000
+#define MDP5_CTL_LAYER_REG_CURSOR_OUT                          0x02000000
+
+static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000614 + 0x100*i0; }
+#define MDP5_CTL_OP_MODE__MASK                                 0x0000000f
+#define MDP5_CTL_OP_MODE__SHIFT                                        0
+static inline uint32_t MDP5_CTL_OP_MODE(enum mdp5_ctl_mode val)
+{
+       return ((val) << MDP5_CTL_OP_MODE__SHIFT) & MDP5_CTL_OP_MODE__MASK;
+}
+#define MDP5_CTL_OP_INTF_NUM__MASK                             0x00000070
+#define MDP5_CTL_OP_INTF_NUM__SHIFT                            4
+static inline uint32_t MDP5_CTL_OP_INTF_NUM(enum mdp5_intfnum val)
+{
+       return ((val) << MDP5_CTL_OP_INTF_NUM__SHIFT) & MDP5_CTL_OP_INTF_NUM__MASK;
+}
+#define MDP5_CTL_OP_CMD_MODE                                   0x00020000
+#define MDP5_CTL_OP_PACK_3D_ENABLE                             0x00080000
+#define MDP5_CTL_OP_PACK_3D__MASK                              0x00300000
+#define MDP5_CTL_OP_PACK_3D__SHIFT                             20
+static inline uint32_t MDP5_CTL_OP_PACK_3D(enum mdp5_pack_3d val)
+{
+       return ((val) << MDP5_CTL_OP_PACK_3D__SHIFT) & MDP5_CTL_OP_PACK_3D__MASK;
+}
+
+static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000618 + 0x100*i0; }
+#define MDP5_CTL_FLUSH_VIG0                                    0x00000001
+#define MDP5_CTL_FLUSH_VIG1                                    0x00000002
+#define MDP5_CTL_FLUSH_VIG2                                    0x00000004
+#define MDP5_CTL_FLUSH_RGB0                                    0x00000008
+#define MDP5_CTL_FLUSH_RGB1                                    0x00000010
+#define MDP5_CTL_FLUSH_RGB2                                    0x00000020
+#define MDP5_CTL_FLUSH_LM0                                     0x00000040
+#define MDP5_CTL_FLUSH_LM1                                     0x00000080
+#define MDP5_CTL_FLUSH_LM2                                     0x00000100
+#define MDP5_CTL_FLUSH_DMA0                                    0x00000800
+#define MDP5_CTL_FLUSH_DMA1                                    0x00001000
+#define MDP5_CTL_FLUSH_DSPP0                                   0x00002000
+#define MDP5_CTL_FLUSH_DSPP1                                   0x00004000
+#define MDP5_CTL_FLUSH_DSPP2                                   0x00008000
+#define MDP5_CTL_FLUSH_CTL                                     0x00020000
+
+static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000061c + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000620 + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000014c4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000014f0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00001500 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+#define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_SRC_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_SRC_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP5_PIPE_SRC_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00001204 + 0x400*i0; }
+#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK                    0xffff0000
+#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT                   16
+static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK                     0x0000ffff
+#define MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT                    0
+static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00001208 + 0x400*i0; }
+#define MDP5_PIPE_SRC_XY_Y__MASK                               0xffff0000
+#define MDP5_PIPE_SRC_XY_Y__SHIFT                              16
+static inline uint32_t MDP5_PIPE_SRC_XY_Y(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_XY_Y__SHIFT) & MDP5_PIPE_SRC_XY_Y__MASK;
+}
+#define MDP5_PIPE_SRC_XY_X__MASK                               0x0000ffff
+#define MDP5_PIPE_SRC_XY_X__SHIFT                              0
+static inline uint32_t MDP5_PIPE_SRC_XY_X(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_XY_X__SHIFT) & MDP5_PIPE_SRC_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000120c + 0x400*i0; }
+#define MDP5_PIPE_OUT_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP5_PIPE_OUT_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_OUT_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_OUT_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP5_PIPE_OUT_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT) & MDP5_PIPE_OUT_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00001210 + 0x400*i0; }
+#define MDP5_PIPE_OUT_XY_Y__MASK                               0xffff0000
+#define MDP5_PIPE_OUT_XY_Y__SHIFT                              16
+static inline uint32_t MDP5_PIPE_OUT_XY_Y(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_XY_Y__SHIFT) & MDP5_PIPE_OUT_XY_Y__MASK;
+}
+#define MDP5_PIPE_OUT_XY_X__MASK                               0x0000ffff
+#define MDP5_PIPE_OUT_XY_X__SHIFT                              0
+static inline uint32_t MDP5_PIPE_OUT_XY_X(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_XY_X__SHIFT) & MDP5_PIPE_OUT_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00001214 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00001218 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000121c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00001220 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00001224 + 0x400*i0; }
+#define MDP5_PIPE_SRC_STRIDE_A_P0__MASK                                0x0000ffff
+#define MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT                       0
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P0(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P0__MASK;
+}
+#define MDP5_PIPE_SRC_STRIDE_A_P1__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P1(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P1__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00001228 + 0x400*i0; }
+#define MDP5_PIPE_SRC_STRIDE_B_P2__MASK                                0x0000ffff
+#define MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT                       0
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P2(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P2__MASK;
+}
+#define MDP5_PIPE_SRC_STRIDE_B_P3__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P3(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P3__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000122c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00001230 + 0x400*i0; }
+#define MDP5_PIPE_SRC_FORMAT_G_BPC__MASK                       0x00000003
+#define MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT                      0
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_G_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_B_BPC__MASK                       0x0000000c
+#define MDP5_PIPE_SRC_FORMAT_B_BPC__SHIFT                      2
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_B_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_B_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_B_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_R_BPC__MASK                       0x00000030
+#define MDP5_PIPE_SRC_FORMAT_R_BPC__SHIFT                      4
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_R_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_R_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_R_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_A_BPC__MASK                       0x000000c0
+#define MDP5_PIPE_SRC_FORMAT_A_BPC__SHIFT                      6
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_A_BPC(enum mdp_bpc_alpha val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_A_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_A_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_ALPHA_ENABLE                      0x00000100
+#define MDP5_PIPE_SRC_FORMAT_CPP__MASK                         0x00000600
+#define MDP5_PIPE_SRC_FORMAT_CPP__SHIFT                                9
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_CPP(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_CPP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CPP__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_ROT90                             0x00000800
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK                        0x00003000
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT               12
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT) & MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT                      0x00020000
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB                  0x00040000
+#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK                  0x00780000
+#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT                 19
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK                 0x01800000
+#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT                        23
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp5_chroma_samp_type val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00001234 + 0x400*i0; }
+#define MDP5_PIPE_SRC_UNPACK_ELEM0__MASK                       0x000000ff
+#define MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT                      0
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM0__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM1__MASK                       0x0000ff00
+#define MDP5_PIPE_SRC_UNPACK_ELEM1__SHIFT                      8
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM1(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM1__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM1__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM2__MASK                       0x00ff0000
+#define MDP5_PIPE_SRC_UNPACK_ELEM2__SHIFT                      16
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM2(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM2__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM2__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM3__MASK                       0xff000000
+#define MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT                      24
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM3__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00001238 + 0x400*i0; }
+#define MDP5_PIPE_SRC_OP_MODE_BWC_EN                           0x00000001
+#define MDP5_PIPE_SRC_OP_MODE_BWC__MASK                                0x00000006
+#define MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT                       1
+static inline uint32_t MDP5_PIPE_SRC_OP_MODE_BWC(enum mdp5_pipe_bwc val)
+{
+       return ((val) << MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT) & MDP5_PIPE_SRC_OP_MODE_BWC__MASK;
+}
+#define MDP5_PIPE_SRC_OP_MODE_FLIP_LR                          0x00002000
+#define MDP5_PIPE_SRC_OP_MODE_FLIP_UD                          0x00004000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_EN                           0x00010000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_0                                0x00020000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_1                                0x00040000
+#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE                      0x00400000
+#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD                  0x00800000
+
+static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000123c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00001248 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000124c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00001250 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00001254 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00001258 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00001270 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000012a4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000012a8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000012ac + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000012b0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000012b4 + 0x400*i0; }
+#define MDP5_PIPE_DECIMATION_VERT__MASK                                0x000000ff
+#define MDP5_PIPE_DECIMATION_VERT__SHIFT                       0
+static inline uint32_t MDP5_PIPE_DECIMATION_VERT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_DECIMATION_VERT__SHIFT) & MDP5_PIPE_DECIMATION_VERT__MASK;
+}
+#define MDP5_PIPE_DECIMATION_HORZ__MASK                                0x0000ff00
+#define MDP5_PIPE_DECIMATION_HORZ__SHIFT                       8
+static inline uint32_t MDP5_PIPE_DECIMATION_HORZ(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00001404 + 0x400*i0; }
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN                       0x00000001
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN                       0x00000002
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK         0x00000300
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__SHIFT                8
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__MASK         0x00000c00
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__SHIFT                10
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__MASK          0x00003000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__SHIFT         12
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__MASK          0x0000c000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__SHIFT         14
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__MASK         0x00030000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__SHIFT                16
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK         0x000c0000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT                18
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00001410 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00001414 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00001420 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00001424 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA                        0x00000002
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA                        0x00000004
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA                        0x00000008
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA                        0x00000010
+
+static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00003204 + 0x400*i0; }
+#define MDP5_LM_OUT_SIZE_HEIGHT__MASK                          0xffff0000
+#define MDP5_LM_OUT_SIZE_HEIGHT__SHIFT                         16
+static inline uint32_t MDP5_LM_OUT_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_LM_OUT_SIZE_HEIGHT__SHIFT) & MDP5_LM_OUT_SIZE_HEIGHT__MASK;
+}
+#define MDP5_LM_OUT_SIZE_WIDTH__MASK                           0x0000ffff
+#define MDP5_LM_OUT_SIZE_WIDTH__SHIFT                          0
+static inline uint32_t MDP5_LM_OUT_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_LM_OUT_SIZE_WIDTH__SHIFT) & MDP5_LM_OUT_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00003208 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00003210 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK                   0x00000003
+#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT                  0
+static inline uint32_t MDP5_LM_BLEND_OP_MODE_FG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT) & MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK;
+}
+#define MDP5_LM_BLEND_OP_MODE_FG_INV_ALPHA                     0x00000004
+#define MDP5_LM_BLEND_OP_MODE_FG_MOD_ALPHA                     0x00000008
+#define MDP5_LM_BLEND_OP_MODE_FG_INV_MOD_ALPHA                 0x00000010
+#define MDP5_LM_BLEND_OP_MODE_FG_TRANSP_EN                     0x00000020
+#define MDP5_LM_BLEND_OP_MODE_BG_ALPHA__MASK                   0x00000300
+#define MDP5_LM_BLEND_OP_MODE_BG_ALPHA__SHIFT                  8
+static inline uint32_t MDP5_LM_BLEND_OP_MODE_BG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP5_LM_BLEND_OP_MODE_BG_ALPHA__SHIFT) & MDP5_LM_BLEND_OP_MODE_BG_ALPHA__MASK;
+}
+#define MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA                     0x00000400
+#define MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA                     0x00000800
+#define MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA                 0x00001000
+#define MDP5_LM_BLEND_OP_MODE_BG_TRANSP_EN                     0x00002000
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003224 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003228 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000322c + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003230 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003234 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003238 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000323c + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003240 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003244 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003248 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000032e0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000032e4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000032e8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000032dc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000032ec + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000032f0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000032f4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000032f8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000032fc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00003300 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00003304 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00003308 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000330c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00003310 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+#define MDP5_DSPP_OP_MODE_IGC_LUT_EN                           0x00000001
+#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK                    0x0000000e
+#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT                   1
+static inline uint32_t MDP5_DSPP_OP_MODE_IGC_TBL_IDX(uint32_t val)
+{
+       return ((val) << MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT) & MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK;
+}
+#define MDP5_DSPP_OP_MODE_PCC_EN                               0x00000010
+#define MDP5_DSPP_OP_MODE_DITHER_EN                            0x00000100
+#define MDP5_DSPP_OP_MODE_HIST_EN                              0x00010000
+#define MDP5_DSPP_OP_MODE_AUTO_CLEAR                           0x00020000
+#define MDP5_DSPP_OP_MODE_HIST_LUT_EN                          0x00080000
+#define MDP5_DSPP_OP_MODE_PA_EN                                        0x00100000
+#define MDP5_DSPP_OP_MODE_GAMUT_EN                             0x00800000
+#define MDP5_DSPP_OP_MODE_GAMUT_ORDER                          0x01000000
+
+static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00004630 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00004750 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00004810 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00004830 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00004834 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00004838 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000048dc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000048b0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00012504 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00012508 + 0x200*i0; }
+#define MDP5_INTF_HSYNC_CTL_PULSEW__MASK                       0x0000ffff
+#define MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT                      0
+static inline uint32_t MDP5_INTF_HSYNC_CTL_PULSEW(uint32_t val)
+{
+       return ((val) << MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT) & MDP5_INTF_HSYNC_CTL_PULSEW__MASK;
+}
+#define MDP5_INTF_HSYNC_CTL_PERIOD__MASK                       0xffff0000
+#define MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT                      16
+static inline uint32_t MDP5_INTF_HSYNC_CTL_PERIOD(uint32_t val)
+{
+       return ((val) << MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT) & MDP5_INTF_HSYNC_CTL_PERIOD__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0001250c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00012510 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00012514 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00012518 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0001251c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00012520 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00012524 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00012528 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0001252c + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK                   0x7fffffff
+#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT                  0
+static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F0_VAL(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK;
+}
+#define MDP5_INTF_ACTIVE_VSTART_F0_ACTIVE_V_ENABLE             0x80000000
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00012530 + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK                   0x7fffffff
+#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT                  0
+static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F1_VAL(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00012534 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00012538 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0001253c + 0x200*i0; }
+#define MDP5_INTF_DISPLAY_HCTL_START__MASK                     0x0000ffff
+#define MDP5_INTF_DISPLAY_HCTL_START__SHIFT                    0
+static inline uint32_t MDP5_INTF_DISPLAY_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP5_INTF_DISPLAY_HCTL_START__SHIFT) & MDP5_INTF_DISPLAY_HCTL_START__MASK;
+}
+#define MDP5_INTF_DISPLAY_HCTL_END__MASK                       0xffff0000
+#define MDP5_INTF_DISPLAY_HCTL_END__SHIFT                      16
+static inline uint32_t MDP5_INTF_DISPLAY_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP5_INTF_DISPLAY_HCTL_END__SHIFT) & MDP5_INTF_DISPLAY_HCTL_END__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00012540 + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_HCTL_START__MASK                      0x00007fff
+#define MDP5_INTF_ACTIVE_HCTL_START__SHIFT                     0
+static inline uint32_t MDP5_INTF_ACTIVE_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_HCTL_START__SHIFT) & MDP5_INTF_ACTIVE_HCTL_START__MASK;
+}
+#define MDP5_INTF_ACTIVE_HCTL_END__MASK                                0x7fff0000
+#define MDP5_INTF_ACTIVE_HCTL_END__SHIFT                       16
+static inline uint32_t MDP5_INTF_ACTIVE_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_HCTL_END__SHIFT) & MDP5_INTF_ACTIVE_HCTL_END__MASK;
+}
+#define MDP5_INTF_ACTIVE_HCTL_ACTIVE_H_ENABLE                  0x80000000
+
+static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00012544 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00012548 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0001254c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00012550 + 0x200*i0; }
+#define MDP5_INTF_POLARITY_CTL_HSYNC_LOW                       0x00000001
+#define MDP5_INTF_POLARITY_CTL_VSYNC_LOW                       0x00000002
+#define MDP5_INTF_POLARITY_CTL_DATA_EN_LOW                     0x00000004
+
+static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00012554 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00012558 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0001255c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00012584 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00012590 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000125a8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000125ac + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000125b0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000125f0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000125f4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000125f8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00012600 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00012604 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00012608 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0001260c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00012610 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00012614 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00012618 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0001261c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00013104 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00013108 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0001310c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00013110 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00013114 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00013118 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0001311c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00013120 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00013124 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00013128 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0001312c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00013130 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00013134 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00013138 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0001317c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000131c8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000131cc + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000131d0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000131d4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000131d8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000131dc + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000131e0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000131e8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000131ec + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000131f0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000131f4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000131f8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00013200 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00013244 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00013248 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0001324c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00013254 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00013258 + 0x200*i0; }
+
+
+#endif /* MDP5_XML */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
new file mode 100644 (file)
index 0000000..71a3b23
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "mdp5_kms.h"
+
+#include <drm/drm_mode.h>
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_flip_work.h"
+
+struct mdp5_crtc {
+       struct drm_crtc base;
+       char name[8];
+       struct drm_plane *plane;
+       struct drm_plane *planes[8];
+       int id;
+       bool enabled;
+
+       /* which mixer/encoder we route output to: */
+       int mixer;
+
+       /* if there is a pending flip, these will be non-null: */
+       struct drm_pending_vblank_event *event;
+       struct msm_fence_cb pageflip_cb;
+
+#define PENDING_CURSOR 0x1
+#define PENDING_FLIP   0x2
+       atomic_t pending;
+
+       /* the fb that we logically (from PoV of KMS API) hold a ref
+        * to.  Which we may not yet be scanning out (we may still
+        * be scanning out previous in case of page_flip while waiting
+        * for gpu rendering to complete:
+        */
+       struct drm_framebuffer *fb;
+
+       /* the fb that we currently hold a scanout ref to: */
+       struct drm_framebuffer *scanout_fb;
+
+       /* for unref'ing framebuffers after scanout completes: */
+       struct drm_flip_work unref_fb_work;
+
+       struct mdp_irq vblank;
+       struct mdp_irq err;
+};
+#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
+
+static struct mdp5_kms *get_kms(struct drm_crtc *crtc)
+{
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+static void request_pending(struct drm_crtc *crtc, uint32_t pending)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       atomic_or(pending, &mdp5_crtc->pending);
+       mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
+}
+
+static void crtc_flush(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int id = mdp5_crtc->id;
+       uint32_t i, flush = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mdp5_crtc->planes); i++) {
+               struct drm_plane *plane = mdp5_crtc->planes[i];
+               if (plane) {
+                       enum mdp5_pipe pipe = mdp5_plane_pipe(plane);
+                       flush |= pipe2flush(pipe);
+               }
+       }
+       flush |= mixer2flush(mdp5_crtc->id);
+       flush |= MDP5_CTL_FLUSH_CTL;
+
+       DBG("%s: flush=%08x", mdp5_crtc->name, flush);
+
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_FLUSH(id), flush);
+}
+
+static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_framebuffer *old_fb = mdp5_crtc->fb;
+
+       /* grab reference to incoming scanout fb: */
+       drm_framebuffer_reference(new_fb);
+       mdp5_crtc->base.fb = new_fb;
+       mdp5_crtc->fb = new_fb;
+
+       if (old_fb)
+               drm_flip_work_queue(&mdp5_crtc->unref_fb_work, old_fb);
+}
+
+/* unlike update_fb(), take a ref to the new scanout fb *before* updating
+ * plane, then call this.  Needed to ensure we don't unref the buffer that
+ * is actually still being scanned out.
+ *
+ * Note that this whole thing goes away with atomic.. since we can defer
+ * calling into driver until rendering is done.
+ */
+static void update_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       /* flush updates, to make sure hw is updated to new scanout fb,
+        * so that we can safely queue unref to current fb (ie. next
+        * vblank we know hw is done w/ previous scanout_fb).
+        */
+       crtc_flush(crtc);
+
+       if (mdp5_crtc->scanout_fb)
+               drm_flip_work_queue(&mdp5_crtc->unref_fb_work,
+                               mdp5_crtc->scanout_fb);
+
+       mdp5_crtc->scanout_fb = fb;
+
+       /* enable vblank to complete flip: */
+       request_pending(crtc, PENDING_FLIP);
+}
+
+/* if file!=NULL, this is preclose potential cancel-flip path */
+static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_pending_vblank_event *event;
+       unsigned long flags, i;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       event = mdp5_crtc->event;
+       if (event) {
+               /* if regular vblank case (!file) or if cancel-flip from
+                * preclose on file that requested flip, then send the
+                * event:
+                */
+               if (!file || (event->base.file_priv == file)) {
+                       mdp5_crtc->event = NULL;
+                       drm_send_vblank_event(dev, mdp5_crtc->id, event);
+               }
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       for (i = 0; i < ARRAY_SIZE(mdp5_crtc->planes); i++) {
+               struct drm_plane *plane = mdp5_crtc->planes[i];
+               if (plane)
+                       mdp5_plane_complete_flip(plane);
+       }
+}
+
+static void pageflip_cb(struct msm_fence_cb *cb)
+{
+       struct mdp5_crtc *mdp5_crtc =
+               container_of(cb, struct mdp5_crtc, pageflip_cb);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       struct drm_framebuffer *fb = mdp5_crtc->fb;
+
+       if (!fb)
+               return;
+
+       drm_framebuffer_reference(fb);
+       mdp5_plane_set_scanout(mdp5_crtc->plane, fb);
+       update_scanout(crtc, fb);
+}
+
+static void unref_fb_worker(struct drm_flip_work *work, void *val)
+{
+       struct mdp5_crtc *mdp5_crtc =
+               container_of(work, struct mdp5_crtc, unref_fb_work);
+       struct drm_device *dev = mdp5_crtc->base.dev;
+
+       mutex_lock(&dev->mode_config.mutex);
+       drm_framebuffer_unreference(val);
+       mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void mdp5_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       mdp5_crtc->plane->funcs->destroy(mdp5_crtc->plane);
+
+       drm_crtc_cleanup(crtc);
+       drm_flip_work_cleanup(&mdp5_crtc->unref_fb_work);
+
+       kfree(mdp5_crtc);
+}
+
+static void mdp5_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("%s: mode=%d", mdp5_crtc->name, mode);
+
+       if (enabled != mdp5_crtc->enabled) {
+               if (enabled) {
+                       mdp5_enable(mdp5_kms);
+                       mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
+               } else {
+                       mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
+                       mdp5_disable(mdp5_kms);
+               }
+               mdp5_crtc->enabled = enabled;
+       }
+}
+
+static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void blend_setup(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int id = mdp5_crtc->id;
+
+       /*
+        * Hard-coded setup for now until I figure out how the
+        * layer-mixer works
+        */
+
+       /* LM[id]: */
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(id),
+                       MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(id, 0),
+                       MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
+                       MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL) |
+                       MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(id, 0), 0xff);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(id, 0), 0x00);
+
+       /* NOTE: seems that LM[n] and CTL[m], we do not need n==m.. but
+        * we want to be setting CTL[m].LAYER[n].  Not sure what the
+        * point of having CTL[m].LAYER[o] (for o!=n).. maybe that is
+        * used when chaining up mixers for high resolution displays?
+        */
+
+       /* CTL[id]: */
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 0),
+                       MDP5_CTL_LAYER_REG_RGB0(STAGE0) |
+                       MDP5_CTL_LAYER_REG_BORDER_COLOR);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 3), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 4), 0);
+}
+
+static int mdp5_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 mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int ret;
+
+       mode = adjusted_mode;
+
+       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mdp5_crtc->name, mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
+
+       ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
+                               mdp5_crtc->name, ret);
+               return ret;
+       }
+
+       mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(mdp5_crtc->id),
+                       MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
+                       MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
+
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
+       return 0;
+}
+
+static void mdp5_crtc_prepare(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       DBG("%s", mdp5_crtc->name);
+       /* make sure we hold a ref to mdp clks while setting up mode: */
+       mdp5_enable(get_kms(crtc));
+       mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp5_crtc_commit(struct drm_crtc *crtc)
+{
+       mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+       crtc_flush(crtc);
+       /* drop the ref to mdp clk's that we got in prepare: */
+       mdp5_disable(get_kms(crtc));
+}
+
+static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+               struct drm_framebuffer *old_fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_plane *plane = mdp5_crtc->plane;
+       struct drm_display_mode *mode = &crtc->mode;
+       int ret;
+
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
+
+       ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
+       return ret;
+}
+
+static void mdp5_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static int mdp5_crtc_page_flip(struct drm_crtc *crtc,
+               struct drm_framebuffer *new_fb,
+               struct drm_pending_vblank_event *event,
+               uint32_t page_flip_flags)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_gem_object *obj;
+       unsigned long flags;
+
+       if (mdp5_crtc->event) {
+               dev_err(dev->dev, "already pending flip!\n");
+               return -EBUSY;
+       }
+
+       obj = msm_framebuffer_bo(new_fb, 0);
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       mdp5_crtc->event = event;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       update_fb(crtc, new_fb);
+
+       return msm_gem_queue_inactive_cb(obj, &mdp5_crtc->pageflip_cb);
+}
+
+static int mdp5_crtc_set_property(struct drm_crtc *crtc,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+static const struct drm_crtc_funcs mdp5_crtc_funcs = {
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = mdp5_crtc_destroy,
+       .page_flip = mdp5_crtc_page_flip,
+       .set_property = mdp5_crtc_set_property,
+};
+
+static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
+       .dpms = mdp5_crtc_dpms,
+       .mode_fixup = mdp5_crtc_mode_fixup,
+       .mode_set = mdp5_crtc_mode_set,
+       .prepare = mdp5_crtc_prepare,
+       .commit = mdp5_crtc_commit,
+       .mode_set_base = mdp5_crtc_mode_set_base,
+       .load_lut = mdp5_crtc_load_lut,
+};
+
+static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, vblank);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       unsigned pending;
+
+       mdp_irq_unregister(&get_kms(crtc)->base, &mdp5_crtc->vblank);
+
+       pending = atomic_xchg(&mdp5_crtc->pending, 0);
+
+       if (pending & PENDING_FLIP) {
+               complete_flip(crtc, NULL);
+               drm_flip_work_commit(&mdp5_crtc->unref_fb_work, priv->wq);
+       }
+}
+
+static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, err);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
+       crtc_flush(crtc);
+}
+
+uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       return mdp5_crtc->vblank.irqmask;
+}
+
+void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       DBG("cancel: %p", file);
+       complete_flip(crtc, file);
+}
+
+/* set interface for routing crtc->encoder: */
+void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf,
+               enum mdp5_intf intf_id)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       static const enum mdp5_intfnum intfnum[] = {
+                       INTF0, INTF1, INTF2, INTF3,
+       };
+       uint32_t intf_sel;
+
+       /* now that we know what irq's we want: */
+       mdp5_crtc->err.irqmask = intf2err(intf);
+       mdp5_crtc->vblank.irqmask = intf2vblank(intf);
+
+       /* when called from modeset_init(), skip the rest until later: */
+       if (!mdp5_kms)
+               return;
+
+       intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);
+
+       switch (intf) {
+       case 0:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf_id);
+               break;
+       case 1:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf_id);
+               break;
+       case 2:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf_id);
+               break;
+       case 3:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf_id);
+               break;
+       default:
+               BUG();
+               break;
+       }
+
+       blend_setup(crtc);
+
+       DBG("%s: intf_sel=%08x", mdp5_crtc->name, intf_sel);
+
+       mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(mdp5_crtc->id),
+                       MDP5_CTL_OP_MODE(MODE_NONE) |
+                       MDP5_CTL_OP_INTF_NUM(intfnum[intf]));
+
+       crtc_flush(crtc);
+}
+
+static void set_attach(struct drm_crtc *crtc, enum mdp5_pipe pipe_id,
+               struct drm_plane *plane)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       BUG_ON(pipe_id >= ARRAY_SIZE(mdp5_crtc->planes));
+
+       if (mdp5_crtc->planes[pipe_id] == plane)
+               return;
+
+       mdp5_crtc->planes[pipe_id] = plane;
+       blend_setup(crtc);
+       if (mdp5_crtc->enabled && (plane != mdp5_crtc->plane))
+               crtc_flush(crtc);
+}
+
+void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp5_plane_pipe(plane), plane);
+}
+
+void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp5_plane_pipe(plane), NULL);
+}
+
+/* initialize crtc */
+struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id)
+{
+       struct drm_crtc *crtc = NULL;
+       struct mdp5_crtc *mdp5_crtc;
+       int ret;
+
+       mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
+       if (!mdp5_crtc) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       crtc = &mdp5_crtc->base;
+
+       mdp5_crtc->plane = plane;
+       mdp5_crtc->id = id;
+
+       mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
+       mdp5_crtc->err.irq = mdp5_crtc_err_irq;
+
+       snprintf(mdp5_crtc->name, sizeof(mdp5_crtc->name), "%s:%d",
+                       pipe2name(mdp5_plane_pipe(plane)), id);
+
+       ret = drm_flip_work_init(&mdp5_crtc->unref_fb_work, 16,
+                       "unref fb", unref_fb_worker);
+       if (ret)
+               goto fail;
+
+       INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
+
+       drm_crtc_init(dev, crtc, &mdp5_crtc_funcs);
+       drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
+
+       mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
+
+       return crtc;
+
+fail:
+       if (crtc)
+               mdp5_crtc_destroy(crtc);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
new file mode 100644 (file)
index 0000000..edec7bf
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "mdp5_kms.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+struct mdp5_encoder {
+       struct drm_encoder base;
+       int intf;
+       enum mdp5_intf intf_id;
+       bool enabled;
+       uint32_t bsc;
+};
+#define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
+
+static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
+{
+       struct msm_drm_private *priv = encoder->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/board.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)           \
+       {                                               \
+               .src = MSM_BUS_MASTER_MDP_PORT0,        \
+               .dst = MSM_BUS_SLAVE_EBI_CH0,           \
+               .ab = (ab_val),                         \
+               .ib = (ib_val),                         \
+       }
+
+static struct msm_bus_vectors mdp_bus_vectors[] = {
+       MDP_BUS_VECTOR_ENTRY(0, 0),
+       MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
+};
+static struct msm_bus_paths mdp_bus_usecases[] = { {
+               .num_paths = 1,
+               .vectors = &mdp_bus_vectors[0],
+}, {
+               .num_paths = 1,
+               .vectors = &mdp_bus_vectors[1],
+} };
+static struct msm_bus_scale_pdata mdp_bus_scale_table = {
+       .usecase = mdp_bus_usecases,
+       .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+       .name = "mdss_mdp",
+};
+
+static void bs_init(struct mdp5_encoder *mdp5_encoder)
+{
+       mdp5_encoder->bsc = msm_bus_scale_register_client(
+                       &mdp_bus_scale_table);
+       DBG("bus scale client: %08x", mdp5_encoder->bsc);
+}
+
+static void bs_fini(struct mdp5_encoder *mdp5_encoder)
+{
+       if (mdp5_encoder->bsc) {
+               msm_bus_scale_unregister_client(mdp5_encoder->bsc);
+               mdp5_encoder->bsc = 0;
+       }
+}
+
+static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx)
+{
+       if (mdp5_encoder->bsc) {
+               DBG("set bus scaling: %d", idx);
+               /* HACK: scaling down, and then immediately back up
+                * seems to leave things broken (underflow).. so
+                * never disable:
+                */
+               idx = 1;
+               msm_bus_scale_client_update_request(mdp5_encoder->bsc, idx);
+       }
+}
+#else
+static void bs_init(struct mdp5_encoder *mdp5_encoder) {}
+static void bs_fini(struct mdp5_encoder *mdp5_encoder) {}
+static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {}
+#endif
+
+static void mdp5_encoder_destroy(struct drm_encoder *encoder)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       bs_fini(mdp5_encoder);
+       drm_encoder_cleanup(encoder);
+       kfree(mdp5_encoder);
+}
+
+static const struct drm_encoder_funcs mdp5_encoder_funcs = {
+       .destroy = mdp5_encoder_destroy,
+};
+
+static void mdp5_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       struct mdp5_kms *mdp5_kms = get_kms(encoder);
+       int intf = mdp5_encoder->intf;
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("mode=%d", mode);
+
+       if (enabled == mdp5_encoder->enabled)
+               return;
+
+       if (enabled) {
+               bs_set(mdp5_encoder, 1);
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
+       } else {
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0);
+               bs_set(mdp5_encoder, 0);
+       }
+
+       mdp5_encoder->enabled = enabled;
+}
+
+static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
+               struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       struct mdp5_kms *mdp5_kms = get_kms(encoder);
+       int intf = mdp5_encoder->intf;
+       uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
+       uint32_t display_v_start, display_v_end;
+       uint32_t hsync_start_x, hsync_end_x;
+       uint32_t format;
+
+       mode = adjusted_mode;
+
+       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       ctrl_pol = 0;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+       /* probably need to get DATA_EN polarity from panel.. */
+
+       dtv_hsync_skew = 0;  /* get this from panel? */
+       format = 0x213f;     /* get this from panel? */
+
+       hsync_start_x = (mode->htotal - mode->hsync_start);
+       hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
+
+       vsync_period = mode->vtotal * mode->htotal;
+       vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
+       display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
+       display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
+
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
+                       MDP5_INTF_HSYNC_CTL_PULSEW(mode->hsync_end - mode->hsync_start) |
+                       MDP5_INTF_HSYNC_CTL_PERIOD(mode->htotal));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_PERIOD_F0(intf), vsync_period);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_LEN_F0(intf), vsync_len);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_HCTL(intf),
+                       MDP5_INTF_DISPLAY_HCTL_START(hsync_start_x) |
+                       MDP5_INTF_DISPLAY_HCTL_END(hsync_end_x));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VSTART_F0(intf), display_v_start);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VEND_F0(intf), display_v_end);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_BORDER_COLOR(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_UNDERFLOW_COLOR(intf), 0xff);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_SKEW(intf), dtv_hsync_skew);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_POLARITY_CTL(intf), ctrl_pol);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_HCTL(intf),
+                       MDP5_INTF_ACTIVE_HCTL_START(0) |
+                       MDP5_INTF_ACTIVE_HCTL_END(0));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VSTART_F0(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VEND_F0(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_PANEL_FORMAT(intf), format);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3);  /* frame+line? */
+}
+
+static void mdp5_encoder_prepare(struct drm_encoder *encoder)
+{
+       mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp5_encoder_commit(struct drm_encoder *encoder)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf,
+                       mdp5_encoder->intf_id);
+       mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
+       .dpms = mdp5_encoder_dpms,
+       .mode_fixup = mdp5_encoder_mode_fixup,
+       .mode_set = mdp5_encoder_mode_set,
+       .prepare = mdp5_encoder_prepare,
+       .commit = mdp5_encoder_commit,
+};
+
+/* initialize encoder */
+struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
+               enum mdp5_intf intf_id)
+{
+       struct drm_encoder *encoder = NULL;
+       struct mdp5_encoder *mdp5_encoder;
+       int ret;
+
+       mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL);
+       if (!mdp5_encoder) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       mdp5_encoder->intf = intf;
+       mdp5_encoder->intf_id = intf_id;
+       encoder = &mdp5_encoder->base;
+
+       drm_encoder_init(dev, encoder, &mdp5_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs);
+
+       bs_init(mdp5_encoder);
+
+       return encoder;
+
+fail:
+       if (encoder)
+               mdp5_encoder_destroy(encoder);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
new file mode 100644 (file)
index 0000000..353d494
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
+#include "mdp5_kms.h"
+
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_INTR_EN, irqmask);
+}
+
+static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+void mdp5_irq_preinstall(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
+}
+
+int mdp5_irq_postinstall(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       struct mdp_irq *error_handler = &mdp5_kms->error_handler;
+
+       error_handler->irq = mdp5_irq_error_handler;
+       error_handler->irqmask = MDP5_IRQ_INTF0_UNDER_RUN |
+                       MDP5_IRQ_INTF1_UNDER_RUN |
+                       MDP5_IRQ_INTF2_UNDER_RUN |
+                       MDP5_IRQ_INTF3_UNDER_RUN;
+
+       mdp_irq_register(mdp_kms, error_handler);
+
+       return 0;
+}
+
+void mdp5_irq_uninstall(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
+}
+
+static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       struct drm_device *dev = mdp5_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       unsigned int id;
+       uint32_t status;
+
+       status = mdp5_read(mdp5_kms, REG_MDP5_INTR_STATUS);
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, status);
+
+       VERB("status=%08x", status);
+
+       for (id = 0; id < priv->num_crtcs; id++)
+               if (status & mdp5_crtc_vblank(priv->crtcs[id]))
+                       drm_handle_vblank(dev, id);
+
+       mdp_dispatch_irqs(mdp_kms, status);
+}
+
+irqreturn_t mdp5_irq(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       uint32_t intr;
+
+       intr = mdp5_read(mdp5_kms, REG_MDP5_HW_INTR_STATUS);
+
+       VERB("intr=%08x", intr);
+
+       if (intr & MDP5_HW_INTR_STATUS_INTR_MDP)
+               mdp5_irq_mdp(mdp_kms);
+
+       if (intr & MDP5_HW_INTR_STATUS_INTR_HDMI)
+               hdmi_irq(0, mdp5_kms->hdmi);
+
+       return IRQ_HANDLED;
+}
+
+int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp5_crtc_vblank(crtc), true);
+       return 0;
+}
+
+void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp5_crtc_vblank(crtc), false);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
new file mode 100644 (file)
index 0000000..ee8446c
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
+#include "msm_mmu.h"
+#include "mdp5_kms.h"
+
+static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev);
+
+static int mdp5_hw_init(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       struct drm_device *dev = mdp5_kms->dev;
+       uint32_t version, major, minor;
+       int ret = 0;
+
+       pm_runtime_get_sync(dev->dev);
+
+       mdp5_enable(mdp5_kms);
+       version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION);
+       mdp5_disable(mdp5_kms);
+
+       major = FIELD(version, MDP5_MDP_VERSION_MAJOR);
+       minor = FIELD(version, MDP5_MDP_VERSION_MINOR);
+
+       DBG("found MDP5 version v%d.%d", major, minor);
+
+       if ((major != 1) || ((minor != 0) && (minor != 2))) {
+               dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
+                               major, minor);
+               ret = -ENXIO;
+               goto out;
+       }
+
+       mdp5_kms->rev = minor;
+
+       /* Magic unknown register writes:
+        *
+        *    W VBIF:0x004 00000001      (mdss_mdp.c:839)
+        *    W MDP5:0x2e0 0xe9          (mdss_mdp.c:839)
+        *    W MDP5:0x2e4 0x55          (mdss_mdp.c:839)
+        *    W MDP5:0x3ac 0xc0000ccc    (mdss_mdp.c:839)
+        *    W MDP5:0x3b4 0xc0000ccc    (mdss_mdp.c:839)
+        *    W MDP5:0x3bc 0xcccccc      (mdss_mdp.c:839)
+        *    W MDP5:0x4a8 0xcccc0c0     (mdss_mdp.c:839)
+        *    W MDP5:0x4b0 0xccccc0c0    (mdss_mdp.c:839)
+        *    W MDP5:0x4b8 0xccccc000    (mdss_mdp.c:839)
+        *
+        * Downstream fbdev driver gets these register offsets/values
+        * from DT.. not really sure what these registers are or if
+        * different values for different boards/SoC's, etc.  I guess
+        * they are the golden registers.
+        *
+        * Not setting these does not seem to cause any problem.  But
+        * we may be getting lucky with the bootloader initializing
+        * them for us.  OTOH, if we can always count on the bootloader
+        * setting the golden registers, then perhaps we don't need to
+        * care.
+        */
+
+       mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(0), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(3), 0);
+
+out:
+       pm_runtime_put_sync(dev->dev);
+
+       return ret;
+}
+
+static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
+               struct drm_encoder *encoder)
+{
+       return rate;
+}
+
+static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       struct msm_drm_private *priv = mdp5_kms->dev->dev_private;
+       unsigned i;
+
+       for (i = 0; i < priv->num_crtcs; i++)
+               mdp5_crtc_cancel_pending_flip(priv->crtcs[i], file);
+}
+
+static void mdp5_destroy(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       kfree(mdp5_kms);
+}
+
+static const struct mdp_kms_funcs kms_funcs = {
+       .base = {
+               .hw_init         = mdp5_hw_init,
+               .irq_preinstall  = mdp5_irq_preinstall,
+               .irq_postinstall = mdp5_irq_postinstall,
+               .irq_uninstall   = mdp5_irq_uninstall,
+               .irq             = mdp5_irq,
+               .enable_vblank   = mdp5_enable_vblank,
+               .disable_vblank  = mdp5_disable_vblank,
+               .get_format      = mdp_get_format,
+               .round_pixclk    = mdp5_round_pixclk,
+               .preclose        = mdp5_preclose,
+               .destroy         = mdp5_destroy,
+       },
+       .set_irqmask         = mdp5_set_irqmask,
+};
+
+int mdp5_disable(struct mdp5_kms *mdp5_kms)
+{
+       DBG("");
+
+       clk_disable_unprepare(mdp5_kms->ahb_clk);
+       clk_disable_unprepare(mdp5_kms->axi_clk);
+       clk_disable_unprepare(mdp5_kms->core_clk);
+       clk_disable_unprepare(mdp5_kms->lut_clk);
+
+       return 0;
+}
+
+int mdp5_enable(struct mdp5_kms *mdp5_kms)
+{
+       DBG("");
+
+       clk_prepare_enable(mdp5_kms->ahb_clk);
+       clk_prepare_enable(mdp5_kms->axi_clk);
+       clk_prepare_enable(mdp5_kms->core_clk);
+       clk_prepare_enable(mdp5_kms->lut_clk);
+
+       return 0;
+}
+
+static int modeset_init(struct mdp5_kms *mdp5_kms)
+{
+       static const enum mdp5_pipe crtcs[] = {
+                       SSPP_RGB0, SSPP_RGB1, SSPP_RGB2,
+       };
+       struct drm_device *dev = mdp5_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       struct drm_encoder *encoder;
+       int i, ret;
+
+       /* construct CRTCs: */
+       for (i = 0; i < ARRAY_SIZE(crtcs); i++) {
+               struct drm_plane *plane;
+               struct drm_crtc *crtc;
+
+               plane = mdp5_plane_init(dev, crtcs[i], true);
+               if (IS_ERR(plane)) {
+                       ret = PTR_ERR(plane);
+                       dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
+                                       pipe2name(crtcs[i]), ret);
+                       goto fail;
+               }
+
+               crtc  = mdp5_crtc_init(dev, plane, i);
+               if (IS_ERR(crtc)) {
+                       ret = PTR_ERR(crtc);
+                       dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
+                                       pipe2name(crtcs[i]), ret);
+                       goto fail;
+               }
+               priv->crtcs[priv->num_crtcs++] = crtc;
+       }
+
+       /* Construct encoder for HDMI: */
+       encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
+       if (IS_ERR(encoder)) {
+               dev_err(dev->dev, "failed to construct encoder\n");
+               ret = PTR_ERR(encoder);
+               goto fail;
+       }
+
+       /* NOTE: the vsync and error irq's are actually associated with
+        * the INTF/encoder.. the easiest way to deal with this (ie. what
+        * we do now) is assume a fixed relationship between crtc's and
+        * encoders.  I'm not sure if there is ever a need to more freely
+        * assign crtcs to encoders, but if there is then we need to take
+        * care of error and vblank irq's that the crtc has registered,
+        * and also update user-requested vblank_mask.
+        */
+       encoder->possible_crtcs = BIT(0);
+       mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI);
+
+       priv->encoders[priv->num_encoders++] = encoder;
+
+       /* Construct bridge/connector for HDMI: */
+       mdp5_kms->hdmi = hdmi_init(dev, encoder);
+       if (IS_ERR(mdp5_kms->hdmi)) {
+               ret = PTR_ERR(mdp5_kms->hdmi);
+               dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       return ret;
+}
+
+static const char *iommu_ports[] = {
+               "mdp_0",
+};
+
+static int get_clk(struct platform_device *pdev, struct clk **clkp,
+               const char *name)
+{
+       struct device *dev = &pdev->dev;
+       struct clk *clk = devm_clk_get(dev, name);
+       if (IS_ERR(clk)) {
+               dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk));
+               return PTR_ERR(clk);
+       }
+       *clkp = clk;
+       return 0;
+}
+
+struct msm_kms *mdp5_kms_init(struct drm_device *dev)
+{
+       struct platform_device *pdev = dev->platformdev;
+       struct mdp5_platform_config *config = mdp5_get_config(pdev);
+       struct mdp5_kms *mdp5_kms;
+       struct msm_kms *kms = NULL;
+       struct msm_mmu *mmu;
+       int ret;
+
+       mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL);
+       if (!mdp5_kms) {
+               dev_err(dev->dev, "failed to allocate kms\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       mdp_kms_init(&mdp5_kms->base, &kms_funcs);
+
+       kms = &mdp5_kms->base.base;
+
+       mdp5_kms->dev = dev;
+       mdp5_kms->smp_blk_cnt = config->smp_blk_cnt;
+
+       mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
+       if (IS_ERR(mdp5_kms->mmio)) {
+               ret = PTR_ERR(mdp5_kms->mmio);
+               goto fail;
+       }
+
+       mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
+       if (IS_ERR(mdp5_kms->vbif)) {
+               ret = PTR_ERR(mdp5_kms->vbif);
+               goto fail;
+       }
+
+       mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
+       if (IS_ERR(mdp5_kms->vdd)) {
+               ret = PTR_ERR(mdp5_kms->vdd);
+               goto fail;
+       }
+
+       ret = regulator_enable(mdp5_kms->vdd);
+       if (ret) {
+               dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret);
+               goto fail;
+       }
+
+       ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk") ||
+                       get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk") ||
+                       get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src") ||
+                       get_clk(pdev, &mdp5_kms->core_clk, "core_clk") ||
+                       get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk") ||
+                       get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk");
+       if (ret)
+               goto fail;
+
+       ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk);
+
+       /* make sure things are off before attaching iommu (bootloader could
+        * have left things on, in which case we'll start getting faults if
+        * we don't disable):
+        */
+       mdp5_enable(mdp5_kms);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(0), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(3), 0);
+       mdp5_disable(mdp5_kms);
+       mdelay(16);
+
+       if (config->iommu) {
+               mmu = msm_iommu_new(dev, config->iommu);
+               if (IS_ERR(mmu)) {
+                       ret = PTR_ERR(mmu);
+                       goto fail;
+               }
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       goto fail;
+       } else {
+               dev_info(dev->dev, "no iommu, fallback to phys "
+                               "contig buffers for scanout\n");
+               mmu = NULL;
+       }
+
+       mdp5_kms->id = msm_register_mmu(dev, mmu);
+       if (mdp5_kms->id < 0) {
+               ret = mdp5_kms->id;
+               dev_err(dev->dev, "failed to register mdp5 iommu: %d\n", ret);
+               goto fail;
+       }
+
+       ret = modeset_init(mdp5_kms);
+       if (ret) {
+               dev_err(dev->dev, "modeset_init failed: %d\n", ret);
+               goto fail;
+       }
+
+       return kms;
+
+fail:
+       if (kms)
+               mdp5_destroy(kms);
+       return ERR_PTR(ret);
+}
+
+static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev)
+{
+       static struct mdp5_platform_config config = {};
+#ifdef CONFIG_OF
+       /* TODO */
+#endif
+       return &config;
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
new file mode 100644 (file)
index 0000000..c8b1a25
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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/>.
+ */
+
+#ifndef __MDP5_KMS_H__
+#define __MDP5_KMS_H__
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp/mdp_kms.h"
+#include "mdp5.xml.h"
+#include "mdp5_smp.h"
+
+struct mdp5_kms {
+       struct mdp_kms base;
+
+       struct drm_device *dev;
+
+       int rev;
+
+       /* mapper-id used to request GEM buffer mapped for scanout: */
+       int id;
+
+       /* for tracking smp allocation amongst pipes: */
+       mdp5_smp_state_t smp_state;
+       struct mdp5_client_smp_state smp_client_state[CID_MAX];
+       int smp_blk_cnt;
+
+       /* io/register spaces: */
+       void __iomem *mmio, *vbif;
+
+       struct regulator *vdd;
+
+       struct clk *axi_clk;
+       struct clk *ahb_clk;
+       struct clk *src_clk;
+       struct clk *core_clk;
+       struct clk *lut_clk;
+       struct clk *vsync_clk;
+
+       struct hdmi *hdmi;
+
+       struct mdp_irq error_handler;
+};
+#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
+
+/* platform config data (ie. from DT, or pdata) */
+struct mdp5_platform_config {
+       struct iommu_domain *iommu;
+       uint32_t max_clk;
+       int smp_blk_cnt;
+};
+
+static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data)
+{
+       msm_writel(data, mdp5_kms->mmio + reg);
+}
+
+static inline u32 mdp5_read(struct mdp5_kms *mdp5_kms, u32 reg)
+{
+       return msm_readl(mdp5_kms->mmio + reg);
+}
+
+static inline const char *pipe2name(enum mdp5_pipe pipe)
+{
+       static const char *names[] = {
+#define NAME(n) [SSPP_ ## n] = #n
+               NAME(VIG0), NAME(VIG1), NAME(VIG2),
+               NAME(RGB0), NAME(RGB1), NAME(RGB2),
+               NAME(DMA0), NAME(DMA1),
+#undef NAME
+       };
+       return names[pipe];
+}
+
+static inline uint32_t pipe2flush(enum mdp5_pipe pipe)
+{
+       switch (pipe) {
+       case SSPP_VIG0: return MDP5_CTL_FLUSH_VIG0;
+       case SSPP_VIG1: return MDP5_CTL_FLUSH_VIG1;
+       case SSPP_VIG2: return MDP5_CTL_FLUSH_VIG2;
+       case SSPP_RGB0: return MDP5_CTL_FLUSH_RGB0;
+       case SSPP_RGB1: return MDP5_CTL_FLUSH_RGB1;
+       case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2;
+       case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0;
+       case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
+       default:        return 0;
+       }
+}
+
+static inline int pipe2nclients(enum mdp5_pipe pipe)
+{
+       switch (pipe) {
+       case SSPP_RGB0:
+       case SSPP_RGB1:
+       case SSPP_RGB2:
+               return 1;
+       default:
+               return 3;
+       }
+}
+
+static inline enum mdp5_client_id pipe2client(enum mdp5_pipe pipe, int plane)
+{
+       WARN_ON(plane >= pipe2nclients(pipe));
+       switch (pipe) {
+       case SSPP_VIG0: return CID_VIG0_Y + plane;
+       case SSPP_VIG1: return CID_VIG1_Y + plane;
+       case SSPP_VIG2: return CID_VIG2_Y + plane;
+       case SSPP_RGB0: return CID_RGB0;
+       case SSPP_RGB1: return CID_RGB1;
+       case SSPP_RGB2: return CID_RGB2;
+       case SSPP_DMA0: return CID_DMA0_Y + plane;
+       case SSPP_DMA1: return CID_DMA1_Y + plane;
+       default:        return CID_UNUSED;
+       }
+}
+
+static inline uint32_t mixer2flush(int lm)
+{
+       switch (lm) {
+       case 0:  return MDP5_CTL_FLUSH_LM0;
+       case 1:  return MDP5_CTL_FLUSH_LM1;
+       case 2:  return MDP5_CTL_FLUSH_LM2;
+       default: return 0;
+       }
+}
+
+static inline uint32_t intf2err(int intf)
+{
+       switch (intf) {
+       case 0:  return MDP5_IRQ_INTF0_UNDER_RUN;
+       case 1:  return MDP5_IRQ_INTF1_UNDER_RUN;
+       case 2:  return MDP5_IRQ_INTF2_UNDER_RUN;
+       case 3:  return MDP5_IRQ_INTF3_UNDER_RUN;
+       default: return 0;
+       }
+}
+
+static inline uint32_t intf2vblank(int intf)
+{
+       switch (intf) {
+       case 0:  return MDP5_IRQ_INTF0_VSYNC;
+       case 1:  return MDP5_IRQ_INTF1_VSYNC;
+       case 2:  return MDP5_IRQ_INTF2_VSYNC;
+       case 3:  return MDP5_IRQ_INTF3_VSYNC;
+       default: return 0;
+       }
+}
+
+int mdp5_disable(struct mdp5_kms *mdp5_kms);
+int mdp5_enable(struct mdp5_kms *mdp5_kms);
+
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp5_irq_preinstall(struct msm_kms *kms);
+int mdp5_irq_postinstall(struct msm_kms *kms);
+void mdp5_irq_uninstall(struct msm_kms *kms);
+irqreturn_t mdp5_irq(struct msm_kms *kms);
+int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+
+static inline
+uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
+               uint32_t max_formats)
+{
+       /* TODO when we have YUV, we need to filter supported formats
+        * based on pipe id..
+        */
+       return mdp_get_formats(pixel_formats, max_formats);
+}
+
+void mdp5_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj);
+void mdp5_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb);
+int mdp5_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);
+void mdp5_plane_complete_flip(struct drm_plane *plane);
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+               enum mdp5_pipe pipe, bool private_plane);
+
+uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
+
+void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
+void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf,
+               enum mdp5_intf intf_id);
+void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
+void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
+struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id);
+
+struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
+               enum mdp5_intf intf_id);
+
+#endif /* __MDP5_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
new file mode 100644 (file)
index 0000000..0ac8bb5
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "mdp5_kms.h"
+
+
+struct mdp5_plane {
+       struct drm_plane base;
+       const char *name;
+
+       enum mdp5_pipe pipe;
+
+       uint32_t nformats;
+       uint32_t formats[32];
+
+       bool enabled;
+};
+#define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
+
+static struct mdp5_kms *get_kms(struct drm_plane *plane)
+{
+       struct msm_drm_private *priv = plane->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+static int mdp5_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)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+
+       mdp5_plane->enabled = true;
+
+       if (plane->fb)
+               drm_framebuffer_unreference(plane->fb);
+
+       drm_framebuffer_reference(fb);
+
+       return mdp5_plane_mode_set(plane, crtc, fb,
+                       crtc_x, crtc_y, crtc_w, crtc_h,
+                       src_x, src_y, src_w, src_h);
+}
+
+static int mdp5_plane_disable(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       int i;
+
+       DBG("%s: disable", mdp5_plane->name);
+
+       /* update our SMP request to zero (release all our blks): */
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_request(mdp5_kms, pipe2client(pipe, i), 0);
+
+       /* TODO detaching now will cause us not to get the last
+        * vblank and mdp5_smp_commit().. so other planes will
+        * still see smp blocks previously allocated to us as
+        * in-use..
+        */
+       if (plane->crtc)
+               mdp5_crtc_detach(plane->crtc, plane);
+
+       return 0;
+}
+
+static void mdp5_plane_destroy(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+
+       mdp5_plane_disable(plane);
+       drm_plane_cleanup(plane);
+
+       kfree(mdp5_plane);
+}
+
+/* helper to install properties which are common to planes and crtcs */
+void mdp5_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj)
+{
+       // XXX
+}
+
+int mdp5_plane_set_property(struct drm_plane *plane,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+static const struct drm_plane_funcs mdp5_plane_funcs = {
+               .update_plane = mdp5_plane_update,
+               .disable_plane = mdp5_plane_disable,
+               .destroy = mdp5_plane_destroy,
+               .set_property = mdp5_plane_set_property,
+};
+
+void mdp5_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       uint32_t nplanes = drm_format_num_planes(fb->pixel_format);
+       uint32_t iova[4];
+       int i;
+
+       for (i = 0; i < nplanes; i++) {
+               struct drm_gem_object *bo = msm_framebuffer_bo(fb, i);
+               msm_gem_get_iova(bo, mdp5_kms->id, &iova[i]);
+       }
+       for (; i < 4; i++)
+               iova[i] = 0;
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
+                       MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
+                       MDP5_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_B(pipe),
+                       MDP5_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
+                       MDP5_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC0_ADDR(pipe), iova[0]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC1_ADDR(pipe), iova[1]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC2_ADDR(pipe), iova[2]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe), iova[3]);
+
+       plane->fb = fb;
+}
+
+/* NOTE: looks like if horizontal decimation is used (if we supported that)
+ * then the width used to calculate SMP block requirements is the post-
+ * decimated width.  Ie. SMP buffering sits downstream of decimation (which
+ * presumably happens during the dma from scanout buffer).
+ */
+static int request_smp_blocks(struct drm_plane *plane, uint32_t format,
+               uint32_t nplanes, uint32_t width)
+{
+       struct drm_device *dev = plane->dev;
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       int i, hsub, nlines, nblks, ret;
+
+       hsub = drm_format_horz_chroma_subsampling(format);
+
+       /* different if BWC (compressed framebuffer?) enabled: */
+       nlines = 2;
+
+       for (i = 0, nblks = 0; i < nplanes; i++) {
+               int n, fetch_stride, cpp;
+
+               cpp = drm_format_plane_cpp(format, i);
+               fetch_stride = width * cpp / (i ? hsub : 1);
+
+               n = DIV_ROUND_UP(fetch_stride * nlines, SMP_BLK_SIZE);
+
+               /* for hw rev v1.00 */
+               if (mdp5_kms->rev == 0)
+                       n = roundup_pow_of_two(n);
+
+               DBG("%s[%d]: request %d SMP blocks", mdp5_plane->name, i, n);
+               ret = mdp5_smp_request(mdp5_kms, pipe2client(pipe, i), n);
+               if (ret) {
+                       dev_err(dev->dev, "Could not allocate %d SMP blocks: %d\n",
+                                       n, ret);
+                       return ret;
+               }
+
+               nblks += n;
+       }
+
+       /* in success case, return total # of blocks allocated: */
+       return nblks;
+}
+
+static void set_fifo_thresholds(struct drm_plane *plane, int nblks)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       uint32_t val;
+
+       /* 1/4 of SMP pool that is being fetched */
+       val = (nblks * SMP_ENTRIES_PER_BLK) / 4;
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(pipe), val * 1);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(pipe), val * 2);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(pipe), val * 3);
+
+}
+
+int mdp5_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 mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       const struct mdp_format *format;
+       uint32_t nplanes, config = 0;
+       uint32_t phasex_step = 0, phasey_step = 0;
+       uint32_t hdecm = 0, vdecm = 0;
+       int i, nblks;
+
+       nplanes = drm_format_num_planes(fb->pixel_format);
+
+       /* bad formats should already be rejected: */
+       if (WARN_ON(nplanes > pipe2nclients(pipe)))
+               return -EINVAL;
+
+       /* 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;
+
+       DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp5_plane->name,
+                       fb->base.id, src_x, src_y, src_w, src_h,
+                       crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
+
+       /*
+        * Calculate and request required # of smp blocks:
+        */
+       nblks = request_smp_blocks(plane, fb->pixel_format, nplanes, src_w);
+       if (nblks < 0)
+               return nblks;
+
+       /*
+        * Currently we update the hw for allocations/requests immediately,
+        * but once atomic modeset/pageflip is in place, the allocation
+        * would move into atomic->check_plane_state(), while updating the
+        * hw would remain here:
+        */
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_configure(mdp5_kms, pipe2client(pipe, i));
+
+       if (src_w != crtc_w) {
+               config |= MDP5_PIPE_SCALE_CONFIG_SCALEX_EN;
+               /* TODO calc phasex_step, hdecm */
+       }
+
+       if (src_h != crtc_h) {
+               config |= MDP5_PIPE_SCALE_CONFIG_SCALEY_EN;
+               /* TODO calc phasey_step, vdecm */
+       }
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
+                       MDP5_PIPE_SRC_IMG_SIZE_WIDTH(src_w) |
+                       MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(src_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_SIZE(pipe),
+                       MDP5_PIPE_SRC_SIZE_WIDTH(src_w) |
+                       MDP5_PIPE_SRC_SIZE_HEIGHT(src_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_XY(pipe),
+                       MDP5_PIPE_SRC_XY_X(src_x) |
+                       MDP5_PIPE_SRC_XY_Y(src_y));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_OUT_SIZE(pipe),
+                       MDP5_PIPE_OUT_SIZE_WIDTH(crtc_w) |
+                       MDP5_PIPE_OUT_SIZE_HEIGHT(crtc_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_OUT_XY(pipe),
+                       MDP5_PIPE_OUT_XY_X(crtc_x) |
+                       MDP5_PIPE_OUT_XY_Y(crtc_y));
+
+       mdp5_plane_set_scanout(plane, fb);
+
+       format = to_mdp_format(msm_framebuffer_format(fb));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe),
+                       MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
+                       MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
+                       MDP5_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
+                       MDP5_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
+                       COND(format->alpha_enable, MDP5_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
+                       MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
+                       MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
+                       COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) |
+                       MDP5_PIPE_SRC_FORMAT_NUM_PLANES(nplanes - 1) |
+                       MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(CHROMA_RGB));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe),
+                       MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
+                       MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));
+
+       /* not using secure mode: */
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), phasex_step);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasey_step);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
+                       MDP5_PIPE_DECIMATION_VERT(vdecm) |
+                       MDP5_PIPE_DECIMATION_HORZ(hdecm));
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe),
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(SCALE_FILTER_NEAREST));
+
+       set_fifo_thresholds(plane, nblks);
+
+       /* TODO detach from old crtc (if we had more than one) */
+       mdp5_crtc_attach(crtc, plane);
+
+       return 0;
+}
+
+void mdp5_plane_complete_flip(struct drm_plane *plane)
+{
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = to_mdp5_plane(plane)->pipe;
+       int i;
+
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_commit(mdp5_kms, pipe2client(pipe, i));
+}
+
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       return mdp5_plane->pipe;
+}
+
+/* initialize plane */
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+               enum mdp5_pipe pipe, bool private_plane)
+{
+       struct drm_plane *plane = NULL;
+       struct mdp5_plane *mdp5_plane;
+       int ret;
+
+       mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
+       if (!mdp5_plane) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       plane = &mdp5_plane->base;
+
+       mdp5_plane->pipe = pipe;
+       mdp5_plane->name = pipe2name(pipe);
+
+       mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
+                       ARRAY_SIZE(mdp5_plane->formats));
+
+       drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
+                       mdp5_plane->formats, mdp5_plane->nformats,
+                       private_plane);
+
+       mdp5_plane_install_properties(plane, &plane->base);
+
+       return plane;
+
+fail:
+       if (plane)
+               mdp5_plane_destroy(plane);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
new file mode 100644 (file)
index 0000000..2d0236b
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "mdp5_kms.h"
+#include "mdp5_smp.h"
+
+
+/* SMP - Shared Memory Pool
+ *
+ * These are shared between all the clients, where each plane in a
+ * scanout buffer is a SMP client.  Ie. scanout of 3 plane I420 on
+ * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
+ *
+ * Based on the size of the attached scanout buffer, a certain # of
+ * blocks must be allocated to that client out of the shared pool.
+ *
+ * For each block, it can be either free, or pending/in-use by a
+ * client.  The updates happen in three steps:
+ *
+ *  1) mdp5_smp_request():
+ *     When plane scanout is setup, calculate required number of
+ *     blocks needed per client, and request.  Blocks not inuse or
+ *     pending by any other client are added to client's pending
+ *     set.
+ *
+ *  2) mdp5_smp_configure():
+ *     As hw is programmed, before FLUSH, MDP5_SMP_ALLOC registers
+ *     are configured for the union(pending, inuse)
+ *
+ *  3) mdp5_smp_commit():
+ *     After next vblank, copy pending -> inuse.  Optionally update
+ *     MDP5_SMP_ALLOC registers if there are newly unused blocks
+ *
+ * On the next vblank after changes have been committed to hw, the
+ * client's pending blocks become it's in-use blocks (and no-longer
+ * in-use blocks become available to other clients).
+ *
+ * btw, hurray for confusing overloaded acronyms!  :-/
+ *
+ * NOTE: for atomic modeset/pageflip NONBLOCK operations, step #1
+ * should happen at (or before)? atomic->check().  And we'd need
+ * an API to discard previous requests if update is aborted or
+ * (test-only).
+ *
+ * TODO would perhaps be nice to have debugfs to dump out kernel
+ * inuse and pending state of all clients..
+ */
+
+static DEFINE_SPINLOCK(smp_lock);
+
+
+/* step #1: update # of blocks pending for the client: */
+int mdp5_smp_request(struct mdp5_kms *mdp5_kms,
+               enum mdp5_client_id cid, int nblks)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int i, ret, avail, cur_nblks, cnt = mdp5_kms->smp_blk_cnt;
+       unsigned long flags;
+
+       spin_lock_irqsave(&smp_lock, flags);
+
+       avail = cnt - bitmap_weight(mdp5_kms->smp_state, cnt);
+       if (nblks > avail) {
+               ret = -ENOSPC;
+               goto fail;
+       }
+
+       cur_nblks = bitmap_weight(ps->pending, cnt);
+       if (nblks > cur_nblks) {
+               /* grow the existing pending reservation: */
+               for (i = cur_nblks; i < nblks; i++) {
+                       int blk = find_first_zero_bit(mdp5_kms->smp_state, cnt);
+                       set_bit(blk, ps->pending);
+                       set_bit(blk, mdp5_kms->smp_state);
+               }
+       } else {
+               /* shrink the existing pending reservation: */
+               for (i = cur_nblks; i > nblks; i--) {
+                       int blk = find_first_bit(ps->pending, cnt);
+                       clear_bit(blk, ps->pending);
+                       /* don't clear in global smp_state until _commit() */
+               }
+       }
+
+fail:
+       spin_unlock_irqrestore(&smp_lock, flags);
+       return 0;
+}
+
+static void update_smp_state(struct mdp5_kms *mdp5_kms,
+               enum mdp5_client_id cid, mdp5_smp_state_t *assigned)
+{
+       int cnt = mdp5_kms->smp_blk_cnt;
+       uint32_t blk, val;
+
+       for_each_set_bit(blk, *assigned, cnt) {
+               int idx = blk / 3;
+               int fld = blk % 3;
+
+               val = mdp5_read(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx));
+
+               switch (fld) {
+               case 0:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT0(cid);
+                       break;
+               case 1:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT1(cid);
+                       break;
+               case 2:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT2(cid);
+                       break;
+               }
+
+               mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx), val);
+               mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(idx), val);
+       }
+}
+
+/* step #2: configure hw for union(pending, inuse): */
+void mdp5_smp_configure(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int cnt = mdp5_kms->smp_blk_cnt;
+       mdp5_smp_state_t assigned;
+
+       bitmap_or(assigned, ps->inuse, ps->pending, cnt);
+       update_smp_state(mdp5_kms, cid, &assigned);
+}
+
+/* step #3: after vblank, copy pending -> inuse: */
+void mdp5_smp_commit(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int cnt = mdp5_kms->smp_blk_cnt;
+       mdp5_smp_state_t released;
+
+       /*
+        * Figure out if there are any blocks we where previously
+        * using, which can be released and made available to other
+        * clients:
+        */
+       if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&smp_lock, flags);
+               /* clear released blocks: */
+               bitmap_andnot(mdp5_kms->smp_state, mdp5_kms->smp_state,
+                               released, cnt);
+               spin_unlock_irqrestore(&smp_lock, flags);
+
+               update_smp_state(mdp5_kms, CID_UNUSED, &released);
+       }
+
+       bitmap_copy(ps->inuse, ps->pending, cnt);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
new file mode 100644 (file)
index 0000000..0ab739e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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/>.
+ */
+
+#ifndef __MDP5_SMP_H__
+#define __MDP5_SMP_H__
+
+#include "msm_drv.h"
+
+#define MAX_SMP_BLOCKS  22
+#define SMP_BLK_SIZE    4096
+#define SMP_ENTRIES_PER_BLK (SMP_BLK_SIZE / 16)
+
+typedef DECLARE_BITMAP(mdp5_smp_state_t, MAX_SMP_BLOCKS);
+
+struct mdp5_client_smp_state {
+       mdp5_smp_state_t inuse;
+       mdp5_smp_state_t pending;
+};
+
+struct mdp5_kms;
+
+int mdp5_smp_request(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid, int nblks);
+void mdp5_smp_configure(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid);
+void mdp5_smp_commit(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid);
+
+
+#endif /* __MDP5_SMP_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
new file mode 100644 (file)
index 0000000..a9629b8
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef MDP_COMMON_XML
+#define MDP_COMMON_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+
+Copyright (C) 2013 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum mdp_mixer_stage_id {
+       STAGE_UNUSED = 0,
+       STAGE_BASE = 1,
+       STAGE0 = 2,
+       STAGE1 = 3,
+       STAGE2 = 4,
+       STAGE3 = 5,
+};
+
+enum mdp_alpha_type {
+       FG_CONST = 0,
+       BG_CONST = 1,
+       FG_PIXEL = 2,
+       BG_PIXEL = 3,
+};
+
+enum mdp_bpc {
+       BPC1 = 0,
+       BPC5 = 1,
+       BPC6 = 2,
+       BPC8 = 3,
+};
+
+enum mdp_bpc_alpha {
+       BPC1A = 0,
+       BPC4A = 1,
+       BPC6A = 2,
+       BPC8A = 3,
+};
+
+
+#endif /* MDP_COMMON_XML */
similarity index 85%
rename from drivers/gpu/drm/msm/mdp4/mdp4_format.c
rename to drivers/gpu/drm/msm/mdp/mdp_format.c
index 17330b0927b2a0ac0f608b2e9a98777cb96016ec..e0a6ffbe6ab42e00c9f829b20499367cb28d99d6 100644 (file)
@@ -17,7 +17,7 @@
 
 
 #include "msm_drv.h"
-#include "mdp4_kms.h"
+#include "mdp_kms.h"
 
 #define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt) { \
                .base = { .pixel_format = DRM_FORMAT_ ## name }, \
@@ -34,7 +34,7 @@
 
 #define BPC0A 0
 
-static const struct mdp4_format formats[] = {
+static const struct mdp_format formats[] = {
        /*  name      a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt */
        FMT(ARGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  true,   true,  4,  4),
        FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4),
@@ -44,12 +44,11 @@ static const struct mdp4_format formats[] = {
        FMT(BGR565,   0, 5, 6, 5,  2, 0, 1, 0,  false,  true,  2,  3),
 };
 
-uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
-               uint32_t max_formats)
+uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats)
 {
        uint32_t i;
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               const struct mdp4_format *f = &formats[i];
+               const struct mdp_format *f = &formats[i];
 
                if (i == max_formats)
                        break;
@@ -60,11 +59,11 @@ uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
        return i;
 }
 
-const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format)
+const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format)
 {
        int i;
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               const struct mdp4_format *f = &formats[i];
+               const struct mdp_format *f = &formats[i];
                if (f->base.pixel_format == format)
                        return &f->base;
        }
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c
new file mode 100644 (file)
index 0000000..3be48f7
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
+#include "mdp_kms.h"
+
+
+struct mdp_irq_wait {
+       struct mdp_irq irq;
+       int count;
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_event);
+
+static DEFINE_SPINLOCK(list_lock);
+
+static void update_irq(struct mdp_kms *mdp_kms)
+{
+       struct mdp_irq *irq;
+       uint32_t irqmask = mdp_kms->vblank_mask;
+
+       BUG_ON(!spin_is_locked(&list_lock));
+
+       list_for_each_entry(irq, &mdp_kms->irq_list, node)
+               irqmask |= irq->irqmask;
+
+       mdp_kms->funcs->set_irqmask(mdp_kms, irqmask);
+}
+
+static void update_irq_unlocked(struct mdp_kms *mdp_kms)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&list_lock, flags);
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status)
+{
+       struct mdp_irq *handler, *n;
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       mdp_kms->in_irq = true;
+       list_for_each_entry_safe(handler, n, &mdp_kms->irq_list, node) {
+               if (handler->irqmask & status) {
+                       spin_unlock_irqrestore(&list_lock, flags);
+                       handler->irq(handler, handler->irqmask & status);
+                       spin_lock_irqsave(&list_lock, flags);
+               }
+       }
+       mdp_kms->in_irq = false;
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+
+}
+
+void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       if (enable)
+               mdp_kms->vblank_mask |= mask;
+       else
+               mdp_kms->vblank_mask &= ~mask;
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+}
+
+static void wait_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp_irq_wait *wait =
+                       container_of(irq, struct mdp_irq_wait, irq);
+       wait->count--;
+       wake_up_all(&wait_event);
+}
+
+void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       struct mdp_irq_wait wait = {
+               .irq = {
+                       .irq = wait_irq,
+                       .irqmask = irqmask,
+               },
+               .count = 1,
+       };
+       mdp_irq_register(mdp_kms, &wait.irq);
+       wait_event(wait_event, (wait.count <= 0));
+       mdp_irq_unregister(mdp_kms, &wait.irq);
+}
+
+void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq)
+{
+       unsigned long flags;
+       bool needs_update = false;
+
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (!irq->registered) {
+               irq->registered = true;
+               list_add(&irq->node, &mdp_kms->irq_list);
+               needs_update = !mdp_kms->in_irq;
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       if (needs_update)
+               update_irq_unlocked(mdp_kms);
+}
+
+void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq)
+{
+       unsigned long flags;
+       bool needs_update = false;
+
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (irq->registered) {
+               irq->registered = false;
+               list_del(&irq->node);
+               needs_update = !mdp_kms->in_irq;
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       if (needs_update)
+               update_irq_unlocked(mdp_kms);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
new file mode 100644 (file)
index 0000000..99557b5
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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/>.
+ */
+
+#ifndef __MDP_KMS_H__
+#define __MDP_KMS_H__
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp_common.xml.h"
+
+struct mdp_kms;
+
+struct mdp_kms_funcs {
+       struct msm_kms_funcs base;
+       void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask);
+};
+
+struct mdp_kms {
+       struct msm_kms base;
+
+       const struct mdp_kms_funcs *funcs;
+
+       /* irq handling: */
+       bool in_irq;
+       struct list_head irq_list;    /* list of mdp4_irq */
+       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+};
+#define to_mdp_kms(x) container_of(x, struct mdp_kms, base)
+
+static inline void mdp_kms_init(struct mdp_kms *mdp_kms,
+               const struct mdp_kms_funcs *funcs)
+{
+       mdp_kms->funcs = funcs;
+       INIT_LIST_HEAD(&mdp_kms->irq_list);
+       msm_kms_init(&mdp_kms->base, &funcs->base);
+}
+
+/*
+ * irq helpers:
+ */
+
+/* For transiently registering for different MDP irqs that various parts
+ * of the KMS code need during setup/configuration.  These are not
+ * necessarily the same as what drm_vblank_get/put() are requesting, and
+ * the hysteresis in drm_vblank_put() is not necessarily desirable for
+ * internal housekeeping related irq usage.
+ */
+struct mdp_irq {
+       struct list_head node;
+       uint32_t irqmask;
+       bool registered;
+       void (*irq)(struct mdp_irq *irq, uint32_t irqstatus);
+};
+
+void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status);
+void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable);
+void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
+void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
+
+
+/*
+ * pixel format helpers:
+ */
+
+struct mdp_format {
+       struct msm_format base;
+       enum mdp_bpc bpc_r, bpc_g, bpc_b;
+       enum mdp_bpc_alpha bpc_a;
+       uint8_t unpack[4];
+       bool alpha_enable, unpack_tight;
+       uint8_t cpp, unpack_count;
+};
+#define to_mdp_format(x) container_of(x, struct mdp_format, base)
+
+uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats);
+const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
+
+#endif /* __MDP_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp4/mdp4_irq.c
deleted file mode 100644 (file)
index 5c6b7fc..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
-#include "mdp4_kms.h"
-
-
-struct mdp4_irq_wait {
-       struct mdp4_irq irq;
-       int count;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(wait_event);
-
-static DEFINE_SPINLOCK(list_lock);
-
-static void update_irq(struct mdp4_kms *mdp4_kms)
-{
-       struct mdp4_irq *irq;
-       uint32_t irqmask = mdp4_kms->vblank_mask;
-
-       BUG_ON(!spin_is_locked(&list_lock));
-
-       list_for_each_entry(irq, &mdp4_kms->irq_list, node)
-               irqmask |= irq->irqmask;
-
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, irqmask);
-}
-
-static void update_irq_unlocked(struct mdp4_kms *mdp4_kms)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&list_lock, flags);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void mdp4_irq_error_handler(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       DRM_ERROR("errors: %08x\n", irqstatus);
-}
-
-void mdp4_irq_preinstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
-}
-
-int mdp4_irq_postinstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct mdp4_irq *error_handler = &mdp4_kms->error_handler;
-
-       INIT_LIST_HEAD(&mdp4_kms->irq_list);
-
-       error_handler->irq = mdp4_irq_error_handler;
-       error_handler->irqmask = MDP4_IRQ_PRIMARY_INTF_UDERRUN |
-                       MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
-
-       mdp4_irq_register(mdp4_kms, error_handler);
-
-       return 0;
-}
-
-void mdp4_irq_uninstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
-}
-
-irqreturn_t mdp4_irq(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct drm_device *dev = mdp4_kms->dev;
-       struct msm_drm_private *priv = dev->dev_private;
-       struct mdp4_irq *handler, *n;
-       unsigned long flags;
-       unsigned int id;
-       uint32_t status;
-
-       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);
-
-       VERB("status=%08x", status);
-
-       for (id = 0; id < priv->num_crtcs; id++)
-               if (status & mdp4_crtc_vblank(priv->crtcs[id]))
-                       drm_handle_vblank(dev, id);
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->in_irq = true;
-       list_for_each_entry_safe(handler, n, &mdp4_kms->irq_list, node) {
-               if (handler->irqmask & status) {
-                       spin_unlock_irqrestore(&list_lock, flags);
-                       handler->irq(handler, handler->irqmask & status);
-                       spin_lock_irqsave(&list_lock, flags);
-               }
-       }
-       mdp4_kms->in_irq = false;
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->vblank_mask |= mdp4_crtc_vblank(crtc);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       return 0;
-}
-
-void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->vblank_mask &= ~mdp4_crtc_vblank(crtc);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void wait_irq(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       struct mdp4_irq_wait *wait =
-                       container_of(irq, struct mdp4_irq_wait, irq);
-       wait->count--;
-       wake_up_all(&wait_event);
-}
-
-void mdp4_irq_wait(struct mdp4_kms *mdp4_kms, uint32_t irqmask)
-{
-       struct mdp4_irq_wait wait = {
-               .irq = {
-                       .irq = wait_irq,
-                       .irqmask = irqmask,
-               },
-               .count = 1,
-       };
-       mdp4_irq_register(mdp4_kms, &wait.irq);
-       wait_event(wait_event, (wait.count <= 0));
-       mdp4_irq_unregister(mdp4_kms, &wait.irq);
-}
-
-void mdp4_irq_register(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq)
-{
-       unsigned long flags;
-       bool needs_update = false;
-
-       spin_lock_irqsave(&list_lock, flags);
-
-       if (!irq->registered) {
-               irq->registered = true;
-               list_add(&irq->node, &mdp4_kms->irq_list);
-               needs_update = !mdp4_kms->in_irq;
-       }
-
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       if (needs_update)
-               update_irq_unlocked(mdp4_kms);
-}
-
-void mdp4_irq_unregister(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq)
-{
-       unsigned long flags;
-       bool needs_update = false;
-
-       spin_lock_irqsave(&list_lock, flags);
-
-       if (irq->registered) {
-               irq->registered = false;
-               list_del(&irq->node);
-               needs_update = !mdp4_kms->in_irq;
-       }
-
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       if (needs_update)
-               update_irq_unlocked(mdp4_kms);
-}
index 86537692e45c4efaeae162d32753cf5613216954..e6adafc7eff3177b789395f6bc81f4ab62042e11 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "msm_drv.h"
 #include "msm_gpu.h"
+#include "msm_kms.h"
 
 static void msm_fb_output_poll_changed(struct drm_device *dev)
 {
@@ -30,50 +31,19 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
        .output_poll_changed = msm_fb_output_poll_changed,
 };
 
-static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
-               unsigned long iova, int flags, void *arg)
-{
-       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
-       return 0;
-}
-
-int msm_register_iommu(struct drm_device *dev, struct iommu_domain *iommu)
+int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
 {
        struct msm_drm_private *priv = dev->dev_private;
-       int idx = priv->num_iommus++;
+       int idx = priv->num_mmus++;
 
-       if (WARN_ON(idx >= ARRAY_SIZE(priv->iommus)))
+       if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus)))
                return -EINVAL;
 
-       priv->iommus[idx] = iommu;
-
-       iommu_set_fault_handler(iommu, msm_fault_handler, dev);
-
-       /* need to iommu_attach_device() somewhere??  on resume?? */
+       priv->mmus[idx] = mmu;
 
        return idx;
 }
 
-int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu,
-               const char **names, int cnt)
-{
-       int i, ret;
-
-       for (i = 0; i < cnt; i++) {
-               /* TODO maybe some day msm iommu won't require this hack: */
-               struct device *msm_iommu_get_ctx(const char *ctx_name);
-               struct device *ctx = msm_iommu_get_ctx(names[i]);
-               if (!ctx)
-                       continue;
-               ret = iommu_attach_device(iommu, ctx);
-               if (ret) {
-                       dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
-                       return ret;
-               }
-       }
-       return 0;
-}
-
 #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
 static bool reglog = false;
 MODULE_PARM_DESC(reglog, "Enable register read/write logging");
@@ -82,6 +52,10 @@ module_param(reglog, bool, 0600);
 #define reglog 0
 #endif
 
+static char *vram;
+MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
+module_param(vram, charp, 0);
+
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
                const char *dbgname)
 {
@@ -161,6 +135,14 @@ static int msm_unload(struct drm_device *dev)
                mutex_unlock(&dev->struct_mutex);
        }
 
+       if (priv->vram.paddr) {
+               DEFINE_DMA_ATTRS(attrs);
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+               drm_mm_takedown(&priv->vram.mm);
+               dma_free_attrs(dev->dev, priv->vram.size, NULL,
+                               priv->vram.paddr, &attrs);
+       }
+
        dev->dev_private = NULL;
 
        kfree(priv);
@@ -168,6 +150,24 @@ static int msm_unload(struct drm_device *dev)
        return 0;
 }
 
+static int get_mdp_ver(struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+       const static struct of_device_id match_types[] = { {
+               .compatible = "qcom,mdss_mdp",
+               .data   = (void *)5,
+       }, {
+               /* end node */
+       } };
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *match;
+       match = of_match_node(match_types, dev->of_node);
+       if (match)
+               return (int)match->data;
+#endif
+       return 4;
+}
+
 static int msm_load(struct drm_device *dev, unsigned long flags)
 {
        struct platform_device *pdev = dev->platformdev;
@@ -191,7 +191,53 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
 
-       kms = mdp4_kms_init(dev);
+       /* if we have no IOMMU, then we need to use carveout allocator.
+        * Grab the entire CMA chunk carved out in early startup in
+        * mach-msm:
+        */
+       if (!iommu_present(&platform_bus_type)) {
+               DEFINE_DMA_ATTRS(attrs);
+               unsigned long size;
+               void *p;
+
+               DBG("using %s VRAM carveout", vram);
+               size = memparse(vram, NULL);
+               priv->vram.size = size;
+
+               drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1);
+
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+               dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+
+               /* note that for no-kernel-mapping, the vaddr returned
+                * is bogus, but non-null if allocation succeeded:
+                */
+               p = dma_alloc_attrs(dev->dev, size,
+                               &priv->vram.paddr, 0, &attrs);
+               if (!p) {
+                       dev_err(dev->dev, "failed to allocate VRAM\n");
+                       priv->vram.paddr = 0;
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               dev_info(dev->dev, "VRAM: %08x->%08x\n",
+                               (uint32_t)priv->vram.paddr,
+                               (uint32_t)(priv->vram.paddr + size));
+       }
+
+       switch (get_mdp_ver(pdev)) {
+       case 4:
+               kms = mdp4_kms_init(dev);
+               break;
+       case 5:
+               kms = mdp5_kms_init(dev);
+               break;
+       default:
+               kms = ERR_PTR(-ENODEV);
+               break;
+       }
+
        if (IS_ERR(kms)) {
                /*
                 * NOTE: once we have GPU support, having no kms should not
@@ -326,7 +372,7 @@ static void msm_lastclose(struct drm_device *dev)
        }
 }
 
-static irqreturn_t msm_irq(DRM_IRQ_ARGS)
+static irqreturn_t msm_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct msm_drm_private *priv = dev->dev_private;
@@ -415,7 +461,7 @@ static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
 
 static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
 {
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
@@ -778,12 +824,13 @@ static const struct dev_pm_ops msm_pm_ops = {
 
 static int msm_pdev_probe(struct platform_device *pdev)
 {
+       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        return drm_platform_init(&msm_driver, pdev);
 }
 
 static int msm_pdev_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&msm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
@@ -793,12 +840,19 @@ static const struct platform_device_id msm_id[] = {
        { }
 };
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,mdss_mdp" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver msm_platform_driver = {
        .probe      = msm_pdev_probe,
        .remove     = msm_pdev_remove,
        .driver     = {
                .owner  = THIS_MODULE,
                .name   = "msm",
+               .of_match_table = dt_match,
                .pm     = &msm_pm_ops,
        },
        .id_table   = msm_id,
index d39f0862b19ebe8db2a74fdcedbb8a52086df3a7..3d63269c5b29c51e69bc0dfe7714dddae71e4fee 100644 (file)
 #include <linux/types.h>
 #include <asm/sizes.h>
 
+
+#if defined(CONFIG_COMPILE_TEST) && !defined(CONFIG_ARCH_MSM)
+/* stubs we need for compile-test: */
+static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+       return NULL;
+}
+#endif
+
 #ifndef CONFIG_OF
 #include <mach/board.h>
 #include <mach/socinfo.h>
@@ -44,6 +53,7 @@
 
 struct msm_kms;
 struct msm_gpu;
+struct msm_mmu;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
 
@@ -76,9 +86,9 @@ struct msm_drm_private {
        /* callbacks deferred until bo is inactive: */
        struct list_head fence_cbs;
 
-       /* registered IOMMU domains: */
-       unsigned int num_iommus;
-       struct iommu_domain *iommus[NUM_DOMAINS];
+       /* registered MMUs: */
+       unsigned int num_mmus;
+       struct msm_mmu *mmus[NUM_DOMAINS];
 
        unsigned int num_planes;
        struct drm_plane *planes[8];
@@ -94,6 +104,16 @@ struct msm_drm_private {
 
        unsigned int num_connectors;
        struct drm_connector *connectors[8];
+
+       /* VRAM carveout, used when no IOMMU: */
+       struct {
+               unsigned long size;
+               dma_addr_t paddr;
+               /* NOTE: mm managed at the page level, size is in # of pages
+                * and position mm_node->start is in # of pages:
+                */
+               struct drm_mm mm;
+       } vram;
 };
 
 struct msm_format {
@@ -114,39 +134,7 @@ void __msm_fence_worker(struct work_struct *work);
                (_cb)->func = _func;                         \
        } while (0)
 
-/* As there are different display controller blocks depending on the
- * snapdragon version, the kms support is split out and the appropriate
- * implementation is loaded at runtime.  The kms module is responsible
- * for constructing the appropriate planes/crtcs/encoders/connectors.
- */
-struct msm_kms_funcs {
-       /* hw initialization: */
-       int (*hw_init)(struct msm_kms *kms);
-       /* irq handling: */
-       void (*irq_preinstall)(struct msm_kms *kms);
-       int (*irq_postinstall)(struct msm_kms *kms);
-       void (*irq_uninstall)(struct msm_kms *kms);
-       irqreturn_t (*irq)(struct msm_kms *kms);
-       int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
-       void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
-       /* misc: */
-       const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
-       long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
-                       struct drm_encoder *encoder);
-       /* cleanup: */
-       void (*preclose)(struct msm_kms *kms, struct drm_file *file);
-       void (*destroy)(struct msm_kms *kms);
-};
-
-struct msm_kms {
-       const struct msm_kms_funcs *funcs;
-};
-
-struct msm_kms *mdp4_kms_init(struct drm_device *dev);
-
-int msm_register_iommu(struct drm_device *dev, struct iommu_domain *iommu);
-int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu,
-               const char **names, int cnt);
+int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
 int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
                struct timespec *timeout);
@@ -202,7 +190,9 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
 
 struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
 
-int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder);
+struct hdmi;
+struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder);
+irqreturn_t hdmi_irq(int irq, void *dev_id);
 void __init hdmi_register(void);
 void __exit hdmi_unregister(void);
 
index 0286c0eeb10ca1e967c27bf559928de58d14358f..81bafdf19ab39fc32428e6f5be692c597a6a8276 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "msm_drv.h"
+#include "msm_kms.h"
 
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
index e587d251c5900cd4532cdbff584d0683131616ed..d8d60c969ac7858bce0e6114f092a5f1aad450aa 100644 (file)
 #include "msm_drv.h"
 #include "msm_gem.h"
 #include "msm_gpu.h"
+#include "msm_mmu.h"
 
+static dma_addr_t physaddr(struct drm_gem_object *obj)
+{
+       struct msm_gem_object *msm_obj = to_msm_bo(obj);
+       struct msm_drm_private *priv = obj->dev->dev_private;
+       return (((dma_addr_t)msm_obj->vram_node->start) << PAGE_SHIFT) +
+                       priv->vram.paddr;
+}
+
+/* allocate pages from VRAM carveout, used when no IOMMU: */
+static struct page **get_pages_vram(struct drm_gem_object *obj,
+               int npages)
+{
+       struct msm_gem_object *msm_obj = to_msm_bo(obj);
+       struct msm_drm_private *priv = obj->dev->dev_private;
+       dma_addr_t paddr;
+       struct page **p;
+       int ret, i;
+
+       p = drm_malloc_ab(npages, sizeof(struct page *));
+       if (!p)
+               return ERR_PTR(-ENOMEM);
+
+       ret = drm_mm_insert_node(&priv->vram.mm, msm_obj->vram_node,
+                       npages, 0, DRM_MM_SEARCH_DEFAULT);
+       if (ret) {
+               drm_free_large(p);
+               return ERR_PTR(ret);
+       }
+
+       paddr = physaddr(obj);
+       for (i = 0; i < npages; i++) {
+               p[i] = phys_to_page(paddr);
+               paddr += PAGE_SIZE;
+       }
+
+       return p;
+}
 
 /* called with dev->struct_mutex held */
 static struct page **get_pages(struct drm_gem_object *obj)
@@ -31,9 +69,14 @@ static struct page **get_pages(struct drm_gem_object *obj)
 
        if (!msm_obj->pages) {
                struct drm_device *dev = obj->dev;
-               struct page **p = drm_gem_get_pages(obj, 0);
+               struct page **p;
                int npages = obj->size >> PAGE_SHIFT;
 
+               if (iommu_present(&platform_bus_type))
+                       p = drm_gem_get_pages(obj, 0);
+               else
+                       p = get_pages_vram(obj, npages);
+
                if (IS_ERR(p)) {
                        dev_err(dev->dev, "could not get pages: %ld\n",
                                        PTR_ERR(p));
@@ -73,7 +116,11 @@ static void put_pages(struct drm_gem_object *obj)
                sg_free_table(msm_obj->sgt);
                kfree(msm_obj->sgt);
 
-               drm_gem_put_pages(obj, msm_obj->pages, true, false);
+               if (iommu_present(&platform_bus_type))
+                       drm_gem_put_pages(obj, msm_obj->pages, true, false);
+               else
+                       drm_mm_remove_node(msm_obj->vram_node);
+
                msm_obj->pages = NULL;
        }
 }
@@ -138,7 +185,6 @@ int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
-       struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct drm_device *dev = obj->dev;
        struct page **pages;
        unsigned long pfn;
@@ -163,7 +209,7 @@ int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        pgoff = ((unsigned long)vmf->virtual_address -
                        vma->vm_start) >> PAGE_SHIFT;
 
-       pfn = page_to_pfn(msm_obj->pages[pgoff]);
+       pfn = page_to_pfn(pages[pgoff]);
 
        VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
                        pfn, pfn << PAGE_SHIFT);
@@ -219,67 +265,6 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj)
        return offset;
 }
 
-/* helpers for dealing w/ iommu: */
-static int map_range(struct iommu_domain *domain, unsigned int iova,
-               struct sg_table *sgt, unsigned int len, int prot)
-{
-       struct scatterlist *sg;
-       unsigned int da = iova;
-       unsigned int i, j;
-       int ret;
-
-       if (!domain || !sgt)
-               return -EINVAL;
-
-       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-               u32 pa = sg_phys(sg) - sg->offset;
-               size_t bytes = sg->length + sg->offset;
-
-               VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes);
-
-               ret = iommu_map(domain, da, pa, bytes, prot);
-               if (ret)
-                       goto fail;
-
-               da += bytes;
-       }
-
-       return 0;
-
-fail:
-       da = iova;
-
-       for_each_sg(sgt->sgl, sg, i, j) {
-               size_t bytes = sg->length + sg->offset;
-               iommu_unmap(domain, da, bytes);
-               da += bytes;
-       }
-       return ret;
-}
-
-static void unmap_range(struct iommu_domain *domain, unsigned int iova,
-               struct sg_table *sgt, unsigned int len)
-{
-       struct scatterlist *sg;
-       unsigned int da = iova;
-       int i;
-
-       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-               size_t bytes = sg->length + sg->offset;
-               size_t unmapped;
-
-               unmapped = iommu_unmap(domain, da, bytes);
-               if (unmapped < bytes)
-                       break;
-
-               VERB("unmap[%d]: %08x(%x)", i, iova, bytes);
-
-               BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
-               da += bytes;
-       }
-}
-
 /* should be called under struct_mutex.. although it can be called
  * from atomic context without struct_mutex to acquire an extra
  * iova ref if you know one is already held.
@@ -295,15 +280,20 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
 
        if (!msm_obj->domain[id].iova) {
                struct msm_drm_private *priv = obj->dev->dev_private;
-               uint32_t offset = (uint32_t)mmap_offset(obj);
-               struct page **pages;
-               pages = get_pages(obj);
+               struct msm_mmu *mmu = priv->mmus[id];
+               struct page **pages = get_pages(obj);
+
                if (IS_ERR(pages))
                        return PTR_ERR(pages);
-               // XXX ideally we would not map buffers writable when not needed...
-               ret = map_range(priv->iommus[id], offset, msm_obj->sgt,
-                               obj->size, IOMMU_READ | IOMMU_WRITE);
-               msm_obj->domain[id].iova = offset;
+
+               if (iommu_present(&platform_bus_type)) {
+                       uint32_t offset = (uint32_t)mmap_offset(obj);
+                       ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
+                                       obj->size, IOMMU_READ | IOMMU_WRITE);
+                       msm_obj->domain[id].iova = offset;
+               } else {
+                       msm_obj->domain[id].iova = physaddr(obj);
+               }
        }
 
        if (!ret)
@@ -514,6 +504,7 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
 void msm_gem_free_object(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
+       struct msm_drm_private *priv = obj->dev->dev_private;
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        int id;
 
@@ -525,11 +516,10 @@ void msm_gem_free_object(struct drm_gem_object *obj)
        list_del(&msm_obj->mm_list);
 
        for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
-               if (msm_obj->domain[id].iova) {
-                       struct msm_drm_private *priv = obj->dev->dev_private;
+               struct msm_mmu *mmu = priv->mmus[id];
+               if (mmu && msm_obj->domain[id].iova) {
                        uint32_t offset = (uint32_t)mmap_offset(obj);
-                       unmap_range(priv->iommus[id], offset,
-                                       msm_obj->sgt, obj->size);
+                       mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size);
                }
        }
 
@@ -591,6 +581,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
 {
        struct msm_drm_private *priv = dev->dev_private;
        struct msm_gem_object *msm_obj;
+       unsigned sz;
 
        switch (flags & MSM_BO_CACHE_MASK) {
        case MSM_BO_UNCACHED:
@@ -603,10 +594,17 @@ static int msm_gem_new_impl(struct drm_device *dev,
                return -EINVAL;
        }
 
-       msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);
+       sz = sizeof(*msm_obj);
+       if (!iommu_present(&platform_bus_type))
+               sz += sizeof(struct drm_mm_node);
+
+       msm_obj = kzalloc(sz, GFP_KERNEL);
        if (!msm_obj)
                return -ENOMEM;
 
+       if (!iommu_present(&platform_bus_type))
+               msm_obj->vram_node = (void *)&msm_obj[1];
+
        msm_obj->flags = flags;
 
        msm_obj->resv = &msm_obj->_resv;
@@ -623,7 +621,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
 struct drm_gem_object *msm_gem_new(struct drm_device *dev,
                uint32_t size, uint32_t flags)
 {
-       struct drm_gem_object *obj;
+       struct drm_gem_object *obj = NULL;
        int ret;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -634,9 +632,13 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
        if (ret)
                goto fail;
 
-       ret = drm_gem_object_init(dev, obj, size);
-       if (ret)
-               goto fail;
+       if (iommu_present(&platform_bus_type)) {
+               ret = drm_gem_object_init(dev, obj, size);
+               if (ret)
+                       goto fail;
+       } else {
+               drm_gem_private_object_init(dev, obj, size);
+       }
 
        return obj;
 
@@ -654,6 +656,12 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
        struct drm_gem_object *obj;
        int ret, npages;
 
+       /* if we don't have IOMMU, don't bother pretending we can import: */
+       if (!iommu_present(&platform_bus_type)) {
+               dev_err(dev->dev, "cannot import without IOMMU\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        size = PAGE_ALIGN(size);
 
        ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
index f4f23a578d9dc76fe4b7d03498729b099471694a..3246bb46c4f2add0636bca94b1b4c726542b1178 100644 (file)
@@ -57,6 +57,11 @@ struct msm_gem_object {
        /* normally (resv == &_resv) except for imported bo's */
        struct reservation_object *resv;
        struct reservation_object _resv;
+
+       /* For physically contiguous buffers.  Used when we don't have
+        * an IOMMU.
+        */
+       struct drm_mm_node *vram_node;
 };
 #define to_msm_bo(x) container_of(x, struct msm_gem_object, base)
 
index 4583d61556f5bed5c7d9cf9d26988d1160ddb386..4ebce8be489db6cdf51f6ba88fb8f7bfd1dbd5ce 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "msm_gpu.h"
 #include "msm_gem.h"
+#include "msm_mmu.h"
 
 
 /*
 
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
-#include <mach/kgsl.h>
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev)
+static void bs_init(struct msm_gpu *gpu)
 {
-       struct drm_device *dev = gpu->dev;
-       struct kgsl_device_platform_data *pdata;
-
-       if (!pdev) {
-               dev_err(dev->dev, "could not find dtv pdata\n");
-               return;
-       }
-
-       pdata = pdev->dev.platform_data;
-       if (pdata->bus_scale_table) {
-               gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
+       if (gpu->bus_scale_table) {
+               gpu->bsc = msm_bus_scale_register_client(gpu->bus_scale_table);
                DBG("bus scale client: %08x", gpu->bsc);
        }
 }
@@ -59,7 +50,7 @@ static void bs_set(struct msm_gpu *gpu, int idx)
        }
 }
 #else
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) {}
+static void bs_init(struct msm_gpu *gpu) {}
 static void bs_fini(struct msm_gpu *gpu) {}
 static void bs_set(struct msm_gpu *gpu, int idx) {}
 #endif
@@ -363,6 +354,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
                const char *name, const char *ioname, const char *irqname, int ringsz)
 {
+       struct iommu_domain *iommu;
        int i, ret;
 
        gpu->dev = drm;
@@ -428,13 +420,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
         * and have separate page tables per context.  For now, to keep things
         * simple and to get something working, just use a single address space:
         */
-       gpu->iommu = iommu_domain_alloc(&platform_bus_type);
-       if (!gpu->iommu) {
-               dev_err(drm->dev, "failed to allocate IOMMU\n");
-               ret = -ENOMEM;
-               goto fail;
+       iommu = iommu_domain_alloc(&platform_bus_type);
+       if (iommu) {
+               dev_info(drm->dev, "%s: using IOMMU\n", name);
+               gpu->mmu = msm_iommu_new(drm, iommu);
+       } else {
+               dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
        }
-       gpu->id = msm_register_iommu(drm, gpu->iommu);
+       gpu->id = msm_register_mmu(drm, gpu->mmu);
 
        /* Create ringbuffer: */
        gpu->rb = msm_ringbuffer_new(gpu, ringsz);
@@ -452,7 +445,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                goto fail;
        }
 
-       bs_init(gpu, pdev);
+       bs_init(gpu);
 
        return 0;
 
@@ -474,6 +467,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
                msm_ringbuffer_destroy(gpu->rb);
        }
 
-       if (gpu->iommu)
-               iommu_domain_free(gpu->iommu);
+       if (gpu->mmu)
+               gpu->mmu->funcs->destroy(gpu->mmu);
 }
index 8cd829e520bb84b6bfa10d90fce8236cf9fbd3c5..458db8c64c28873f260aa59b44bbd96da7a3b18f 100644 (file)
@@ -78,14 +78,18 @@ struct msm_gpu {
        void __iomem *mmio;
        int irq;
 
-       struct iommu_domain *iommu;
+       struct msm_mmu *mmu;
        int id;
 
        /* Power Control: */
        struct regulator *gpu_reg, *gpu_cx;
        struct clk *ebi1_clk, *grp_clks[5];
        uint32_t fast_rate, slow_rate, bus_freq;
+
+#ifdef CONFIG_MSM_BUS_SCALING
+       struct msm_bus_scale_pdata *bus_scale_table;
        uint32_t bsc;
+#endif
 
        /* Hang Detction: */
 #define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
new file mode 100644 (file)
index 0000000..92b7459
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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 "msm_drv.h"
+#include "msm_mmu.h"
+
+struct msm_iommu {
+       struct msm_mmu base;
+       struct iommu_domain *domain;
+};
+#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
+
+static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
+               unsigned long iova, int flags, void *arg)
+{
+       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
+       return 0;
+}
+
+static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
+{
+       struct drm_device *dev = mmu->dev;
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       int i, ret;
+
+       for (i = 0; i < cnt; i++) {
+               struct device *msm_iommu_get_ctx(const char *ctx_name);
+               struct device *ctx = msm_iommu_get_ctx(names[i]);
+               if (IS_ERR_OR_NULL(ctx))
+                       continue;
+               ret = iommu_attach_device(iommu->domain, ctx);
+               if (ret) {
+                       dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
+               struct sg_table *sgt, unsigned len, int prot)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       unsigned int i, j;
+       int ret;
+
+       if (!domain || !sgt)
+               return -EINVAL;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               u32 pa = sg_phys(sg) - sg->offset;
+               size_t bytes = sg->length + sg->offset;
+
+               VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes);
+
+               ret = iommu_map(domain, da, pa, bytes, prot);
+               if (ret)
+                       goto fail;
+
+               da += bytes;
+       }
+
+       return 0;
+
+fail:
+       da = iova;
+
+       for_each_sg(sgt->sgl, sg, i, j) {
+               size_t bytes = sg->length + sg->offset;
+               iommu_unmap(domain, da, bytes);
+               da += bytes;
+       }
+       return ret;
+}
+
+static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
+               struct sg_table *sgt, unsigned len)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       int i;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               size_t bytes = sg->length + sg->offset;
+               size_t unmapped;
+
+               unmapped = iommu_unmap(domain, da, bytes);
+               if (unmapped < bytes)
+                       return unmapped;
+
+               VERB("unmap[%d]: %08x(%x)", i, iova, bytes);
+
+               BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
+
+               da += bytes;
+       }
+
+       return 0;
+}
+
+static void msm_iommu_destroy(struct msm_mmu *mmu)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       iommu_domain_free(iommu->domain);
+       kfree(iommu);
+}
+
+static const struct msm_mmu_funcs funcs = {
+               .attach = msm_iommu_attach,
+               .map = msm_iommu_map,
+               .unmap = msm_iommu_unmap,
+               .destroy = msm_iommu_destroy,
+};
+
+struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain)
+{
+       struct msm_iommu *iommu;
+
+       iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+       if (!iommu)
+               return ERR_PTR(-ENOMEM);
+
+       iommu->domain = domain;
+       msm_mmu_init(&iommu->base, dev, &funcs);
+       iommu_set_fault_handler(domain, msm_fault_handler, dev);
+
+       return &iommu->base;
+}
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
new file mode 100644 (file)
index 0000000..0643774
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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/>.
+ */
+
+#ifndef __MSM_KMS_H__
+#define __MSM_KMS_H__
+
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "msm_drv.h"
+
+/* As there are different display controller blocks depending on the
+ * snapdragon version, the kms support is split out and the appropriate
+ * implementation is loaded at runtime.  The kms module is responsible
+ * for constructing the appropriate planes/crtcs/encoders/connectors.
+ */
+struct msm_kms_funcs {
+       /* hw initialization: */
+       int (*hw_init)(struct msm_kms *kms);
+       /* irq handling: */
+       void (*irq_preinstall)(struct msm_kms *kms);
+       int (*irq_postinstall)(struct msm_kms *kms);
+       void (*irq_uninstall)(struct msm_kms *kms);
+       irqreturn_t (*irq)(struct msm_kms *kms);
+       int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+       void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+       /* misc: */
+       const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
+       long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
+                       struct drm_encoder *encoder);
+       /* cleanup: */
+       void (*preclose)(struct msm_kms *kms, struct drm_file *file);
+       void (*destroy)(struct msm_kms *kms);
+};
+
+struct msm_kms {
+       const struct msm_kms_funcs *funcs;
+
+       /* irq handling: */
+       bool in_irq;
+       struct list_head irq_list;    /* list of mdp4_irq */
+       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+};
+
+static inline void msm_kms_init(struct msm_kms *kms,
+               const struct msm_kms_funcs *funcs)
+{
+       kms->funcs = funcs;
+}
+
+struct msm_kms *mdp4_kms_init(struct drm_device *dev);
+struct msm_kms *mdp5_kms_init(struct drm_device *dev);
+
+#endif /* __MSM_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
new file mode 100644 (file)
index 0000000..0303244
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@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 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/>.
+ */
+
+#ifndef __MSM_MMU_H__
+#define __MSM_MMU_H__
+
+#include <linux/iommu.h>
+
+struct msm_mmu_funcs {
+       int (*attach)(struct msm_mmu *mmu, const char **names, int cnt);
+       int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+                       unsigned len, int prot);
+       int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+                       unsigned len);
+       void (*destroy)(struct msm_mmu *mmu);
+};
+
+struct msm_mmu {
+       const struct msm_mmu_funcs *funcs;
+       struct drm_device *dev;
+};
+
+static inline void msm_mmu_init(struct msm_mmu *mmu, struct drm_device *dev,
+               const struct msm_mmu_funcs *funcs)
+{
+       mmu->dev = dev;
+       mmu->funcs = funcs;
+}
+
+struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain);
+struct msm_mmu *msm_gpummu_new(struct drm_device *dev, struct msm_gpu *gpu);
+
+#endif /* __MSM_MMU_H__ */
index b3fa1ba191b7115be412894936c3633bf9221188..e88145ba1bf515429a3b85753bde5df7d28bde70 100644 (file)
@@ -41,6 +41,7 @@ nouveau-y += core/subdev/bios/init.o
 nouveau-y += core/subdev/bios/mxm.o
 nouveau-y += core/subdev/bios/perf.o
 nouveau-y += core/subdev/bios/pll.o
+nouveau-y += core/subdev/bios/ramcfg.o
 nouveau-y += core/subdev/bios/rammap.o
 nouveau-y += core/subdev/bios/timing.o
 nouveau-y += core/subdev/bios/therm.o
@@ -71,7 +72,10 @@ nouveau-y += core/subdev/devinit/nv10.o
 nouveau-y += core/subdev/devinit/nv1a.o
 nouveau-y += core/subdev/devinit/nv20.o
 nouveau-y += core/subdev/devinit/nv50.o
+nouveau-y += core/subdev/devinit/nv84.o
+nouveau-y += core/subdev/devinit/nv98.o
 nouveau-y += core/subdev/devinit/nva3.o
+nouveau-y += core/subdev/devinit/nvaf.o
 nouveau-y += core/subdev/devinit/nvc0.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
@@ -232,6 +236,7 @@ nouveau-y += core/engine/fifo/nv50.o
 nouveau-y += core/engine/fifo/nv84.o
 nouveau-y += core/engine/fifo/nvc0.o
 nouveau-y += core/engine/fifo/nve0.o
+nouveau-y += core/engine/fifo/nv108.o
 nouveau-y += core/engine/graph/ctxnv40.o
 nouveau-y += core/engine/graph/ctxnv50.o
 nouveau-y += core/engine/graph/ctxnvc0.o
@@ -242,6 +247,7 @@ nouveau-y += core/engine/graph/ctxnvd7.o
 nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
 nouveau-y += core/engine/graph/ctxnvf0.o
+nouveau-y += core/engine/graph/ctxnv108.o
 nouveau-y += core/engine/graph/nv04.o
 nouveau-y += core/engine/graph/nv10.o
 nouveau-y += core/engine/graph/nv20.o
@@ -260,6 +266,7 @@ nouveau-y += core/engine/graph/nvd7.o
 nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
 nouveau-y += core/engine/graph/nvf0.o
+nouveau-y += core/engine/graph/nv108.o
 nouveau-y += core/engine/mpeg/nv31.o
 nouveau-y += core/engine/mpeg/nv40.o
 nouveau-y += core/engine/mpeg/nv44.o
index c8bed4a2683339072786a0b4d146b06c9594cc5b..1f6954ae9dd36e51141a9b810d91e49f1ddad2b2 100644 (file)
@@ -42,11 +42,24 @@ nouveau_engine_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       if ( parent &&
-           !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) {
-               if (!enable)
-                       nv_warn(engine, "disabled, %s=1 to enable\n", iname);
-               return -ENODEV;
+       if (parent) {
+               struct nouveau_device *device = nv_device(parent);
+               int engidx = nv_engidx(nv_object(engine));
+
+               if (device->disable_mask & (1ULL << engidx)) {
+                       if (!nouveau_boolopt(device->cfgopt, iname, false)) {
+                               nv_debug(engine, "engine disabled by hw/fw\n");
+                               return -ENODEV;
+                       }
+
+                       nv_warn(engine, "ignoring hw/fw engine disable\n");
+               }
+
+               if (!nouveau_boolopt(device->cfgopt, iname, enable)) {
+                       if (!enable)
+                               nv_warn(engine, "disabled, %s=1 to enable\n", iname);
+                       return -ENODEV;
+               }
        }
 
        INIT_LIST_HEAD(&engine->contexts);
index 48f06378d3f9d5f9e09e03291a11d6e26527f674..2ea5568b6cf59be811fa6777612eca8b8180736b 100644 (file)
@@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent,
 
        if (parent) {
                struct nouveau_device *device = nv_device(parent);
-               int subidx = nv_hclass(subdev) & 0xff;
-
                subdev->debug = nouveau_dbgopt(device->dbgopt, subname);
                subdev->mmio  = nv_subdev(device)->mmio;
-               device->subdev[subidx] = *pobject;
        }
 
        return 0;
index 993df09ad64386e51ab7316e1dbc57de5cba5409..ac3291f781f6e4c204506e02d39d8ca521cf8917 100644 (file)
@@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000100)
-               return -ENODEV;
-
        ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,
                                    "PCE0", "copy0", &priv);
        *pobject = nv_object(priv);
@@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000200)
-               return -ENODEV;
-
        ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,
                                    "PCE1", "copy1", &priv);
        *pobject = nv_object(priv);
index 30f1ef1edcc59db83deb0e12a41f6d1f399e23c6..748a61eb3c6f25fe4c08bed0a374b2148852e0f5 100644 (file)
@@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000100)
-               return -ENODEV;
-
        ret = nouveau_engine_create(parent, engine, oclass, true,
                                    "PCE0", "copy0", &priv);
        *pobject = nv_object(priv);
@@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000200)
-               return -ENODEV;
-
        ret = nouveau_engine_create(parent, engine, oclass, true,
                                    "PCE1", "copy1", &priv);
        *pobject = nv_object(priv);
index 9135b25a29d09a4e82e57e1c9a1a27608eee6a99..dd01c6c435d6e2e01ecb92ccbd57cf09e7346660 100644 (file)
@@ -268,6 +268,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                if (ret)
                        return ret;
 
+               device->subdev[i] = devobj->subdev[i];
+
                /* note: can't init *any* subdevs until devinit has been run
                 * due to not knowing exactly what the vbios init tables will
                 * mess with.  devinit also can't be run until all of its
index dbd2dde7b7e7649d2873c513d69a263b59329b77..32113b08c4d5fb16e401e871ec65080d61a63e7c 100644 (file)
@@ -49,12 +49,12 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
@@ -67,12 +67,12 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
index 6e03dd6abeea51da34fe9e1046e50075fc481070..744f15d7e1315a6a3b9406f364d0a8bf78231cd5 100644 (file)
@@ -51,12 +51,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -68,12 +68,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -87,12 +87,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -106,12 +106,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -125,12 +125,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -144,12 +144,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -163,12 +163,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -182,12 +182,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index dcde53b9f07f7cd77f2886b8c8b927054691f289..27ba61fb271045c1efa9acd2982c48ce7b60f278 100644 (file)
@@ -52,12 +52,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -109,12 +109,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index 7b8662ef4f59193a91246ad074c8e87d84bb9019..fd47ace67543cd15f6be3c6b6799aefe497e4dcf 100644 (file)
@@ -52,12 +52,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -110,12 +110,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -130,12 +130,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index c8c41e93695ee3d0f83da140f0615cb737c14472..1b653dd74a7046ceaae41bca181f3097827dcccd 100644 (file)
@@ -57,12 +57,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -80,12 +80,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -103,12 +103,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -126,12 +126,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -149,12 +149,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -172,12 +172,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv47_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -195,12 +195,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -218,12 +218,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -241,12 +241,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -264,12 +264,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -287,12 +287,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -310,12 +310,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -333,12 +333,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv4e_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -356,12 +356,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -379,12 +379,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -402,12 +402,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
index db3fc7be856a733d07f8431a182326e3f20b4182..81d5c26643d50dcff2067abdf0f2bb7a227621ad 100644 (file)
@@ -65,12 +65,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv50_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -90,12 +90,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -118,12 +118,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -146,12 +146,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -174,12 +174,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -202,12 +202,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -230,12 +230,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -258,12 +258,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -286,12 +286,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -314,12 +314,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -342,12 +342,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -372,12 +372,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -401,12 +401,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -430,12 +430,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaf_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
index 8d06eef2b9ee02f7b3d895c8d7a37bfd6e022924..b7d66b59f43d4c7cc3ea0c733f809f966c37aa3d 100644 (file)
@@ -65,14 +65,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -97,14 +97,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -129,14 +129,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -160,14 +160,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -192,14 +192,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -224,14 +224,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -255,14 +255,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -287,14 +287,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -318,14 +318,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
index 3900104976fc7bfc2ca3df441318254bdae3bf97..987edbc30a0917cc2db2a035c749f42c5818b5b9 100644 (file)
@@ -65,14 +65,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -98,14 +98,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -131,14 +131,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -164,14 +164,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -199,29 +199,27 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
-#if 0
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
-#endif
+               device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass;
-#if 0
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+#if 0
                device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
index 378a015091d2bf22d9a2ba5e49cd095b3ac774c7..d52c0f50a1a9b0076682a01171418da974625bfb 100644 (file)
@@ -967,9 +967,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index fb1fe6ae5e74ddbd6f3336a3d34de8eb58757b5b..20725b363d582b3485b55f5ef4692247d20adce2 100644 (file)
@@ -54,9 +54,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index 42aa6b97dbea3c5867676f0209151a1ead3a849d..a488c36e40f9dc0d7923362dd1c09e346b37b7dd 100644 (file)
@@ -54,9 +54,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index 5a1c68474597cbc979eb216735941714b1ce4901..8836c3cb99c3862a84ed2b946e6c3e34c47e520d 100644 (file)
@@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
 bool
 nv_lockvgac(void *obj, bool lock)
 {
+       struct nouveau_device *dev = nv_device(obj);
+
        bool locked = !nv_rdvgac(obj, 0, 0x1f);
        u8 data = lock ? 0x99 : 0x57;
-       nv_wrvgac(obj, 0, 0x1f, data);
-       if (nv_device(obj)->chipset == 0x11) {
+       if (dev->card_type < NV_50)
+               nv_wrvgac(obj, 0, 0x1f, data);
+       else
+               nv_wrvgac(obj, 0, 0x3f, data);
+       if (dev->chipset == 0x11) {
                if (!(nv_rd32(obj, 0x001084) & 0x10000000))
                        nv_wrvgac(obj, 1, 0x1f, data);
        }
index e03fc8e4dc1dac8c8262a93b2b0b812dcae60841..5e077e4ed7f6aa23d0e8ed3fde50ad58c2fd99d7 100644 (file)
@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)
        nv_wr32(falcon, falcon->addr + addr, data);
 }
 
+static void *
+vmemdup(const void *src, size_t len)
+{
+       void *p = vmalloc(len);
+
+       if (p)
+               memcpy(p, src, len);
+       return p;
+}
+
 int
 _nouveau_falcon_init(struct nouveau_object *object)
 {
@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
 
                ret = request_firmware(&fw, name, &device->pdev->dev);
                if (ret == 0) {
-                       falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+                       falcon->code.data = vmemdup(fw->data, fw->size);
                        falcon->code.size = fw->size;
                        falcon->data.data = NULL;
                        falcon->data.size = 0;
@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                        return ret;
                }
 
-               falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+               falcon->data.data = vmemdup(fw->data, fw->size);
                falcon->data.size = fw->size;
                release_firmware(fw);
                if (!falcon->data.data)
@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                        return ret;
                }
 
-               falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+               falcon->code.data = vmemdup(fw->data, fw->size);
                falcon->code.size = fw->size;
                release_firmware(fw);
                if (!falcon->code.data)
@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
        if (!suspend) {
                nouveau_gpuobj_ref(NULL, &falcon->core);
                if (falcon->external) {
-                       kfree(falcon->data.data);
-                       kfree(falcon->code.data);
+                       vfree(falcon->data.data);
+                       vfree(falcon->code.data);
                        falcon->code.data = NULL;
                }
        }
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c
new file mode 100644 (file)
index 0000000..09362a5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#include "nve0.h"
+
+struct nouveau_oclass *
+nv108_fifo_oclass = &(struct nve0_fifo_impl) {
+       .base.handle = NV_ENGINE(FIFO, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nve0_fifo_ctor,
+               .dtor = nve0_fifo_dtor,
+               .init = nve0_fifo_init,
+               .fini = _nouveau_fifo_fini,
+       },
+       .channels = 1024,
+}.base;
index 9ac94d4e5646d2cd24579f3b47777f2e17f5e9fe..b22a33f0702dd0159ed01f79edb00b7349f6b561 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
index 04f412922d2d43f5a5fbce11185fc2f9f4196e7e..9a850fe19515fe2ddcd513c3497c7d87c86cba8a 100644 (file)
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
-#include <engine/fifo.h>
+
+#include "nve0.h"
 
 #define _(a,b) { (a), ((1ULL << (a)) | (b)) }
 static const struct {
@@ -56,8 +58,8 @@ static const struct {
 #define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
 
 struct nve0_fifo_engn {
-       struct nouveau_gpuobj *playlist[2];
-       int cur_playlist;
+       struct nouveau_gpuobj *runlist[2];
+       int cur_runlist;
 };
 
 struct nve0_fifo_priv {
@@ -86,7 +88,7 @@ struct nve0_fifo_chan {
  ******************************************************************************/
 
 static void
-nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
+nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
 {
        struct nouveau_bar *bar = nouveau_bar(priv);
        struct nve0_fifo_engn *engn = &priv->engine[engine];
@@ -95,8 +97,8 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        int i, p;
 
        mutex_lock(&nv_subdev(priv)->mutex);
-       cur = engn->playlist[engn->cur_playlist];
-       engn->cur_playlist = !engn->cur_playlist;
+       cur = engn->runlist[engn->cur_runlist];
+       engn->cur_runlist = !engn->cur_runlist;
 
        for (i = 0, p = 0; i < priv->base.max; i++) {
                u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001;
@@ -111,7 +113,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
        if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
-               nv_error(priv, "playlist %d update timeout\n", engine);
+               nv_error(priv, "runlist %d update timeout\n", engine);
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
@@ -278,7 +280,7 @@ nve0_fifo_chan_init(struct nouveau_object *object)
        nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
-       nve0_fifo_playlist_update(priv, chan->engine);
+       nve0_fifo_runlist_update(priv, chan->engine);
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
        return 0;
 }
@@ -291,7 +293,7 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
        u32 chid = chan->base.chid;
 
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
-       nve0_fifo_playlist_update(priv, chan->engine);
+       nve0_fifo_runlist_update(priv, chan->engine);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
 
        return nouveau_fifo_channel_fini(&chan->base, suspend);
@@ -375,54 +377,189 @@ nve0_fifo_cclass = {
  * PFIFO engine
  ******************************************************************************/
 
-static const struct nouveau_enum nve0_fifo_fault_unit[] = {
+static const struct nouveau_enum nve0_fifo_sched_reason[] = {
+       { 0x0a, "CTXSW_TIMEOUT" },
+       {}
+};
+
+static const struct nouveau_enum nve0_fifo_fault_engine[] = {
+       { 0x00, "GR", NULL, NVDEV_ENGINE_GR },
+       { 0x03, "IFB" },
+       { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
+       { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
+       { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
+       { 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO },
+       { 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO },
+       { 0x10, "MSVLD", NULL, NVDEV_ENGINE_BSP },
+       { 0x11, "MSPPP", NULL, NVDEV_ENGINE_PPP },
+       { 0x13, "PERF" },
+       { 0x14, "MSPDEC", NULL, NVDEV_ENGINE_VP },
+       { 0x15, "CE0", NULL, NVDEV_ENGINE_COPY0 },
+       { 0x16, "CE1", NULL, NVDEV_ENGINE_COPY1 },
+       { 0x17, "PMU" },
+       { 0x19, "MSENC", NULL, NVDEV_ENGINE_VENC },
+       { 0x1b, "CE2", NULL, NVDEV_ENGINE_COPY2 },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_reason[] = {
-       { 0x00, "PT_NOT_PRESENT" },
-       { 0x01, "PT_TOO_SHORT" },
-       { 0x02, "PAGE_NOT_PRESENT" },
-       { 0x03, "VM_LIMIT_EXCEEDED" },
-       { 0x04, "NO_CHANNEL" },
-       { 0x05, "PAGE_SYSTEM_ONLY" },
-       { 0x06, "PAGE_READ_ONLY" },
-       { 0x0a, "COMPRESSED_SYSRAM" },
-       { 0x0c, "INVALID_STORAGE_TYPE" },
+       { 0x00, "PDE" },
+       { 0x01, "PDE_SIZE" },
+       { 0x02, "PTE" },
+       { 0x03, "VA_LIMIT_VIOLATION" },
+       { 0x04, "UNBOUND_INST_BLOCK" },
+       { 0x05, "PRIV_VIOLATION" },
+       { 0x06, "RO_VIOLATION" },
+       { 0x07, "WO_VIOLATION" },
+       { 0x08, "PITCH_MASK_VIOLATION" },
+       { 0x09, "WORK_CREATION" },
+       { 0x0a, "UNSUPPORTED_APERTURE" },
+       { 0x0b, "COMPRESSION_FAILURE" },
+       { 0x0c, "UNSUPPORTED_KIND" },
+       { 0x0d, "REGION_VIOLATION" },
+       { 0x0e, "BOTH_PTES_VALID" },
+       { 0x0f, "INFO_TYPE_POISONED" },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
+       { 0x00, "VIP" },
+       { 0x01, "CE0" },
+       { 0x02, "CE1" },
+       { 0x03, "DNISO" },
+       { 0x04, "FE" },
+       { 0x05, "FECS" },
+       { 0x06, "HOST" },
+       { 0x07, "HOST_CPU" },
+       { 0x08, "HOST_CPU_NB" },
+       { 0x09, "ISO" },
+       { 0x0a, "MMU" },
+       { 0x0b, "MSPDEC" },
+       { 0x0c, "MSPPP" },
+       { 0x0d, "MSVLD" },
+       { 0x0e, "NISO" },
+       { 0x0f, "P2P" },
+       { 0x10, "PD" },
+       { 0x11, "PERF" },
+       { 0x12, "PMU" },
+       { 0x13, "RASTERTWOD" },
+       { 0x14, "SCC" },
+       { 0x15, "SCC_NB" },
+       { 0x16, "SEC" },
+       { 0x17, "SSYNC" },
+       { 0x18, "GR_COPY" },
+       { 0x19, "CE2" },
+       { 0x1a, "XV" },
+       { 0x1b, "MMU_NB" },
+       { 0x1c, "MSENC" },
+       { 0x1d, "DFALCON" },
+       { 0x1e, "SKED" },
+       { 0x1f, "AFALCON" },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
+       { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
+       { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
+       { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
+       { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
+       { 0x0c, "RAST" },
+       { 0x0d, "GCC" },
+       { 0x0e, "GPCCS" },
+       { 0x0f, "PROP_0" },
+       { 0x10, "PROP_1" },
+       { 0x11, "PROP_2" },
+       { 0x12, "PROP_3" },
+       { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
+       { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
+       { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
+       { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
+       { 0x1f, "GPM" },
+       { 0x20, "LTP_UTLB_0" },
+       { 0x21, "LTP_UTLB_1" },
+       { 0x22, "LTP_UTLB_2" },
+       { 0x23, "LTP_UTLB_3" },
+       { 0x24, "GPC_RGG_UTLB" },
        {}
 };
 
-static const struct nouveau_bitfield nve0_fifo_subfifo_intr[] = {
-       { 0x00200000, "ILLEGAL_MTHD" },
-       { 0x00800000, "EMPTY_SUBC" },
+static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
+       { 0x00000001, "MEMREQ" },
+       { 0x00000002, "MEMACK_TIMEOUT" },
+       { 0x00000004, "MEMACK_EXTRA" },
+       { 0x00000008, "MEMDAT_TIMEOUT" },
+       { 0x00000010, "MEMDAT_EXTRA" },
+       { 0x00000020, "MEMFLUSH" },
+       { 0x00000040, "MEMOP" },
+       { 0x00000080, "LBCONNECT" },
+       { 0x00000100, "LBREQ" },
+       { 0x00000200, "LBACK_TIMEOUT" },
+       { 0x00000400, "LBACK_EXTRA" },
+       { 0x00000800, "LBDAT_TIMEOUT" },
+       { 0x00001000, "LBDAT_EXTRA" },
+       { 0x00002000, "GPFIFO" },
+       { 0x00004000, "GPPTR" },
+       { 0x00008000, "GPENTRY" },
+       { 0x00010000, "GPCRC" },
+       { 0x00020000, "PBPTR" },
+       { 0x00040000, "PBENTRY" },
+       { 0x00080000, "PBCRC" },
+       { 0x00100000, "XBARCONNECT" },
+       { 0x00200000, "METHOD" },
+       { 0x00400000, "METHODCRC" },
+       { 0x00800000, "DEVICE" },
+       { 0x02000000, "SEMAPHORE" },
+       { 0x04000000, "ACQUIRE" },
+       { 0x08000000, "PRI" },
+       { 0x20000000, "NO_CTXSW_SEG" },
+       { 0x40000000, "PBSEG" },
+       { 0x80000000, "SIGNATURE" },
        {}
 };
 
 static void
-nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x00254c);
+       u32 code = intr & 0x000000ff;
+       nv_error(priv, "SCHED_ERROR [");
+       nouveau_enum_print(nve0_fifo_sched_reason, code);
+       pr_cont("]\n");
+}
+
+static void
+nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00256c);
+       nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
+       nv_wr32(priv, 0x00256c, stat);
+}
+
+static void
+nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00259c);
+       nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
+}
+
+static void
+nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
 {
        u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10));
        u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10));
        u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
        u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
        u32 client = (stat & 0x00001f00) >> 8;
-       const struct nouveau_enum *en;
-       struct nouveau_engine *engine;
+       struct nouveau_engine *engine = NULL;
        struct nouveau_object *engctx = NULL;
+       const struct nouveau_enum *en;
+       const char *name = "unknown";
 
        nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
                       "write" : "read", (u64)vahi << 32 | valo);
        nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
        pr_cont("] from ");
-       en = nouveau_enum_print(nve0_fifo_fault_unit, unit);
+       en = nouveau_enum_print(nve0_fifo_fault_engine, unit);
        if (stat & 0x00000040) {
                pr_cont("/");
                nouveau_enum_print(nve0_fifo_fault_hubclient, client);
@@ -432,14 +569,22 @@ nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
        }
 
        if (en && en->data2) {
-               engine = nouveau_engine(priv, en->data2);
-               if (engine)
-                       engctx = nouveau_engctx_get(engine, inst);
-
+               if (en->data2 == NVDEV_SUBDEV_BAR) {
+                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+                       name = "BAR1";
+               } else
+               if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
+                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+                       name = "BAR3";
+               } else {
+                       engine = nouveau_engine(priv, en->data2);
+                       if (engine) {
+                               engctx = nouveau_engctx_get(engine, inst);
+                               name   = nouveau_client_name(engctx);
+                       }
+               }
        }
-
-       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
-                       nouveau_client_name(engctx));
+       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
 
        nouveau_engctx_put(engctx);
 }
@@ -471,7 +616,7 @@ out:
 }
 
 static void
-nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
 {
        u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
        u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -487,11 +632,11 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
        }
 
        if (show) {
-               nv_error(priv, "SUBFIFO%d:", unit);
-               nouveau_bitfield_print(nve0_fifo_subfifo_intr, show);
+               nv_error(priv, "PBDMA%d:", unit);
+               nouveau_bitfield_print(nve0_fifo_pbdma_intr, show);
                pr_cont("\n");
                nv_error(priv,
-                        "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
+                        "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
                         unit, chid,
                         nouveau_client_name_for_fifo_chid(&priv->base, chid),
                         subc, mthd, data);
@@ -508,19 +653,56 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        u32 mask = nv_rd32(priv, 0x002140);
        u32 stat = nv_rd32(priv, 0x002100) & mask;
 
+       if (stat & 0x00000001) {
+               u32 stat = nv_rd32(priv, 0x00252c);
+               nv_error(priv, "BIND_ERROR 0x%08x\n", stat);
+               nv_wr32(priv, 0x002100, 0x00000001);
+               stat &= ~0x00000001;
+       }
+
+       if (stat & 0x00000010) {
+               nv_error(priv, "PIO_ERROR\n");
+               nv_wr32(priv, 0x002100, 0x00000010);
+               stat &= ~0x00000010;
+       }
+
        if (stat & 0x00000100) {
-               nv_warn(priv, "unknown status 0x00000100\n");
+               nve0_fifo_intr_sched(priv);
                nv_wr32(priv, 0x002100, 0x00000100);
                stat &= ~0x00000100;
        }
 
+       if (stat & 0x00010000) {
+               nve0_fifo_intr_chsw(priv);
+               nv_wr32(priv, 0x002100, 0x00010000);
+               stat &= ~0x00010000;
+       }
+
+       if (stat & 0x00800000) {
+               nv_error(priv, "FB_FLUSH_TIMEOUT\n");
+               nv_wr32(priv, 0x002100, 0x00800000);
+               stat &= ~0x00800000;
+       }
+
+       if (stat & 0x01000000) {
+               nv_error(priv, "LB_ERROR\n");
+               nv_wr32(priv, 0x002100, 0x01000000);
+               stat &= ~0x01000000;
+       }
+
+       if (stat & 0x08000000) {
+               nve0_fifo_intr_dropped_fault(priv);
+               nv_wr32(priv, 0x002100, 0x08000000);
+               stat &= ~0x08000000;
+       }
+
        if (stat & 0x10000000) {
                u32 units = nv_rd32(priv, 0x00259c);
                u32 u = units;
 
                while (u) {
                        int i = ffs(u) - 1;
-                       nve0_fifo_isr_vm_fault(priv, i);
+                       nve0_fifo_intr_fault(priv, i);
                        u &= ~(1 << i);
                }
 
@@ -529,22 +711,28 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x20000000) {
-               u32 units = nv_rd32(priv, 0x0025a0);
-               u32 u = units;
+               u32 mask = nv_rd32(priv, 0x0025a0);
+               u32 temp = mask;
 
-               while (u) {
-                       int i = ffs(u) - 1;
-                       nve0_fifo_isr_subfifo_intr(priv, i);
-                       u &= ~(1 << i);
+               while (temp) {
+                       u32 unit = ffs(temp) - 1;
+                       nve0_fifo_intr_pbdma(priv, unit);
+                       temp &= ~(1 << unit);
                }
 
-               nv_wr32(priv, 0x0025a0, units);
+               nv_wr32(priv, 0x0025a0, mask);
                stat &= ~0x20000000;
        }
 
        if (stat & 0x40000000) {
-               nv_warn(priv, "unknown status 0x40000000\n");
-               nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+               u32 mask = nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+
+               while (mask) {
+                       u32 engn = ffs(mask) - 1;
+                       /* runlist event, not currently used */
+                       mask &= ~(1 << engn);
+               }
+
                stat &= ~0x40000000;
        }
 
@@ -575,53 +763,52 @@ nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
        nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
 }
 
-static int
-nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-              struct nouveau_oclass *oclass, void *data, u32 size,
-              struct nouveau_object **pobject)
+int
+nve0_fifo_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nve0_fifo_priv *priv;
-       int ret, i;
+       struct nve0_fifo_priv *priv = (void *)object;
+       int ret;
 
-       ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv);
-       *pobject = nv_object(priv);
+       ret = nouveau_fifo_fini(&priv->base, suspend);
        if (ret)
                return ret;
 
-       for (i = 0; i < FIFO_ENGINE_NR; i++) {
-               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-                                        0, &priv->engine[i].playlist[0]);
-               if (ret)
-                       return ret;
+       /* allow mmu fault interrupts, even when we're not using fifo */
+       nv_mask(priv, 0x002140, 0x10000000, 0x10000000);
+       return 0;
+}
 
-               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-                                        0, &priv->engine[i].playlist[1]);
-               if (ret)
-                       return ret;
-       }
+int
+nve0_fifo_init(struct nouveau_object *object)
+{
+       struct nve0_fifo_priv *priv = (void *)object;
+       int ret, i;
 
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
-                                NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+       ret = nouveau_fifo_init(&priv->base);
        if (ret)
                return ret;
 
-       ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
-                               &priv->user.bar);
-       if (ret)
-               return ret;
+       /* enable all available PBDMA units */
+       nv_wr32(priv, 0x000204, 0xffffffff);
+       priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
+       nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr);
 
-       priv->base.uevent->enable = nve0_fifo_uevent_enable;
-       priv->base.uevent->disable = nve0_fifo_uevent_disable;
-       priv->base.uevent->priv = priv;
+       /* PBDMA[n] */
+       for (i = 0; i < priv->spoon_nr; i++) {
+               nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
+               nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
+               nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+       }
 
-       nv_subdev(priv)->unit = 0x00000100;
-       nv_subdev(priv)->intr = nve0_fifo_intr;
-       nv_engine(priv)->cclass = &nve0_fifo_cclass;
-       nv_engine(priv)->sclass = nve0_fifo_sclass;
+       nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+
+       nv_wr32(priv, 0x002a00, 0xffffffff);
+       nv_wr32(priv, 0x002100, 0xffffffff);
+       nv_wr32(priv, 0x002140, 0x3fffffff);
        return 0;
 }
 
-static void
+void
 nve0_fifo_dtor(struct nouveau_object *object)
 {
        struct nve0_fifo_priv *priv = (void *)object;
@@ -631,50 +818,69 @@ nve0_fifo_dtor(struct nouveau_object *object)
        nouveau_gpuobj_ref(NULL, &priv->user.mem);
 
        for (i = 0; i < FIFO_ENGINE_NR; i++) {
-               nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]);
-               nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]);
+               nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[1]);
+               nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[0]);
        }
 
        nouveau_fifo_destroy(&priv->base);
 }
 
-static int
-nve0_fifo_init(struct nouveau_object *object)
+int
+nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
 {
-       struct nve0_fifo_priv *priv = (void *)object;
+       struct nve0_fifo_impl *impl = (void *)oclass;
+       struct nve0_fifo_priv *priv;
        int ret, i;
 
-       ret = nouveau_fifo_init(&priv->base);
+       ret = nouveau_fifo_create(parent, engine, oclass, 0,
+                                 impl->channels - 1, &priv);
+       *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       /* enable all available PSUBFIFOs */
-       nv_wr32(priv, 0x000204, 0xffffffff);
-       priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
-       nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr);
+       for (i = 0; i < FIFO_ENGINE_NR; i++) {
+               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+                                        0, &priv->engine[i].runlist[0]);
+               if (ret)
+                       return ret;
 
-       /* PSUBFIFO[n] */
-       for (i = 0; i < priv->spoon_nr; i++) {
-               nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
-               nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
-               nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+                                        0, &priv->engine[i].runlist[1]);
+               if (ret)
+                       return ret;
        }
 
-       nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
+                                NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+       if (ret)
+               return ret;
 
-       nv_wr32(priv, 0x002a00, 0xffffffff);
-       nv_wr32(priv, 0x002100, 0xffffffff);
-       nv_wr32(priv, 0x002140, 0x3fffffff);
+       ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
+                               &priv->user.bar);
+       if (ret)
+               return ret;
+
+       priv->base.uevent->enable = nve0_fifo_uevent_enable;
+       priv->base.uevent->disable = nve0_fifo_uevent_disable;
+       priv->base.uevent->priv = priv;
+
+       nv_subdev(priv)->unit = 0x00000100;
+       nv_subdev(priv)->intr = nve0_fifo_intr;
+       nv_engine(priv)->cclass = &nve0_fifo_cclass;
+       nv_engine(priv)->sclass = nve0_fifo_sclass;
        return 0;
 }
 
 struct nouveau_oclass *
-nve0_fifo_oclass = &(struct nouveau_oclass) {
-       .handle = NV_ENGINE(FIFO, 0xe0),
-       .ofuncs = &(struct nouveau_ofuncs) {
+nve0_fifo_oclass = &(struct nve0_fifo_impl) {
+       .base.handle = NV_ENGINE(FIFO, 0xe0),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nve0_fifo_ctor,
                .dtor = nve0_fifo_dtor,
                .init = nve0_fifo_init,
-               .fini = _nouveau_fifo_fini,
+               .fini = nve0_fifo_fini,
        },
-};
+       .channels = 4096,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h
new file mode 100644 (file)
index 0000000..014344e
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __NVKM_FIFO_NVE0_H__
+#define __NVKM_FIFO_NVE0_H__
+
+#include <engine/fifo.h>
+
+int  nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *,
+                   struct nouveau_oclass *, void *, u32,
+                   struct nouveau_object **);
+void nve0_fifo_dtor(struct nouveau_object *);
+int  nve0_fifo_init(struct nouveau_object *);
+
+struct nve0_fifo_impl {
+       struct nouveau_oclass base;
+       u32 channels;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
new file mode 100644 (file)
index 0000000..a86bd33
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+static struct nvc0_graph_init
+nv108_grctx_init_icmd[] = {
+       { 0x001000,   1, 0x01, 0x00000004 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x0000a9,   1, 0x01, 0x0000ffff },
+       { 0x000038,   1, 0x01, 0x0fac6881 },
+       { 0x00003d,   1, 0x01, 0x00000001 },
+       { 0x0000e8,   8, 0x01, 0x00000400 },
+       { 0x000078,   8, 0x01, 0x00000300 },
+       { 0x000050,   1, 0x01, 0x00000011 },
+       { 0x000058,   8, 0x01, 0x00000008 },
+       { 0x000208,   8, 0x01, 0x00000001 },
+       { 0x000081,   1, 0x01, 0x00000001 },
+       { 0x000085,   1, 0x01, 0x00000004 },
+       { 0x000088,   1, 0x01, 0x00000400 },
+       { 0x000090,   1, 0x01, 0x00000300 },
+       { 0x000098,   1, 0x01, 0x00001001 },
+       { 0x0000e3,   1, 0x01, 0x00000001 },
+       { 0x0000da,   1, 0x01, 0x00000001 },
+       { 0x0000f8,   1, 0x01, 0x00000003 },
+       { 0x0000fa,   1, 0x01, 0x00000001 },
+       { 0x00009f,   4, 0x01, 0x0000ffff },
+       { 0x0000b1,   1, 0x01, 0x00000001 },
+       { 0x0000ad,   1, 0x01, 0x0000013e },
+       { 0x0000e1,   1, 0x01, 0x00000010 },
+       { 0x000290,  16, 0x01, 0x00000000 },
+       { 0x0003b0,  16, 0x01, 0x00000000 },
+       { 0x0002a0,  16, 0x01, 0x00000000 },
+       { 0x000420,  16, 0x01, 0x00000000 },
+       { 0x0002b0,  16, 0x01, 0x00000000 },
+       { 0x000430,  16, 0x01, 0x00000000 },
+       { 0x0002c0,  16, 0x01, 0x00000000 },
+       { 0x0004d0,  16, 0x01, 0x00000000 },
+       { 0x000720,  16, 0x01, 0x00000000 },
+       { 0x0008c0,  16, 0x01, 0x00000000 },
+       { 0x000890,  16, 0x01, 0x00000000 },
+       { 0x0008e0,  16, 0x01, 0x00000000 },
+       { 0x0008a0,  16, 0x01, 0x00000000 },
+       { 0x0008f0,  16, 0x01, 0x00000000 },
+       { 0x00094c,   1, 0x01, 0x000000ff },
+       { 0x00094d,   1, 0x01, 0xffffffff },
+       { 0x00094e,   1, 0x01, 0x00000002 },
+       { 0x0002ec,   1, 0x01, 0x00000001 },
+       { 0x0002f2,   2, 0x01, 0x00000001 },
+       { 0x0002f5,   1, 0x01, 0x00000001 },
+       { 0x0002f7,   1, 0x01, 0x00000001 },
+       { 0x000303,   1, 0x01, 0x00000001 },
+       { 0x0002e6,   1, 0x01, 0x00000001 },
+       { 0x000466,   1, 0x01, 0x00000052 },
+       { 0x000301,   1, 0x01, 0x3f800000 },
+       { 0x000304,   1, 0x01, 0x30201000 },
+       { 0x000305,   1, 0x01, 0x70605040 },
+       { 0x000306,   1, 0x01, 0xb8a89888 },
+       { 0x000307,   1, 0x01, 0xf8e8d8c8 },
+       { 0x00030a,   1, 0x01, 0x00ffff00 },
+       { 0x00030b,   1, 0x01, 0x0000001a },
+       { 0x00030c,   1, 0x01, 0x00000001 },
+       { 0x000318,   1, 0x01, 0x00000001 },
+       { 0x000340,   1, 0x01, 0x00000000 },
+       { 0x000375,   1, 0x01, 0x00000001 },
+       { 0x00037d,   1, 0x01, 0x00000006 },
+       { 0x0003a0,   1, 0x01, 0x00000002 },
+       { 0x0003aa,   1, 0x01, 0x00000001 },
+       { 0x0003a9,   1, 0x01, 0x00000001 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000383,   1, 0x01, 0x00000011 },
+       { 0x000360,   1, 0x01, 0x00000040 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x00037a,   1, 0x01, 0x00000012 },
+       { 0x000619,   1, 0x01, 0x00000003 },
+       { 0x000811,   1, 0x01, 0x00000003 },
+       { 0x000812,   1, 0x01, 0x00000004 },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000815,   1, 0x01, 0x0000000b },
+       { 0x000800,   6, 0x01, 0x00000001 },
+       { 0x000632,   1, 0x01, 0x00000001 },
+       { 0x000633,   1, 0x01, 0x00000002 },
+       { 0x000634,   1, 0x01, 0x00000003 },
+       { 0x000635,   1, 0x01, 0x00000004 },
+       { 0x000654,   1, 0x01, 0x3f800000 },
+       { 0x000657,   1, 0x01, 0x3f800000 },
+       { 0x000655,   2, 0x01, 0x3f800000 },
+       { 0x0006cd,   1, 0x01, 0x3f800000 },
+       { 0x0007f5,   1, 0x01, 0x3f800000 },
+       { 0x0007dc,   1, 0x01, 0x39291909 },
+       { 0x0007dd,   1, 0x01, 0x79695949 },
+       { 0x0007de,   1, 0x01, 0xb9a99989 },
+       { 0x0007df,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007e8,   1, 0x01, 0x00003210 },
+       { 0x0007e9,   1, 0x01, 0x00007654 },
+       { 0x0007ea,   1, 0x01, 0x00000098 },
+       { 0x0007ec,   1, 0x01, 0x39291909 },
+       { 0x0007ed,   1, 0x01, 0x79695949 },
+       { 0x0007ee,   1, 0x01, 0xb9a99989 },
+       { 0x0007ef,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007f0,   1, 0x01, 0x00003210 },
+       { 0x0007f1,   1, 0x01, 0x00007654 },
+       { 0x0007f2,   1, 0x01, 0x00000098 },
+       { 0x0005a5,   1, 0x01, 0x00000001 },
+       { 0x000980, 128, 0x01, 0x00000000 },
+       { 0x000468,   1, 0x01, 0x00000004 },
+       { 0x00046c,   1, 0x01, 0x00000001 },
+       { 0x000470,  96, 0x01, 0x00000000 },
+       { 0x000510,  16, 0x01, 0x3f800000 },
+       { 0x000520,   1, 0x01, 0x000002b6 },
+       { 0x000529,   1, 0x01, 0x00000001 },
+       { 0x000530,  16, 0x01, 0xffff0000 },
+       { 0x000585,   1, 0x01, 0x0000003f },
+       { 0x000576,   1, 0x01, 0x00000003 },
+       { 0x00057b,   1, 0x01, 0x00000059 },
+       { 0x000586,   1, 0x01, 0x00000040 },
+       { 0x000582,   2, 0x01, 0x00000080 },
+       { 0x0005c2,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
+       { 0x00063a,   1, 0x01, 0x00000002 },
+       { 0x00063b,   2, 0x01, 0x00000001 },
+       { 0x00063d,   1, 0x01, 0x00000002 },
+       { 0x00063e,   1, 0x01, 0x00000001 },
+       { 0x0008b8,   8, 0x01, 0x00000001 },
+       { 0x000900,   8, 0x01, 0x00000001 },
+       { 0x000908,   8, 0x01, 0x00000002 },
+       { 0x000910,  16, 0x01, 0x00000001 },
+       { 0x000920,   8, 0x01, 0x00000002 },
+       { 0x000928,   8, 0x01, 0x00000001 },
+       { 0x000662,   1, 0x01, 0x00000001 },
+       { 0x000648,   9, 0x01, 0x00000001 },
+       { 0x000658,   1, 0x01, 0x0000000f },
+       { 0x0007ff,   1, 0x01, 0x0000000a },
+       { 0x00066a,   1, 0x01, 0x40000000 },
+       { 0x00066b,   1, 0x01, 0x10000000 },
+       { 0x00066c,   2, 0x01, 0xffff0000 },
+       { 0x0007af,   2, 0x01, 0x00000008 },
+       { 0x0007f6,   1, 0x01, 0x00000001 },
+       { 0x00080b,   1, 0x01, 0x00000002 },
+       { 0x0006b2,   1, 0x01, 0x00000055 },
+       { 0x0007ad,   1, 0x01, 0x00000003 },
+       { 0x000937,   1, 0x01, 0x00000001 },
+       { 0x000971,   1, 0x01, 0x00000008 },
+       { 0x000972,   1, 0x01, 0x00000040 },
+       { 0x000973,   1, 0x01, 0x0000012c },
+       { 0x00097c,   1, 0x01, 0x00000040 },
+       { 0x000979,   1, 0x01, 0x00000003 },
+       { 0x000975,   1, 0x01, 0x00000020 },
+       { 0x000976,   1, 0x01, 0x00000001 },
+       { 0x000977,   1, 0x01, 0x00000020 },
+       { 0x000978,   1, 0x01, 0x00000001 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x00095e,   1, 0x01, 0x20164010 },
+       { 0x00095f,   1, 0x01, 0x00000020 },
+       { 0x000a0d,   1, 0x01, 0x00000006 },
+       { 0x00097d,   1, 0x01, 0x00000020 },
+       { 0x000683,   1, 0x01, 0x00000006 },
+       { 0x000685,   1, 0x01, 0x003fffff },
+       { 0x000687,   1, 0x01, 0x003fffff },
+       { 0x0006a0,   1, 0x01, 0x00000005 },
+       { 0x000840,   1, 0x01, 0x00400008 },
+       { 0x000841,   1, 0x01, 0x08000080 },
+       { 0x000842,   1, 0x01, 0x00400008 },
+       { 0x000843,   1, 0x01, 0x08000080 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ab,   1, 0x01, 0x00000002 },
+       { 0x0006ac,   1, 0x01, 0x00000080 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x0006bb,   1, 0x01, 0x000000cf },
+       { 0x0006ce,   1, 0x01, 0x2a712488 },
+       { 0x000739,   1, 0x01, 0x4085c000 },
+       { 0x00073a,   1, 0x01, 0x00000080 },
+       { 0x000786,   1, 0x01, 0x80000100 },
+       { 0x00073c,   1, 0x01, 0x00010100 },
+       { 0x00073d,   1, 0x01, 0x02800000 },
+       { 0x000787,   1, 0x01, 0x000000cf },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x000836,   1, 0x01, 0x00000001 },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x000833,   1, 0x01, 0x04444480 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c1b0,   8, 0x01, 0x0000000f },
+       { 0x00c1b8,   1, 0x01, 0x0fac6881 },
+       { 0x00c1b9,   1, 0x01, 0x00fac688 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000002 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000008 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000001 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_a197[] = {
+       { 0x000800,   1, 0x04, 0x00000000 },
+       { 0x000840,   1, 0x04, 0x00000000 },
+       { 0x000880,   1, 0x04, 0x00000000 },
+       { 0x0008c0,   1, 0x04, 0x00000000 },
+       { 0x000900,   1, 0x04, 0x00000000 },
+       { 0x000940,   1, 0x04, 0x00000000 },
+       { 0x000980,   1, 0x04, 0x00000000 },
+       { 0x0009c0,   1, 0x04, 0x00000000 },
+       { 0x000804,   1, 0x04, 0x00000000 },
+       { 0x000844,   1, 0x04, 0x00000000 },
+       { 0x000884,   1, 0x04, 0x00000000 },
+       { 0x0008c4,   1, 0x04, 0x00000000 },
+       { 0x000904,   1, 0x04, 0x00000000 },
+       { 0x000944,   1, 0x04, 0x00000000 },
+       { 0x000984,   1, 0x04, 0x00000000 },
+       { 0x0009c4,   1, 0x04, 0x00000000 },
+       { 0x000808,   1, 0x04, 0x00000400 },
+       { 0x000848,   1, 0x04, 0x00000400 },
+       { 0x000888,   1, 0x04, 0x00000400 },
+       { 0x0008c8,   1, 0x04, 0x00000400 },
+       { 0x000908,   1, 0x04, 0x00000400 },
+       { 0x000948,   1, 0x04, 0x00000400 },
+       { 0x000988,   1, 0x04, 0x00000400 },
+       { 0x0009c8,   1, 0x04, 0x00000400 },
+       { 0x00080c,   1, 0x04, 0x00000300 },
+       { 0x00084c,   1, 0x04, 0x00000300 },
+       { 0x00088c,   1, 0x04, 0x00000300 },
+       { 0x0008cc,   1, 0x04, 0x00000300 },
+       { 0x00090c,   1, 0x04, 0x00000300 },
+       { 0x00094c,   1, 0x04, 0x00000300 },
+       { 0x00098c,   1, 0x04, 0x00000300 },
+       { 0x0009cc,   1, 0x04, 0x00000300 },
+       { 0x000810,   1, 0x04, 0x000000cf },
+       { 0x000850,   1, 0x04, 0x00000000 },
+       { 0x000890,   1, 0x04, 0x00000000 },
+       { 0x0008d0,   1, 0x04, 0x00000000 },
+       { 0x000910,   1, 0x04, 0x00000000 },
+       { 0x000950,   1, 0x04, 0x00000000 },
+       { 0x000990,   1, 0x04, 0x00000000 },
+       { 0x0009d0,   1, 0x04, 0x00000000 },
+       { 0x000814,   1, 0x04, 0x00000040 },
+       { 0x000854,   1, 0x04, 0x00000040 },
+       { 0x000894,   1, 0x04, 0x00000040 },
+       { 0x0008d4,   1, 0x04, 0x00000040 },
+       { 0x000914,   1, 0x04, 0x00000040 },
+       { 0x000954,   1, 0x04, 0x00000040 },
+       { 0x000994,   1, 0x04, 0x00000040 },
+       { 0x0009d4,   1, 0x04, 0x00000040 },
+       { 0x000818,   1, 0x04, 0x00000001 },
+       { 0x000858,   1, 0x04, 0x00000001 },
+       { 0x000898,   1, 0x04, 0x00000001 },
+       { 0x0008d8,   1, 0x04, 0x00000001 },
+       { 0x000918,   1, 0x04, 0x00000001 },
+       { 0x000958,   1, 0x04, 0x00000001 },
+       { 0x000998,   1, 0x04, 0x00000001 },
+       { 0x0009d8,   1, 0x04, 0x00000001 },
+       { 0x00081c,   1, 0x04, 0x00000000 },
+       { 0x00085c,   1, 0x04, 0x00000000 },
+       { 0x00089c,   1, 0x04, 0x00000000 },
+       { 0x0008dc,   1, 0x04, 0x00000000 },
+       { 0x00091c,   1, 0x04, 0x00000000 },
+       { 0x00095c,   1, 0x04, 0x00000000 },
+       { 0x00099c,   1, 0x04, 0x00000000 },
+       { 0x0009dc,   1, 0x04, 0x00000000 },
+       { 0x000820,   1, 0x04, 0x00000000 },
+       { 0x000860,   1, 0x04, 0x00000000 },
+       { 0x0008a0,   1, 0x04, 0x00000000 },
+       { 0x0008e0,   1, 0x04, 0x00000000 },
+       { 0x000920,   1, 0x04, 0x00000000 },
+       { 0x000960,   1, 0x04, 0x00000000 },
+       { 0x0009a0,   1, 0x04, 0x00000000 },
+       { 0x0009e0,   1, 0x04, 0x00000000 },
+       { 0x001c00,   1, 0x04, 0x00000000 },
+       { 0x001c10,   1, 0x04, 0x00000000 },
+       { 0x001c20,   1, 0x04, 0x00000000 },
+       { 0x001c30,   1, 0x04, 0x00000000 },
+       { 0x001c40,   1, 0x04, 0x00000000 },
+       { 0x001c50,   1, 0x04, 0x00000000 },
+       { 0x001c60,   1, 0x04, 0x00000000 },
+       { 0x001c70,   1, 0x04, 0x00000000 },
+       { 0x001c80,   1, 0x04, 0x00000000 },
+       { 0x001c90,   1, 0x04, 0x00000000 },
+       { 0x001ca0,   1, 0x04, 0x00000000 },
+       { 0x001cb0,   1, 0x04, 0x00000000 },
+       { 0x001cc0,   1, 0x04, 0x00000000 },
+       { 0x001cd0,   1, 0x04, 0x00000000 },
+       { 0x001ce0,   1, 0x04, 0x00000000 },
+       { 0x001cf0,   1, 0x04, 0x00000000 },
+       { 0x001c04,   1, 0x04, 0x00000000 },
+       { 0x001c14,   1, 0x04, 0x00000000 },
+       { 0x001c24,   1, 0x04, 0x00000000 },
+       { 0x001c34,   1, 0x04, 0x00000000 },
+       { 0x001c44,   1, 0x04, 0x00000000 },
+       { 0x001c54,   1, 0x04, 0x00000000 },
+       { 0x001c64,   1, 0x04, 0x00000000 },
+       { 0x001c74,   1, 0x04, 0x00000000 },
+       { 0x001c84,   1, 0x04, 0x00000000 },
+       { 0x001c94,   1, 0x04, 0x00000000 },
+       { 0x001ca4,   1, 0x04, 0x00000000 },
+       { 0x001cb4,   1, 0x04, 0x00000000 },
+       { 0x001cc4,   1, 0x04, 0x00000000 },
+       { 0x001cd4,   1, 0x04, 0x00000000 },
+       { 0x001ce4,   1, 0x04, 0x00000000 },
+       { 0x001cf4,   1, 0x04, 0x00000000 },
+       { 0x001c08,   1, 0x04, 0x00000000 },
+       { 0x001c18,   1, 0x04, 0x00000000 },
+       { 0x001c28,   1, 0x04, 0x00000000 },
+       { 0x001c38,   1, 0x04, 0x00000000 },
+       { 0x001c48,   1, 0x04, 0x00000000 },
+       { 0x001c58,   1, 0x04, 0x00000000 },
+       { 0x001c68,   1, 0x04, 0x00000000 },
+       { 0x001c78,   1, 0x04, 0x00000000 },
+       { 0x001c88,   1, 0x04, 0x00000000 },
+       { 0x001c98,   1, 0x04, 0x00000000 },
+       { 0x001ca8,   1, 0x04, 0x00000000 },
+       { 0x001cb8,   1, 0x04, 0x00000000 },
+       { 0x001cc8,   1, 0x04, 0x00000000 },
+       { 0x001cd8,   1, 0x04, 0x00000000 },
+       { 0x001ce8,   1, 0x04, 0x00000000 },
+       { 0x001cf8,   1, 0x04, 0x00000000 },
+       { 0x001c0c,   1, 0x04, 0x00000000 },
+       { 0x001c1c,   1, 0x04, 0x00000000 },
+       { 0x001c2c,   1, 0x04, 0x00000000 },
+       { 0x001c3c,   1, 0x04, 0x00000000 },
+       { 0x001c4c,   1, 0x04, 0x00000000 },
+       { 0x001c5c,   1, 0x04, 0x00000000 },
+       { 0x001c6c,   1, 0x04, 0x00000000 },
+       { 0x001c7c,   1, 0x04, 0x00000000 },
+       { 0x001c8c,   1, 0x04, 0x00000000 },
+       { 0x001c9c,   1, 0x04, 0x00000000 },
+       { 0x001cac,   1, 0x04, 0x00000000 },
+       { 0x001cbc,   1, 0x04, 0x00000000 },
+       { 0x001ccc,   1, 0x04, 0x00000000 },
+       { 0x001cdc,   1, 0x04, 0x00000000 },
+       { 0x001cec,   1, 0x04, 0x00000000 },
+       { 0x001cfc,   2, 0x04, 0x00000000 },
+       { 0x001d10,   1, 0x04, 0x00000000 },
+       { 0x001d20,   1, 0x04, 0x00000000 },
+       { 0x001d30,   1, 0x04, 0x00000000 },
+       { 0x001d40,   1, 0x04, 0x00000000 },
+       { 0x001d50,   1, 0x04, 0x00000000 },
+       { 0x001d60,   1, 0x04, 0x00000000 },
+       { 0x001d70,   1, 0x04, 0x00000000 },
+       { 0x001d80,   1, 0x04, 0x00000000 },
+       { 0x001d90,   1, 0x04, 0x00000000 },
+       { 0x001da0,   1, 0x04, 0x00000000 },
+       { 0x001db0,   1, 0x04, 0x00000000 },
+       { 0x001dc0,   1, 0x04, 0x00000000 },
+       { 0x001dd0,   1, 0x04, 0x00000000 },
+       { 0x001de0,   1, 0x04, 0x00000000 },
+       { 0x001df0,   1, 0x04, 0x00000000 },
+       { 0x001d04,   1, 0x04, 0x00000000 },
+       { 0x001d14,   1, 0x04, 0x00000000 },
+       { 0x001d24,   1, 0x04, 0x00000000 },
+       { 0x001d34,   1, 0x04, 0x00000000 },
+       { 0x001d44,   1, 0x04, 0x00000000 },
+       { 0x001d54,   1, 0x04, 0x00000000 },
+       { 0x001d64,   1, 0x04, 0x00000000 },
+       { 0x001d74,   1, 0x04, 0x00000000 },
+       { 0x001d84,   1, 0x04, 0x00000000 },
+       { 0x001d94,   1, 0x04, 0x00000000 },
+       { 0x001da4,   1, 0x04, 0x00000000 },
+       { 0x001db4,   1, 0x04, 0x00000000 },
+       { 0x001dc4,   1, 0x04, 0x00000000 },
+       { 0x001dd4,   1, 0x04, 0x00000000 },
+       { 0x001de4,   1, 0x04, 0x00000000 },
+       { 0x001df4,   1, 0x04, 0x00000000 },
+       { 0x001d08,   1, 0x04, 0x00000000 },
+       { 0x001d18,   1, 0x04, 0x00000000 },
+       { 0x001d28,   1, 0x04, 0x00000000 },
+       { 0x001d38,   1, 0x04, 0x00000000 },
+       { 0x001d48,   1, 0x04, 0x00000000 },
+       { 0x001d58,   1, 0x04, 0x00000000 },
+       { 0x001d68,   1, 0x04, 0x00000000 },
+       { 0x001d78,   1, 0x04, 0x00000000 },
+       { 0x001d88,   1, 0x04, 0x00000000 },
+       { 0x001d98,   1, 0x04, 0x00000000 },
+       { 0x001da8,   1, 0x04, 0x00000000 },
+       { 0x001db8,   1, 0x04, 0x00000000 },
+       { 0x001dc8,   1, 0x04, 0x00000000 },
+       { 0x001dd8,   1, 0x04, 0x00000000 },
+       { 0x001de8,   1, 0x04, 0x00000000 },
+       { 0x001df8,   1, 0x04, 0x00000000 },
+       { 0x001d0c,   1, 0x04, 0x00000000 },
+       { 0x001d1c,   1, 0x04, 0x00000000 },
+       { 0x001d2c,   1, 0x04, 0x00000000 },
+       { 0x001d3c,   1, 0x04, 0x00000000 },
+       { 0x001d4c,   1, 0x04, 0x00000000 },
+       { 0x001d5c,   1, 0x04, 0x00000000 },
+       { 0x001d6c,   1, 0x04, 0x00000000 },
+       { 0x001d7c,   1, 0x04, 0x00000000 },
+       { 0x001d8c,   1, 0x04, 0x00000000 },
+       { 0x001d9c,   1, 0x04, 0x00000000 },
+       { 0x001dac,   1, 0x04, 0x00000000 },
+       { 0x001dbc,   1, 0x04, 0x00000000 },
+       { 0x001dcc,   1, 0x04, 0x00000000 },
+       { 0x001ddc,   1, 0x04, 0x00000000 },
+       { 0x001dec,   1, 0x04, 0x00000000 },
+       { 0x001dfc,   1, 0x04, 0x00000000 },
+       { 0x001f00,   1, 0x04, 0x00000000 },
+       { 0x001f08,   1, 0x04, 0x00000000 },
+       { 0x001f10,   1, 0x04, 0x00000000 },
+       { 0x001f18,   1, 0x04, 0x00000000 },
+       { 0x001f20,   1, 0x04, 0x00000000 },
+       { 0x001f28,   1, 0x04, 0x00000000 },
+       { 0x001f30,   1, 0x04, 0x00000000 },
+       { 0x001f38,   1, 0x04, 0x00000000 },
+       { 0x001f40,   1, 0x04, 0x00000000 },
+       { 0x001f48,   1, 0x04, 0x00000000 },
+       { 0x001f50,   1, 0x04, 0x00000000 },
+       { 0x001f58,   1, 0x04, 0x00000000 },
+       { 0x001f60,   1, 0x04, 0x00000000 },
+       { 0x001f68,   1, 0x04, 0x00000000 },
+       { 0x001f70,   1, 0x04, 0x00000000 },
+       { 0x001f78,   1, 0x04, 0x00000000 },
+       { 0x001f04,   1, 0x04, 0x00000000 },
+       { 0x001f0c,   1, 0x04, 0x00000000 },
+       { 0x001f14,   1, 0x04, 0x00000000 },
+       { 0x001f1c,   1, 0x04, 0x00000000 },
+       { 0x001f24,   1, 0x04, 0x00000000 },
+       { 0x001f2c,   1, 0x04, 0x00000000 },
+       { 0x001f34,   1, 0x04, 0x00000000 },
+       { 0x001f3c,   1, 0x04, 0x00000000 },
+       { 0x001f44,   1, 0x04, 0x00000000 },
+       { 0x001f4c,   1, 0x04, 0x00000000 },
+       { 0x001f54,   1, 0x04, 0x00000000 },
+       { 0x001f5c,   1, 0x04, 0x00000000 },
+       { 0x001f64,   1, 0x04, 0x00000000 },
+       { 0x001f6c,   1, 0x04, 0x00000000 },
+       { 0x001f74,   1, 0x04, 0x00000000 },
+       { 0x001f7c,   2, 0x04, 0x00000000 },
+       { 0x001f88,   1, 0x04, 0x00000000 },
+       { 0x001f90,   1, 0x04, 0x00000000 },
+       { 0x001f98,   1, 0x04, 0x00000000 },
+       { 0x001fa0,   1, 0x04, 0x00000000 },
+       { 0x001fa8,   1, 0x04, 0x00000000 },
+       { 0x001fb0,   1, 0x04, 0x00000000 },
+       { 0x001fb8,   1, 0x04, 0x00000000 },
+       { 0x001fc0,   1, 0x04, 0x00000000 },
+       { 0x001fc8,   1, 0x04, 0x00000000 },
+       { 0x001fd0,   1, 0x04, 0x00000000 },
+       { 0x001fd8,   1, 0x04, 0x00000000 },
+       { 0x001fe0,   1, 0x04, 0x00000000 },
+       { 0x001fe8,   1, 0x04, 0x00000000 },
+       { 0x001ff0,   1, 0x04, 0x00000000 },
+       { 0x001ff8,   1, 0x04, 0x00000000 },
+       { 0x001f84,   1, 0x04, 0x00000000 },
+       { 0x001f8c,   1, 0x04, 0x00000000 },
+       { 0x001f94,   1, 0x04, 0x00000000 },
+       { 0x001f9c,   1, 0x04, 0x00000000 },
+       { 0x001fa4,   1, 0x04, 0x00000000 },
+       { 0x001fac,   1, 0x04, 0x00000000 },
+       { 0x001fb4,   1, 0x04, 0x00000000 },
+       { 0x001fbc,   1, 0x04, 0x00000000 },
+       { 0x001fc4,   1, 0x04, 0x00000000 },
+       { 0x001fcc,   1, 0x04, 0x00000000 },
+       { 0x001fd4,   1, 0x04, 0x00000000 },
+       { 0x001fdc,   1, 0x04, 0x00000000 },
+       { 0x001fe4,   1, 0x04, 0x00000000 },
+       { 0x001fec,   1, 0x04, 0x00000000 },
+       { 0x001ff4,   1, 0x04, 0x00000000 },
+       { 0x001ffc,   2, 0x04, 0x00000000 },
+       { 0x002040,   1, 0x04, 0x00000011 },
+       { 0x002080,   1, 0x04, 0x00000020 },
+       { 0x0020c0,   1, 0x04, 0x00000030 },
+       { 0x002100,   1, 0x04, 0x00000040 },
+       { 0x002140,   1, 0x04, 0x00000051 },
+       { 0x00200c,   1, 0x04, 0x00000001 },
+       { 0x00204c,   1, 0x04, 0x00000001 },
+       { 0x00208c,   1, 0x04, 0x00000001 },
+       { 0x0020cc,   1, 0x04, 0x00000001 },
+       { 0x00210c,   1, 0x04, 0x00000001 },
+       { 0x00214c,   1, 0x04, 0x00000001 },
+       { 0x002010,   1, 0x04, 0x00000000 },
+       { 0x002050,   1, 0x04, 0x00000000 },
+       { 0x002090,   1, 0x04, 0x00000001 },
+       { 0x0020d0,   1, 0x04, 0x00000002 },
+       { 0x002110,   1, 0x04, 0x00000003 },
+       { 0x002150,   1, 0x04, 0x00000004 },
+       { 0x000380,   1, 0x04, 0x00000000 },
+       { 0x0003a0,   1, 0x04, 0x00000000 },
+       { 0x0003c0,   1, 0x04, 0x00000000 },
+       { 0x0003e0,   1, 0x04, 0x00000000 },
+       { 0x000384,   1, 0x04, 0x00000000 },
+       { 0x0003a4,   1, 0x04, 0x00000000 },
+       { 0x0003c4,   1, 0x04, 0x00000000 },
+       { 0x0003e4,   1, 0x04, 0x00000000 },
+       { 0x000388,   1, 0x04, 0x00000000 },
+       { 0x0003a8,   1, 0x04, 0x00000000 },
+       { 0x0003c8,   1, 0x04, 0x00000000 },
+       { 0x0003e8,   1, 0x04, 0x00000000 },
+       { 0x00038c,   1, 0x04, 0x00000000 },
+       { 0x0003ac,   1, 0x04, 0x00000000 },
+       { 0x0003cc,   1, 0x04, 0x00000000 },
+       { 0x0003ec,   1, 0x04, 0x00000000 },
+       { 0x000700,   1, 0x04, 0x00000000 },
+       { 0x000710,   1, 0x04, 0x00000000 },
+       { 0x000720,   1, 0x04, 0x00000000 },
+       { 0x000730,   1, 0x04, 0x00000000 },
+       { 0x000704,   1, 0x04, 0x00000000 },
+       { 0x000714,   1, 0x04, 0x00000000 },
+       { 0x000724,   1, 0x04, 0x00000000 },
+       { 0x000734,   1, 0x04, 0x00000000 },
+       { 0x000708,   1, 0x04, 0x00000000 },
+       { 0x000718,   1, 0x04, 0x00000000 },
+       { 0x000728,   1, 0x04, 0x00000000 },
+       { 0x000738,   1, 0x04, 0x00000000 },
+       { 0x002800, 128, 0x04, 0x00000000 },
+       { 0x000a00,   1, 0x04, 0x00000000 },
+       { 0x000a20,   1, 0x04, 0x00000000 },
+       { 0x000a40,   1, 0x04, 0x00000000 },
+       { 0x000a60,   1, 0x04, 0x00000000 },
+       { 0x000a80,   1, 0x04, 0x00000000 },
+       { 0x000aa0,   1, 0x04, 0x00000000 },
+       { 0x000ac0,   1, 0x04, 0x00000000 },
+       { 0x000ae0,   1, 0x04, 0x00000000 },
+       { 0x000b00,   1, 0x04, 0x00000000 },
+       { 0x000b20,   1, 0x04, 0x00000000 },
+       { 0x000b40,   1, 0x04, 0x00000000 },
+       { 0x000b60,   1, 0x04, 0x00000000 },
+       { 0x000b80,   1, 0x04, 0x00000000 },
+       { 0x000ba0,   1, 0x04, 0x00000000 },
+       { 0x000bc0,   1, 0x04, 0x00000000 },
+       { 0x000be0,   1, 0x04, 0x00000000 },
+       { 0x000a04,   1, 0x04, 0x00000000 },
+       { 0x000a24,   1, 0x04, 0x00000000 },
+       { 0x000a44,   1, 0x04, 0x00000000 },
+       { 0x000a64,   1, 0x04, 0x00000000 },
+       { 0x000a84,   1, 0x04, 0x00000000 },
+       { 0x000aa4,   1, 0x04, 0x00000000 },
+       { 0x000ac4,   1, 0x04, 0x00000000 },
+       { 0x000ae4,   1, 0x04, 0x00000000 },
+       { 0x000b04,   1, 0x04, 0x00000000 },
+       { 0x000b24,   1, 0x04, 0x00000000 },
+       { 0x000b44,   1, 0x04, 0x00000000 },
+       { 0x000b64,   1, 0x04, 0x00000000 },
+       { 0x000b84,   1, 0x04, 0x00000000 },
+       { 0x000ba4,   1, 0x04, 0x00000000 },
+       { 0x000bc4,   1, 0x04, 0x00000000 },
+       { 0x000be4,   1, 0x04, 0x00000000 },
+       { 0x000a08,   1, 0x04, 0x00000000 },
+       { 0x000a28,   1, 0x04, 0x00000000 },
+       { 0x000a48,   1, 0x04, 0x00000000 },
+       { 0x000a68,   1, 0x04, 0x00000000 },
+       { 0x000a88,   1, 0x04, 0x00000000 },
+       { 0x000aa8,   1, 0x04, 0x00000000 },
+       { 0x000ac8,   1, 0x04, 0x00000000 },
+       { 0x000ae8,   1, 0x04, 0x00000000 },
+       { 0x000b08,   1, 0x04, 0x00000000 },
+       { 0x000b28,   1, 0x04, 0x00000000 },
+       { 0x000b48,   1, 0x04, 0x00000000 },
+       { 0x000b68,   1, 0x04, 0x00000000 },
+       { 0x000b88,   1, 0x04, 0x00000000 },
+       { 0x000ba8,   1, 0x04, 0x00000000 },
+       { 0x000bc8,   1, 0x04, 0x00000000 },
+       { 0x000be8,   1, 0x04, 0x00000000 },
+       { 0x000a0c,   1, 0x04, 0x00000000 },
+       { 0x000a2c,   1, 0x04, 0x00000000 },
+       { 0x000a4c,   1, 0x04, 0x00000000 },
+       { 0x000a6c,   1, 0x04, 0x00000000 },
+       { 0x000a8c,   1, 0x04, 0x00000000 },
+       { 0x000aac,   1, 0x04, 0x00000000 },
+       { 0x000acc,   1, 0x04, 0x00000000 },
+       { 0x000aec,   1, 0x04, 0x00000000 },
+       { 0x000b0c,   1, 0x04, 0x00000000 },
+       { 0x000b2c,   1, 0x04, 0x00000000 },
+       { 0x000b4c,   1, 0x04, 0x00000000 },
+       { 0x000b6c,   1, 0x04, 0x00000000 },
+       { 0x000b8c,   1, 0x04, 0x00000000 },
+       { 0x000bac,   1, 0x04, 0x00000000 },
+       { 0x000bcc,   1, 0x04, 0x00000000 },
+       { 0x000bec,   1, 0x04, 0x00000000 },
+       { 0x000a10,   1, 0x04, 0x00000000 },
+       { 0x000a30,   1, 0x04, 0x00000000 },
+       { 0x000a50,   1, 0x04, 0x00000000 },
+       { 0x000a70,   1, 0x04, 0x00000000 },
+       { 0x000a90,   1, 0x04, 0x00000000 },
+       { 0x000ab0,   1, 0x04, 0x00000000 },
+       { 0x000ad0,   1, 0x04, 0x00000000 },
+       { 0x000af0,   1, 0x04, 0x00000000 },
+       { 0x000b10,   1, 0x04, 0x00000000 },
+       { 0x000b30,   1, 0x04, 0x00000000 },
+       { 0x000b50,   1, 0x04, 0x00000000 },
+       { 0x000b70,   1, 0x04, 0x00000000 },
+       { 0x000b90,   1, 0x04, 0x00000000 },
+       { 0x000bb0,   1, 0x04, 0x00000000 },
+       { 0x000bd0,   1, 0x04, 0x00000000 },
+       { 0x000bf0,   1, 0x04, 0x00000000 },
+       { 0x000a14,   1, 0x04, 0x00000000 },
+       { 0x000a34,   1, 0x04, 0x00000000 },
+       { 0x000a54,   1, 0x04, 0x00000000 },
+       { 0x000a74,   1, 0x04, 0x00000000 },
+       { 0x000a94,   1, 0x04, 0x00000000 },
+       { 0x000ab4,   1, 0x04, 0x00000000 },
+       { 0x000ad4,   1, 0x04, 0x00000000 },
+       { 0x000af4,   1, 0x04, 0x00000000 },
+       { 0x000b14,   1, 0x04, 0x00000000 },
+       { 0x000b34,   1, 0x04, 0x00000000 },
+       { 0x000b54,   1, 0x04, 0x00000000 },
+       { 0x000b74,   1, 0x04, 0x00000000 },
+       { 0x000b94,   1, 0x04, 0x00000000 },
+       { 0x000bb4,   1, 0x04, 0x00000000 },
+       { 0x000bd4,   1, 0x04, 0x00000000 },
+       { 0x000bf4,   1, 0x04, 0x00000000 },
+       { 0x000c00,   1, 0x04, 0x00000000 },
+       { 0x000c10,   1, 0x04, 0x00000000 },
+       { 0x000c20,   1, 0x04, 0x00000000 },
+       { 0x000c30,   1, 0x04, 0x00000000 },
+       { 0x000c40,   1, 0x04, 0x00000000 },
+       { 0x000c50,   1, 0x04, 0x00000000 },
+       { 0x000c60,   1, 0x04, 0x00000000 },
+       { 0x000c70,   1, 0x04, 0x00000000 },
+       { 0x000c80,   1, 0x04, 0x00000000 },
+       { 0x000c90,   1, 0x04, 0x00000000 },
+       { 0x000ca0,   1, 0x04, 0x00000000 },
+       { 0x000cb0,   1, 0x04, 0x00000000 },
+       { 0x000cc0,   1, 0x04, 0x00000000 },
+       { 0x000cd0,   1, 0x04, 0x00000000 },
+       { 0x000ce0,   1, 0x04, 0x00000000 },
+       { 0x000cf0,   1, 0x04, 0x00000000 },
+       { 0x000c04,   1, 0x04, 0x00000000 },
+       { 0x000c14,   1, 0x04, 0x00000000 },
+       { 0x000c24,   1, 0x04, 0x00000000 },
+       { 0x000c34,   1, 0x04, 0x00000000 },
+       { 0x000c44,   1, 0x04, 0x00000000 },
+       { 0x000c54,   1, 0x04, 0x00000000 },
+       { 0x000c64,   1, 0x04, 0x00000000 },
+       { 0x000c74,   1, 0x04, 0x00000000 },
+       { 0x000c84,   1, 0x04, 0x00000000 },
+       { 0x000c94,   1, 0x04, 0x00000000 },
+       { 0x000ca4,   1, 0x04, 0x00000000 },
+       { 0x000cb4,   1, 0x04, 0x00000000 },
+       { 0x000cc4,   1, 0x04, 0x00000000 },
+       { 0x000cd4,   1, 0x04, 0x00000000 },
+       { 0x000ce4,   1, 0x04, 0x00000000 },
+       { 0x000cf4,   1, 0x04, 0x00000000 },
+       { 0x000c08,   1, 0x04, 0x00000000 },
+       { 0x000c18,   1, 0x04, 0x00000000 },
+       { 0x000c28,   1, 0x04, 0x00000000 },
+       { 0x000c38,   1, 0x04, 0x00000000 },
+       { 0x000c48,   1, 0x04, 0x00000000 },
+       { 0x000c58,   1, 0x04, 0x00000000 },
+       { 0x000c68,   1, 0x04, 0x00000000 },
+       { 0x000c78,   1, 0x04, 0x00000000 },
+       { 0x000c88,   1, 0x04, 0x00000000 },
+       { 0x000c98,   1, 0x04, 0x00000000 },
+       { 0x000ca8,   1, 0x04, 0x00000000 },
+       { 0x000cb8,   1, 0x04, 0x00000000 },
+       { 0x000cc8,   1, 0x04, 0x00000000 },
+       { 0x000cd8,   1, 0x04, 0x00000000 },
+       { 0x000ce8,   1, 0x04, 0x00000000 },
+       { 0x000cf8,   1, 0x04, 0x00000000 },
+       { 0x000c0c,   1, 0x04, 0x3f800000 },
+       { 0x000c1c,   1, 0x04, 0x3f800000 },
+       { 0x000c2c,   1, 0x04, 0x3f800000 },
+       { 0x000c3c,   1, 0x04, 0x3f800000 },
+       { 0x000c4c,   1, 0x04, 0x3f800000 },
+       { 0x000c5c,   1, 0x04, 0x3f800000 },
+       { 0x000c6c,   1, 0x04, 0x3f800000 },
+       { 0x000c7c,   1, 0x04, 0x3f800000 },
+       { 0x000c8c,   1, 0x04, 0x3f800000 },
+       { 0x000c9c,   1, 0x04, 0x3f800000 },
+       { 0x000cac,   1, 0x04, 0x3f800000 },
+       { 0x000cbc,   1, 0x04, 0x3f800000 },
+       { 0x000ccc,   1, 0x04, 0x3f800000 },
+       { 0x000cdc,   1, 0x04, 0x3f800000 },
+       { 0x000cec,   1, 0x04, 0x3f800000 },
+       { 0x000cfc,   1, 0x04, 0x3f800000 },
+       { 0x000d00,   1, 0x04, 0xffff0000 },
+       { 0x000d08,   1, 0x04, 0xffff0000 },
+       { 0x000d10,   1, 0x04, 0xffff0000 },
+       { 0x000d18,   1, 0x04, 0xffff0000 },
+       { 0x000d20,   1, 0x04, 0xffff0000 },
+       { 0x000d28,   1, 0x04, 0xffff0000 },
+       { 0x000d30,   1, 0x04, 0xffff0000 },
+       { 0x000d38,   1, 0x04, 0xffff0000 },
+       { 0x000d04,   1, 0x04, 0xffff0000 },
+       { 0x000d0c,   1, 0x04, 0xffff0000 },
+       { 0x000d14,   1, 0x04, 0xffff0000 },
+       { 0x000d1c,   1, 0x04, 0xffff0000 },
+       { 0x000d24,   1, 0x04, 0xffff0000 },
+       { 0x000d2c,   1, 0x04, 0xffff0000 },
+       { 0x000d34,   1, 0x04, 0xffff0000 },
+       { 0x000d3c,   1, 0x04, 0xffff0000 },
+       { 0x000e00,   1, 0x04, 0x00000000 },
+       { 0x000e10,   1, 0x04, 0x00000000 },
+       { 0x000e20,   1, 0x04, 0x00000000 },
+       { 0x000e30,   1, 0x04, 0x00000000 },
+       { 0x000e40,   1, 0x04, 0x00000000 },
+       { 0x000e50,   1, 0x04, 0x00000000 },
+       { 0x000e60,   1, 0x04, 0x00000000 },
+       { 0x000e70,   1, 0x04, 0x00000000 },
+       { 0x000e80,   1, 0x04, 0x00000000 },
+       { 0x000e90,   1, 0x04, 0x00000000 },
+       { 0x000ea0,   1, 0x04, 0x00000000 },
+       { 0x000eb0,   1, 0x04, 0x00000000 },
+       { 0x000ec0,   1, 0x04, 0x00000000 },
+       { 0x000ed0,   1, 0x04, 0x00000000 },
+       { 0x000ee0,   1, 0x04, 0x00000000 },
+       { 0x000ef0,   1, 0x04, 0x00000000 },
+       { 0x000e04,   1, 0x04, 0xffff0000 },
+       { 0x000e14,   1, 0x04, 0xffff0000 },
+       { 0x000e24,   1, 0x04, 0xffff0000 },
+       { 0x000e34,   1, 0x04, 0xffff0000 },
+       { 0x000e44,   1, 0x04, 0xffff0000 },
+       { 0x000e54,   1, 0x04, 0xffff0000 },
+       { 0x000e64,   1, 0x04, 0xffff0000 },
+       { 0x000e74,   1, 0x04, 0xffff0000 },
+       { 0x000e84,   1, 0x04, 0xffff0000 },
+       { 0x000e94,   1, 0x04, 0xffff0000 },
+       { 0x000ea4,   1, 0x04, 0xffff0000 },
+       { 0x000eb4,   1, 0x04, 0xffff0000 },
+       { 0x000ec4,   1, 0x04, 0xffff0000 },
+       { 0x000ed4,   1, 0x04, 0xffff0000 },
+       { 0x000ee4,   1, 0x04, 0xffff0000 },
+       { 0x000ef4,   1, 0x04, 0xffff0000 },
+       { 0x000e08,   1, 0x04, 0xffff0000 },
+       { 0x000e18,   1, 0x04, 0xffff0000 },
+       { 0x000e28,   1, 0x04, 0xffff0000 },
+       { 0x000e38,   1, 0x04, 0xffff0000 },
+       { 0x000e48,   1, 0x04, 0xffff0000 },
+       { 0x000e58,   1, 0x04, 0xffff0000 },
+       { 0x000e68,   1, 0x04, 0xffff0000 },
+       { 0x000e78,   1, 0x04, 0xffff0000 },
+       { 0x000e88,   1, 0x04, 0xffff0000 },
+       { 0x000e98,   1, 0x04, 0xffff0000 },
+       { 0x000ea8,   1, 0x04, 0xffff0000 },
+       { 0x000eb8,   1, 0x04, 0xffff0000 },
+       { 0x000ec8,   1, 0x04, 0xffff0000 },
+       { 0x000ed8,   1, 0x04, 0xffff0000 },
+       { 0x000ee8,   1, 0x04, 0xffff0000 },
+       { 0x000ef8,   1, 0x04, 0xffff0000 },
+       { 0x000d40,   1, 0x04, 0x00000000 },
+       { 0x000d48,   1, 0x04, 0x00000000 },
+       { 0x000d50,   1, 0x04, 0x00000000 },
+       { 0x000d58,   1, 0x04, 0x00000000 },
+       { 0x000d44,   1, 0x04, 0x00000000 },
+       { 0x000d4c,   1, 0x04, 0x00000000 },
+       { 0x000d54,   1, 0x04, 0x00000000 },
+       { 0x000d5c,   1, 0x04, 0x00000000 },
+       { 0x001e00,   1, 0x04, 0x00000001 },
+       { 0x001e20,   1, 0x04, 0x00000001 },
+       { 0x001e40,   1, 0x04, 0x00000001 },
+       { 0x001e60,   1, 0x04, 0x00000001 },
+       { 0x001e80,   1, 0x04, 0x00000001 },
+       { 0x001ea0,   1, 0x04, 0x00000001 },
+       { 0x001ec0,   1, 0x04, 0x00000001 },
+       { 0x001ee0,   1, 0x04, 0x00000001 },
+       { 0x001e04,   1, 0x04, 0x00000001 },
+       { 0x001e24,   1, 0x04, 0x00000001 },
+       { 0x001e44,   1, 0x04, 0x00000001 },
+       { 0x001e64,   1, 0x04, 0x00000001 },
+       { 0x001e84,   1, 0x04, 0x00000001 },
+       { 0x001ea4,   1, 0x04, 0x00000001 },
+       { 0x001ec4,   1, 0x04, 0x00000001 },
+       { 0x001ee4,   1, 0x04, 0x00000001 },
+       { 0x001e08,   1, 0x04, 0x00000002 },
+       { 0x001e28,   1, 0x04, 0x00000002 },
+       { 0x001e48,   1, 0x04, 0x00000002 },
+       { 0x001e68,   1, 0x04, 0x00000002 },
+       { 0x001e88,   1, 0x04, 0x00000002 },
+       { 0x001ea8,   1, 0x04, 0x00000002 },
+       { 0x001ec8,   1, 0x04, 0x00000002 },
+       { 0x001ee8,   1, 0x04, 0x00000002 },
+       { 0x001e0c,   1, 0x04, 0x00000001 },
+       { 0x001e2c,   1, 0x04, 0x00000001 },
+       { 0x001e4c,   1, 0x04, 0x00000001 },
+       { 0x001e6c,   1, 0x04, 0x00000001 },
+       { 0x001e8c,   1, 0x04, 0x00000001 },
+       { 0x001eac,   1, 0x04, 0x00000001 },
+       { 0x001ecc,   1, 0x04, 0x00000001 },
+       { 0x001eec,   1, 0x04, 0x00000001 },
+       { 0x001e10,   1, 0x04, 0x00000001 },
+       { 0x001e30,   1, 0x04, 0x00000001 },
+       { 0x001e50,   1, 0x04, 0x00000001 },
+       { 0x001e70,   1, 0x04, 0x00000001 },
+       { 0x001e90,   1, 0x04, 0x00000001 },
+       { 0x001eb0,   1, 0x04, 0x00000001 },
+       { 0x001ed0,   1, 0x04, 0x00000001 },
+       { 0x001ef0,   1, 0x04, 0x00000001 },
+       { 0x001e14,   1, 0x04, 0x00000002 },
+       { 0x001e34,   1, 0x04, 0x00000002 },
+       { 0x001e54,   1, 0x04, 0x00000002 },
+       { 0x001e74,   1, 0x04, 0x00000002 },
+       { 0x001e94,   1, 0x04, 0x00000002 },
+       { 0x001eb4,   1, 0x04, 0x00000002 },
+       { 0x001ed4,   1, 0x04, 0x00000002 },
+       { 0x001ef4,   1, 0x04, 0x00000002 },
+       { 0x001e18,   1, 0x04, 0x00000001 },
+       { 0x001e38,   1, 0x04, 0x00000001 },
+       { 0x001e58,   1, 0x04, 0x00000001 },
+       { 0x001e78,   1, 0x04, 0x00000001 },
+       { 0x001e98,   1, 0x04, 0x00000001 },
+       { 0x001eb8,   1, 0x04, 0x00000001 },
+       { 0x001ed8,   1, 0x04, 0x00000001 },
+       { 0x001ef8,   1, 0x04, 0x00000001 },
+       { 0x003400, 128, 0x04, 0x00000000 },
+       { 0x00030c,   1, 0x04, 0x00000001 },
+       { 0x001944,   1, 0x04, 0x00000000 },
+       { 0x001514,   1, 0x04, 0x00000000 },
+       { 0x000d68,   1, 0x04, 0x0000ffff },
+       { 0x00121c,   1, 0x04, 0x0fac6881 },
+       { 0x000fac,   1, 0x04, 0x00000001 },
+       { 0x001538,   1, 0x04, 0x00000001 },
+       { 0x000fe0,   2, 0x04, 0x00000000 },
+       { 0x000fe8,   1, 0x04, 0x00000014 },
+       { 0x000fec,   1, 0x04, 0x00000040 },
+       { 0x000ff0,   1, 0x04, 0x00000000 },
+       { 0x00179c,   1, 0x04, 0x00000000 },
+       { 0x001228,   1, 0x04, 0x00000400 },
+       { 0x00122c,   1, 0x04, 0x00000300 },
+       { 0x001230,   1, 0x04, 0x00010001 },
+       { 0x0007f8,   1, 0x04, 0x00000000 },
+       { 0x0015b4,   1, 0x04, 0x00000001 },
+       { 0x0015cc,   1, 0x04, 0x00000000 },
+       { 0x001534,   1, 0x04, 0x00000000 },
+       { 0x000fb0,   1, 0x04, 0x00000000 },
+       { 0x0015d0,   1, 0x04, 0x00000000 },
+       { 0x00153c,   1, 0x04, 0x00000000 },
+       { 0x0016b4,   1, 0x04, 0x00000003 },
+       { 0x000fbc,   4, 0x04, 0x0000ffff },
+       { 0x000df8,   2, 0x04, 0x00000000 },
+       { 0x001948,   1, 0x04, 0x00000000 },
+       { 0x001970,   1, 0x04, 0x00000001 },
+       { 0x00161c,   1, 0x04, 0x000009f0 },
+       { 0x000dcc,   1, 0x04, 0x00000010 },
+       { 0x00163c,   1, 0x04, 0x00000000 },
+       { 0x0015e4,   1, 0x04, 0x00000000 },
+       { 0x001160,  32, 0x04, 0x25e00040 },
+       { 0x001880,  32, 0x04, 0x00000000 },
+       { 0x000f84,   2, 0x04, 0x00000000 },
+       { 0x0017c8,   2, 0x04, 0x00000000 },
+       { 0x0017d0,   1, 0x04, 0x000000ff },
+       { 0x0017d4,   1, 0x04, 0xffffffff },
+       { 0x0017d8,   1, 0x04, 0x00000002 },
+       { 0x0017dc,   1, 0x04, 0x00000000 },
+       { 0x0015f4,   2, 0x04, 0x00000000 },
+       { 0x001434,   2, 0x04, 0x00000000 },
+       { 0x000d74,   1, 0x04, 0x00000000 },
+       { 0x000dec,   1, 0x04, 0x00000001 },
+       { 0x0013a4,   1, 0x04, 0x00000000 },
+       { 0x001318,   1, 0x04, 0x00000001 },
+       { 0x001644,   1, 0x04, 0x00000000 },
+       { 0x000748,   1, 0x04, 0x00000000 },
+       { 0x000de8,   1, 0x04, 0x00000000 },
+       { 0x001648,   1, 0x04, 0x00000000 },
+       { 0x0012a4,   1, 0x04, 0x00000000 },
+       { 0x001120,   4, 0x04, 0x00000000 },
+       { 0x001118,   1, 0x04, 0x00000000 },
+       { 0x00164c,   1, 0x04, 0x00000000 },
+       { 0x001658,   1, 0x04, 0x00000000 },
+       { 0x001910,   1, 0x04, 0x00000290 },
+       { 0x001518,   1, 0x04, 0x00000000 },
+       { 0x00165c,   1, 0x04, 0x00000001 },
+       { 0x001520,   1, 0x04, 0x00000000 },
+       { 0x001604,   1, 0x04, 0x00000000 },
+       { 0x001570,   1, 0x04, 0x00000000 },
+       { 0x0013b0,   2, 0x04, 0x3f800000 },
+       { 0x00020c,   1, 0x04, 0x00000000 },
+       { 0x001670,   1, 0x04, 0x30201000 },
+       { 0x001674,   1, 0x04, 0x70605040 },
+       { 0x001678,   1, 0x04, 0xb8a89888 },
+       { 0x00167c,   1, 0x04, 0xf8e8d8c8 },
+       { 0x00166c,   1, 0x04, 0x00000000 },
+       { 0x001680,   1, 0x04, 0x00ffff00 },
+       { 0x0012d0,   1, 0x04, 0x00000003 },
+       { 0x0012d4,   1, 0x04, 0x00000002 },
+       { 0x001684,   2, 0x04, 0x00000000 },
+       { 0x000dac,   2, 0x04, 0x00001b02 },
+       { 0x000db4,   1, 0x04, 0x00000000 },
+       { 0x00168c,   1, 0x04, 0x00000000 },
+       { 0x0015bc,   1, 0x04, 0x00000000 },
+       { 0x00156c,   1, 0x04, 0x00000000 },
+       { 0x00187c,   1, 0x04, 0x00000000 },
+       { 0x001110,   1, 0x04, 0x00000001 },
+       { 0x000dc0,   3, 0x04, 0x00000000 },
+       { 0x001234,   1, 0x04, 0x00000000 },
+       { 0x001690,   1, 0x04, 0x00000000 },
+       { 0x0012ac,   1, 0x04, 0x00000001 },
+       { 0x0002c4,   1, 0x04, 0x00000000 },
+       { 0x000790,   5, 0x04, 0x00000000 },
+       { 0x00077c,   1, 0x04, 0x00000000 },
+       { 0x001000,   1, 0x04, 0x00000010 },
+       { 0x0010fc,   1, 0x04, 0x00000000 },
+       { 0x001290,   1, 0x04, 0x00000000 },
+       { 0x000218,   1, 0x04, 0x00000010 },
+       { 0x0012d8,   1, 0x04, 0x00000000 },
+       { 0x0012dc,   1, 0x04, 0x00000010 },
+       { 0x000d94,   1, 0x04, 0x00000001 },
+       { 0x00155c,   2, 0x04, 0x00000000 },
+       { 0x001564,   1, 0x04, 0x00000fff },
+       { 0x001574,   2, 0x04, 0x00000000 },
+       { 0x00157c,   1, 0x04, 0x000fffff },
+       { 0x001354,   1, 0x04, 0x00000000 },
+       { 0x001610,   1, 0x04, 0x00000012 },
+       { 0x001608,   2, 0x04, 0x00000000 },
+       { 0x00260c,   1, 0x04, 0x00000000 },
+       { 0x0007ac,   1, 0x04, 0x00000000 },
+       { 0x00162c,   1, 0x04, 0x00000003 },
+       { 0x000210,   1, 0x04, 0x00000000 },
+       { 0x000320,   1, 0x04, 0x00000000 },
+       { 0x000324,   6, 0x04, 0x3f800000 },
+       { 0x000750,   1, 0x04, 0x00000000 },
+       { 0x000760,   1, 0x04, 0x39291909 },
+       { 0x000764,   1, 0x04, 0x79695949 },
+       { 0x000768,   1, 0x04, 0xb9a99989 },
+       { 0x00076c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x000770,   1, 0x04, 0x30201000 },
+       { 0x000774,   1, 0x04, 0x70605040 },
+       { 0x000778,   1, 0x04, 0x00009080 },
+       { 0x000780,   1, 0x04, 0x39291909 },
+       { 0x000784,   1, 0x04, 0x79695949 },
+       { 0x000788,   1, 0x04, 0xb9a99989 },
+       { 0x00078c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x0007d0,   1, 0x04, 0x30201000 },
+       { 0x0007d4,   1, 0x04, 0x70605040 },
+       { 0x0007d8,   1, 0x04, 0x00009080 },
+       { 0x00037c,   1, 0x04, 0x00000001 },
+       { 0x000740,   2, 0x04, 0x00000000 },
+       { 0x002600,   1, 0x04, 0x00000000 },
+       { 0x001918,   1, 0x04, 0x00000000 },
+       { 0x00191c,   1, 0x04, 0x00000900 },
+       { 0x001920,   1, 0x04, 0x00000405 },
+       { 0x001308,   1, 0x04, 0x00000001 },
+       { 0x001924,   1, 0x04, 0x00000000 },
+       { 0x0013ac,   1, 0x04, 0x00000000 },
+       { 0x00192c,   1, 0x04, 0x00000001 },
+       { 0x00193c,   1, 0x04, 0x00002c1c },
+       { 0x000d7c,   1, 0x04, 0x00000000 },
+       { 0x000f8c,   1, 0x04, 0x00000000 },
+       { 0x0002c0,   1, 0x04, 0x00000001 },
+       { 0x001510,   1, 0x04, 0x00000000 },
+       { 0x001940,   1, 0x04, 0x00000000 },
+       { 0x000ff4,   2, 0x04, 0x00000000 },
+       { 0x00194c,   2, 0x04, 0x00000000 },
+       { 0x001968,   1, 0x04, 0x00000000 },
+       { 0x001590,   1, 0x04, 0x0000003f },
+       { 0x0007e8,   4, 0x04, 0x00000000 },
+       { 0x00196c,   1, 0x04, 0x00000011 },
+       { 0x0002e4,   1, 0x04, 0x0000b001 },
+       { 0x00036c,   2, 0x04, 0x00000000 },
+       { 0x00197c,   1, 0x04, 0x00000000 },
+       { 0x000fcc,   2, 0x04, 0x00000000 },
+       { 0x0002d8,   1, 0x04, 0x00000040 },
+       { 0x001980,   1, 0x04, 0x00000080 },
+       { 0x001504,   1, 0x04, 0x00000080 },
+       { 0x001984,   1, 0x04, 0x00000000 },
+       { 0x000300,   1, 0x04, 0x00000001 },
+       { 0x0013a8,   1, 0x04, 0x00000000 },
+       { 0x0012ec,   1, 0x04, 0x00000000 },
+       { 0x001310,   1, 0x04, 0x00000000 },
+       { 0x001314,   1, 0x04, 0x00000001 },
+       { 0x001380,   1, 0x04, 0x00000000 },
+       { 0x001384,   4, 0x04, 0x00000001 },
+       { 0x001394,   1, 0x04, 0x00000000 },
+       { 0x00139c,   1, 0x04, 0x00000000 },
+       { 0x001398,   1, 0x04, 0x00000000 },
+       { 0x001594,   1, 0x04, 0x00000000 },
+       { 0x001598,   4, 0x04, 0x00000001 },
+       { 0x000f54,   3, 0x04, 0x00000000 },
+       { 0x0019bc,   1, 0x04, 0x00000000 },
+       { 0x000f9c,   2, 0x04, 0x00000000 },
+       { 0x0012cc,   1, 0x04, 0x00000000 },
+       { 0x0012e8,   1, 0x04, 0x00000000 },
+       { 0x00130c,   1, 0x04, 0x00000001 },
+       { 0x001360,   8, 0x04, 0x00000000 },
+       { 0x00133c,   2, 0x04, 0x00000001 },
+       { 0x001344,   1, 0x04, 0x00000002 },
+       { 0x001348,   2, 0x04, 0x00000001 },
+       { 0x001350,   1, 0x04, 0x00000002 },
+       { 0x001358,   1, 0x04, 0x00000001 },
+       { 0x0012e4,   1, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
+       { 0x0019c0,   1, 0x04, 0x00000000 },
+       { 0x001140,   1, 0x04, 0x00000000 },
+       { 0x0019c4,   1, 0x04, 0x00000000 },
+       { 0x0019c8,   1, 0x04, 0x00001500 },
+       { 0x00135c,   1, 0x04, 0x00000000 },
+       { 0x000f90,   1, 0x04, 0x00000000 },
+       { 0x0019e0,   8, 0x04, 0x00000001 },
+       { 0x0019cc,   1, 0x04, 0x00000001 },
+       { 0x0015b8,   1, 0x04, 0x00000000 },
+       { 0x001a00,   1, 0x04, 0x00001111 },
+       { 0x001a04,   7, 0x04, 0x00000000 },
+       { 0x000d6c,   2, 0x04, 0xffff0000 },
+       { 0x0010f8,   1, 0x04, 0x00001010 },
+       { 0x000d80,   5, 0x04, 0x00000000 },
+       { 0x000da0,   1, 0x04, 0x00000000 },
+       { 0x0007a4,   2, 0x04, 0x00000000 },
+       { 0x001508,   1, 0x04, 0x80000000 },
+       { 0x00150c,   1, 0x04, 0x40000000 },
+       { 0x001668,   1, 0x04, 0x00000000 },
+       { 0x000318,   2, 0x04, 0x00000008 },
+       { 0x000d9c,   1, 0x04, 0x00000001 },
+       { 0x000ddc,   1, 0x04, 0x00000002 },
+       { 0x000374,   1, 0x04, 0x00000000 },
+       { 0x000378,   1, 0x04, 0x00000020 },
+       { 0x0007dc,   1, 0x04, 0x00000000 },
+       { 0x00074c,   1, 0x04, 0x00000055 },
+       { 0x001420,   1, 0x04, 0x00000003 },
+       { 0x0017bc,   2, 0x04, 0x00000000 },
+       { 0x0017c4,   1, 0x04, 0x00000001 },
+       { 0x001008,   1, 0x04, 0x00000008 },
+       { 0x00100c,   1, 0x04, 0x00000040 },
+       { 0x001010,   1, 0x04, 0x0000012c },
+       { 0x000d60,   1, 0x04, 0x00000040 },
+       { 0x00075c,   1, 0x04, 0x00000003 },
+       { 0x001018,   1, 0x04, 0x00000020 },
+       { 0x00101c,   1, 0x04, 0x00000001 },
+       { 0x001020,   1, 0x04, 0x00000020 },
+       { 0x001024,   1, 0x04, 0x00000001 },
+       { 0x001444,   3, 0x04, 0x00000000 },
+       { 0x000360,   1, 0x04, 0x20164010 },
+       { 0x000364,   1, 0x04, 0x00000020 },
+       { 0x000368,   1, 0x04, 0x00000000 },
+       { 0x000de4,   1, 0x04, 0x00000000 },
+       { 0x000204,   1, 0x04, 0x00000006 },
+       { 0x000208,   1, 0x04, 0x00000000 },
+       { 0x0002cc,   2, 0x04, 0x003fffff },
+       { 0x001220,   1, 0x04, 0x00000005 },
+       { 0x000fdc,   1, 0x04, 0x00000000 },
+       { 0x000f98,   1, 0x04, 0x00400008 },
+       { 0x001284,   1, 0x04, 0x08000080 },
+       { 0x001450,   1, 0x04, 0x00400008 },
+       { 0x001454,   1, 0x04, 0x08000080 },
+       { 0x000214,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk40xx[] = {
+       { 0x404004,   8, 0x04, 0x00000000 },
+       { 0x404024,   1, 0x04, 0x0000e000 },
+       { 0x404028,   8, 0x04, 0x00000000 },
+       { 0x4040a8,   8, 0x04, 0x00000000 },
+       { 0x4040c8,   1, 0x04, 0xf800008f },
+       { 0x4040d0,   6, 0x04, 0x00000000 },
+       { 0x4040e8,   1, 0x04, 0x00001000 },
+       { 0x4040f8,   1, 0x04, 0x00000000 },
+       { 0x404100,  10, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
+       { 0x404138,   1, 0x04, 0x20000040 },
+       { 0x404150,   1, 0x04, 0x0000002e },
+       { 0x404154,   1, 0x04, 0x00000400 },
+       { 0x404158,   1, 0x04, 0x00000200 },
+       { 0x404164,   1, 0x04, 0x00000055 },
+       { 0x40417c,   2, 0x04, 0x00000000 },
+       { 0x404194,   1, 0x04, 0x01000700 },
+       { 0x4041a0,   4, 0x04, 0x00000000 },
+       { 0x404200,   1, 0x04, 0x0000a197 },
+       { 0x404204,   1, 0x04, 0x0000a1c0 },
+       { 0x404208,   1, 0x04, 0x0000a140 },
+       { 0x40420c,   1, 0x04, 0x0000902d },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk58xx[] = {
+       { 0x405800,   1, 0x04, 0x0f8000bf },
+       { 0x405830,   1, 0x04, 0x02180648 },
+       { 0x405834,   1, 0x04, 0x08000000 },
+       { 0x405838,   1, 0x04, 0x00000000 },
+       { 0x405854,   1, 0x04, 0x00000000 },
+       { 0x405870,   4, 0x04, 0x00000001 },
+       { 0x405a00,   2, 0x04, 0x00000000 },
+       { 0x405a18,   1, 0x04, 0x00000000 },
+       { 0x405a1c,   1, 0x04, 0x000000ff },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk64xx[] = {
+       { 0x4064a8,   1, 0x04, 0x00000000 },
+       { 0x4064ac,   1, 0x04, 0x00003fff },
+       { 0x4064b0,   3, 0x04, 0x00000000 },
+       { 0x4064c0,   1, 0x04, 0x802000f0 },
+       { 0x4064c4,   1, 0x04, 0x0192ffff },
+       { 0x4064c8,   1, 0x04, 0x00c20200 },
+       { 0x4064cc,   9, 0x04, 0x00000000 },
+       { 0x4064fc,   1, 0x04, 0x0000022a },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk78xx[] = {
+       { 0x407804,   1, 0x04, 0x00000063 },
+       { 0x40780c,   1, 0x04, 0x0a418820 },
+       { 0x407810,   1, 0x04, 0x062080e6 },
+       { 0x407814,   1, 0x04, 0x020398a4 },
+       { 0x407818,   1, 0x04, 0x0e629062 },
+       { 0x40781c,   1, 0x04, 0x0a418820 },
+       { 0x407820,   1, 0x04, 0x000000e6 },
+       { 0x4078bc,   1, 0x04, 0x00000103 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk88xx[] = {
+       { 0x408800,   1, 0x04, 0x32802a3c },
+       { 0x408804,   1, 0x04, 0x00000040 },
+       { 0x408808,   1, 0x04, 0x1003e005 },
+       { 0x408840,   1, 0x04, 0x0000000b },
+       { 0x408900,   1, 0x04, 0xb080b801 },
+       { 0x408904,   1, 0x04, 0x62000001 },
+       { 0x408908,   1, 0x04, 0x02c8102f },
+       { 0x408980,   1, 0x04, 0x0000011d },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_gpc_0[] = {
+       { 0x418380,   1, 0x04, 0x00000016 },
+       { 0x418400,   1, 0x04, 0x38005e00 },
+       { 0x418404,   1, 0x04, 0x71e0ffff },
+       { 0x41840c,   1, 0x04, 0x00001008 },
+       { 0x418410,   1, 0x04, 0x0fff0fff },
+       { 0x418414,   1, 0x04, 0x02200fff },
+       { 0x418450,   6, 0x04, 0x00000000 },
+       { 0x418468,   1, 0x04, 0x00000001 },
+       { 0x41846c,   2, 0x04, 0x00000000 },
+       { 0x418600,   1, 0x04, 0x0000007f },
+       { 0x418684,   1, 0x04, 0x0000001f },
+       { 0x418700,   1, 0x04, 0x00000002 },
+       { 0x418704,   2, 0x04, 0x00000080 },
+       { 0x41870c,   2, 0x04, 0x00000000 },
+       { 0x418800,   1, 0x04, 0x7006863a },
+       { 0x418808,   1, 0x04, 0x00000000 },
+       { 0x41880c,   1, 0x04, 0x00000030 },
+       { 0x418810,   1, 0x04, 0x00000000 },
+       { 0x418828,   1, 0x04, 0x00000044 },
+       { 0x418830,   1, 0x04, 0x10000001 },
+       { 0x4188d8,   1, 0x04, 0x00000008 },
+       { 0x4188e0,   1, 0x04, 0x01000000 },
+       { 0x4188e8,   5, 0x04, 0x00000000 },
+       { 0x4188fc,   1, 0x04, 0x20100058 },
+       { 0x41891c,   1, 0x04, 0x00ff00ff },
+       { 0x418924,   1, 0x04, 0x00000000 },
+       { 0x418928,   1, 0x04, 0x00ffff00 },
+       { 0x41892c,   1, 0x04, 0x0000ff00 },
+       { 0x418b00,   1, 0x04, 0x0000001e },
+       { 0x418b08,   1, 0x04, 0x0a418820 },
+       { 0x418b0c,   1, 0x04, 0x062080e6 },
+       { 0x418b10,   1, 0x04, 0x020398a4 },
+       { 0x418b14,   1, 0x04, 0x0e629062 },
+       { 0x418b18,   1, 0x04, 0x0a418820 },
+       { 0x418b1c,   1, 0x04, 0x000000e6 },
+       { 0x418bb8,   1, 0x04, 0x00000103 },
+       { 0x418c08,   1, 0x04, 0x00000001 },
+       { 0x418c10,   8, 0x04, 0x00000000 },
+       { 0x418c40,   1, 0x04, 0xffffffff },
+       { 0x418c6c,   1, 0x04, 0x00000001 },
+       { 0x418c80,   1, 0x04, 0x2020000c },
+       { 0x418c8c,   1, 0x04, 0x00000001 },
+       { 0x418d24,   1, 0x04, 0x00000000 },
+       { 0x419000,   1, 0x04, 0x00000780 },
+       { 0x419004,   2, 0x04, 0x00000000 },
+       { 0x419014,   1, 0x04, 0x00000004 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_tpc[] = {
+       { 0x419848,   1, 0x04, 0x00000000 },
+       { 0x419864,   1, 0x04, 0x00000129 },
+       { 0x419888,   1, 0x04, 0x00000000 },
+       { 0x419a00,   1, 0x04, 0x000100f0 },
+       { 0x419a04,   1, 0x04, 0x00000001 },
+       { 0x419a08,   1, 0x04, 0x00000421 },
+       { 0x419a0c,   1, 0x04, 0x00120000 },
+       { 0x419a10,   1, 0x04, 0x00000000 },
+       { 0x419a14,   1, 0x04, 0x00000200 },
+       { 0x419a1c,   1, 0x04, 0x0000c000 },
+       { 0x419a20,   1, 0x04, 0x00000800 },
+       { 0x419a30,   1, 0x04, 0x00000001 },
+       { 0x419ac4,   1, 0x04, 0x0037f440 },
+       { 0x419c00,   1, 0x04, 0x0000001a },
+       { 0x419c04,   1, 0x04, 0x80000006 },
+       { 0x419c08,   1, 0x04, 0x00000002 },
+       { 0x419c20,   1, 0x04, 0x00000000 },
+       { 0x419c24,   1, 0x04, 0x00084210 },
+       { 0x419c28,   1, 0x04, 0x3efbefbe },
+       { 0x419ce8,   1, 0x04, 0x00000000 },
+       { 0x419cf4,   1, 0x04, 0x00000203 },
+       { 0x419e04,   1, 0x04, 0x00000000 },
+       { 0x419e08,   1, 0x04, 0x0000001d },
+       { 0x419e0c,   1, 0x04, 0x00000000 },
+       { 0x419e10,   1, 0x04, 0x00001c02 },
+       { 0x419e44,   1, 0x04, 0x0013eff2 },
+       { 0x419e48,   1, 0x04, 0x00000000 },
+       { 0x419e4c,   1, 0x04, 0x0000007f },
+       { 0x419e50,   2, 0x04, 0x00000000 },
+       { 0x419e58,   1, 0x04, 0x00000001 },
+       { 0x419e5c,   3, 0x04, 0x00000000 },
+       { 0x419e68,   1, 0x04, 0x00000002 },
+       { 0x419e6c,  12, 0x04, 0x00000000 },
+       { 0x419eac,   1, 0x04, 0x00001f8f },
+       { 0x419eb0,   1, 0x04, 0x0db00da0 },
+       { 0x419eb8,   1, 0x04, 0x00000000 },
+       { 0x419ec8,   1, 0x04, 0x0001304f },
+       { 0x419f30,   4, 0x04, 0x00000000 },
+       { 0x419f40,   1, 0x04, 0x00000018 },
+       { 0x419f44,   3, 0x04, 0x00000000 },
+       { 0x419f58,   1, 0x04, 0x00000020 },
+       { 0x419f70,   1, 0x04, 0x00000000 },
+       { 0x419f78,   1, 0x04, 0x000001eb },
+       { 0x419f7c,   1, 0x04, 0x00000404 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk[] = {
+       { 0x41be24,   1, 0x04, 0x00000006 },
+       { 0x41bec0,   1, 0x04, 0x10000000 },
+       { 0x41bec4,   1, 0x04, 0x00037f7f },
+       { 0x41bee4,   1, 0x04, 0x00000000 },
+       { 0x41bef0,   1, 0x04, 0x000003ff },
+       { 0x41bf00,   1, 0x04, 0x0a418820 },
+       { 0x41bf04,   1, 0x04, 0x062080e6 },
+       { 0x41bf08,   1, 0x04, 0x020398a4 },
+       { 0x41bf0c,   1, 0x04, 0x0e629062 },
+       { 0x41bf10,   1, 0x04, 0x0a418820 },
+       { 0x41bf14,   1, 0x04, 0x000000e6 },
+       { 0x41bfd0,   1, 0x04, 0x00900103 },
+       { 0x41bfe0,   1, 0x04, 0x00400001 },
+       { 0x41bfe4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static void
+nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+       u32 magic[GPC_MAX][2];
+       u32 offset;
+       int gpc;
+
+       mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+       mmio_list(0x40800c, 0x00000000,  8, 1);
+       mmio_list(0x408010, 0x80000000,  0, 0);
+       mmio_list(0x419004, 0x00000000,  8, 1);
+       mmio_list(0x419008, 0x00000000,  0, 0);
+       mmio_list(0x408004, 0x00000000,  8, 0);
+       mmio_list(0x408008, 0x80000030,  0, 0);
+       mmio_list(0x418808, 0x00000000,  8, 0);
+       mmio_list(0x41880c, 0x80000030,  0, 0);
+       mmio_list(0x418810, 0x80000000, 12, 2);
+       mmio_list(0x419848, 0x10000000, 12, 2);
+
+       mmio_list(0x405830, 0x02180648,  0, 0);
+       mmio_list(0x4064c4, 0x0192ffff,  0, 0);
+
+       for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+               u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
+               u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
+               magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
+               magic[gpc][1]  = 0x00000000 | (magic1 << 16);
+               offset += 0x0324 * priv->tpc_nr[gpc];
+       }
+
+       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+               mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
+               mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
+               offset += 0x07ff * priv->tpc_nr[gpc];
+       }
+
+       mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
+       mmio_list(0x17e920, 0x00090d08, 0, 0);
+}
+
+static struct nvc0_graph_init *
+nv108_grctx_init_hub[] = {
+       nvc0_grctx_init_base,
+       nv108_grctx_init_unk40xx,
+       nvf0_grctx_init_unk44xx,
+       nve4_grctx_init_unk46xx,
+       nve4_grctx_init_unk47xx,
+       nv108_grctx_init_unk58xx,
+       nvf0_grctx_init_unk5bxx,
+       nvf0_grctx_init_unk60xx,
+       nv108_grctx_init_unk64xx,
+       nv108_grctx_init_unk78xx,
+       nve4_grctx_init_unk80xx,
+       nv108_grctx_init_unk88xx,
+       NULL
+};
+
+struct nvc0_graph_init *
+nv108_grctx_init_gpc[] = {
+       nv108_grctx_init_gpc_0,
+       nvc0_grctx_init_gpc_1,
+       nv108_grctx_init_tpc,
+       nv108_grctx_init_unk,
+       NULL
+};
+
+struct nvc0_graph_init
+nv108_grctx_init_mthd_magic[] = {
+       { 0x3410, 1, 0x04, 0x8e0e2006 },
+       { 0x3414, 1, 0x04, 0x00000038 },
+       {}
+};
+
+static struct nvc0_graph_mthd
+nv108_grctx_init_mthd[] = {
+       { 0xa197, nv108_grctx_init_a197, },
+       { 0x902d, nvc0_grctx_init_902d, },
+       { 0x902d, nv108_grctx_init_mthd_magic, },
+       {}
+};
+
+struct nouveau_oclass *
+nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
+       .base.handle = NV_ENGCTX(GR, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_context_ctor,
+               .dtor = nvc0_graph_context_dtor,
+               .init = _nouveau_graph_context_init,
+               .fini = _nouveau_graph_context_fini,
+               .rd32 = _nouveau_graph_context_rd32,
+               .wr32 = _nouveau_graph_context_wr32,
+       },
+       .main = nve4_grctx_generate_main,
+       .mods = nv108_grctx_generate_mods,
+       .unkn = nve4_grctx_generate_unkn,
+       .hub  = nv108_grctx_init_hub,
+       .gpc  = nv108_grctx_init_gpc,
+       .icmd = nv108_grctx_init_icmd,
+       .mthd = nv108_grctx_init_mthd,
+}.base;
index dcb2ebb8c29d93ac211bebd3d79f6224b48604b8..44012c3da53832c325e2286bafcc191208d9e946 100644 (file)
@@ -50,7 +50,7 @@ nvf0_grctx_init_unk40xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk44xx[] = {
        { 0x404404,  12, 0x04, 0x00000000 },
        { 0x404438,   1, 0x04, 0x00000000 },
@@ -62,7 +62,7 @@ nvf0_grctx_init_unk44xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk5bxx[] = {
        { 0x405b00,   1, 0x04, 0x00000000 },
        { 0x405b10,   1, 0x04, 0x00001000 },
@@ -70,7 +70,7 @@ nvf0_grctx_init_unk5bxx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk60xx[] = {
        { 0x406020,   1, 0x04, 0x034103c1 },
        { 0x406028,   4, 0x04, 0x00000001 },
@@ -286,7 +286,6 @@ nvf0_grctx_init_hub[] = {
        nvf0_grctx_init_unk64xx,
        nve4_grctx_init_unk80xx,
        nvf0_grctx_init_unk88xx,
-       nvd9_grctx_init_rop,
        NULL
 };
 
index 5d24b6de16cce636e3db922c7c81d09018d9f2cc..e148961b8075e96be5ab2f1b86ebc7170676db4e 100644 (file)
@@ -38,7 +38,7 @@ queue_put:
        cmpu b32 $r8 $r9
        bra ne #queue_put_next
                mov $r15 E_CMD_OVERFLOW
-               call #error
+               call(error)
                ret
 
        // store cmd/data on queue
@@ -92,18 +92,16 @@ queue_get_done:
 // Out: $r15 value
 //
 nv_rd32:
-       mov $r11 0x728
-       shl b32 $r11 6
        mov b32 $r12 $r14
        bset $r12 31                    // MMIO_CTRL_PENDING
-       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
        nv_rd32_wait:
-               iord $r12 I[$r11 + 0x000]
+               nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
                xbit $r12 $r12 31
                bra ne #nv_rd32_wait
        mov $r10 6                      // DONE_MMIO_RD
-       call #wait_doneo
-       iord $r15 I[$r11 + 0x100]       // MMIO_RDVAL
+       call(wait_doneo)
+       nv_iord($r15, NV_PGRAPH_FECS_MMIO_RDVAL, 0)
        ret
 
 // nv_wr32 - write 32-bit value to nv register
@@ -112,37 +110,17 @@ nv_rd32:
 //      $r15 value
 //
 nv_wr32:
-       mov $r11 0x728
-       shl b32 $r11 6
-       iowr I[$r11 + 0x200] $r15       // MMIO_WRVAL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_WRVAL, 0, $r15)
        mov b32 $r12 $r14
        bset $r12 31                    // MMIO_CTRL_PENDING
        bset $r12 30                    // MMIO_CTRL_WRITE
-       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
        nv_wr32_wait:
-               iord $r12 I[$r11 + 0x000]
+               nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
                xbit $r12 $r12 31
                bra ne #nv_wr32_wait
        ret
 
-// (re)set watchdog timer
-//
-// In : $r15 timeout
-//
-watchdog_reset:
-       mov $r8 0x430
-       shl b32 $r8 6
-       bset $r15 31
-       iowr I[$r8 + 0x000] $r15
-       ret
-
-// clear watchdog timer
-watchdog_clear:
-       mov $r8 0x430
-       shl b32 $r8 6
-       iowr I[$r8 + 0x000] $r0
-       ret
-
 // wait_donez - wait on FUC_DONE bit to become clear
 //
 // In : $r10 bit to wait on
@@ -163,13 +141,9 @@ wait_donez:
 //
 wait_doneo:
        trace_set(T_WAIT);
-       mov $r8 0x818
-       shl b32 $r8 6
-       iowr I[$r8 + 0x000] $r10
+       nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)
        wait_doneo_e:
-               mov $r8 0x400
-               shl b32 $r8 6
-               iord $r8 I[$r8 + 0x000]
+               nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)
                xbit $r8 $r8 $r10
                bra e #wait_doneo_e
        trace_clr(T_WAIT)
@@ -209,21 +183,18 @@ mmctx_size:
 //
 mmctx_xfer:
        trace_set(T_MMCTX)
-       mov $r8 0x710
-       shl b32 $r8 6
        clear b32 $r9
        or $r11 $r11
        bra e #mmctx_base_disabled
-               iowr I[$r8 + 0x000] $r11        // MMCTX_BASE
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_BASE, 0, $r11)
                bset $r9 0                      // BASE_EN
        mmctx_base_disabled:
        or $r14 $r14
        bra e #mmctx_multi_disabled
-               iowr I[$r8 + 0x200] $r14        // MMCTX_MULTI_STRIDE
-               iowr I[$r8 + 0x300] $r15        // MMCTX_MULTI_MASK
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE, 0, $r14)
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_MASK, 0, $r15)
                bset $r9 1                      // MULTI_EN
        mmctx_multi_disabled:
-       add b32 $r8 0x100
 
        xbit $r11 $r10 0
        shl b32 $r11 16                 // DIR
@@ -231,20 +202,20 @@ mmctx_xfer:
        xbit $r14 $r10 1
        shl b32 $r14 17
        or $r11 $r14                    // START_TRIGGER
-       iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
 
        // loop over the mmio list, and send requests to the hw
        mmctx_exec_loop:
                // wait for space in mmctx queue
                mmctx_wait_free:
-                       iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+                       nv_iord($r14, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        and $r14 0x1f
                        bra e #mmctx_wait_free
 
                // queue up an entry
                ld b32 $r14 D[$r12]
                or $r14 $r9
-               iowr I[$r8 + 0x300] $r14
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_QUEUE, 0, $r14)
                add b32 $r12 4
                cmpu b32 $r12 $r13
                bra ne #mmctx_exec_loop
@@ -253,22 +224,22 @@ mmctx_xfer:
        bra ne #mmctx_stop
                // wait for queue to empty
                mmctx_fini_wait:
-                       iord $r11 I[$r8 + 0x000]        // MMCTX_CTRL
+                       nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        and $r11 0x1f
                        cmpu b32 $r11 0x10
                        bra ne #mmctx_fini_wait
                mov $r10 2                              // DONE_MMCTX
-               call #wait_donez
+               call(wait_donez)
                bra #mmctx_done
        mmctx_stop:
                xbit $r11 $r10 0
                shl b32 $r11 16                 // DIR
                bset $r11 12                    // QLIMIT = 0x10
                bset $r11 18                    // STOP_TRIGGER
-               iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
                mmctx_stop_wait:
                        // wait for STOP_TRIGGER to clear
-                       iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+                       nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        xbit $r11 $r11 18
                        bra ne #mmctx_stop_wait
        mmctx_done:
@@ -280,28 +251,24 @@ mmctx_xfer:
 strand_wait:
        push $r10
        mov $r10 2
-       call #wait_donez
+       call(wait_donez)
        pop $r10
        ret
 
 // unknown - call before issuing strand commands
 //
 strand_pre:
-       mov $r8 0x4afc
-       sethi $r8 0x20000
-       mov $r9 0xc
-       iowr I[$r8] $r9
-       call #strand_wait
+       mov $r9 NV_PGRAPH_FECS_STRAND_CMD_ENABLE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+       call(strand_wait)
        ret
 
 // unknown - call after issuing strand commands
 //
 strand_post:
-       mov $r8 0x4afc
-       sethi $r8 0x20000
-       mov $r9 0xd
-       iowr I[$r8] $r9
-       call #strand_wait
+       mov $r9 NV_PGRAPH_FECS_STRAND_CMD_DISABLE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+       call(strand_wait)
        ret
 
 // Selects strand set?!
@@ -309,18 +276,14 @@ strand_post:
 // In: $r14 id
 //
 strand_set:
-       mov $r10 0x4ffc
-       sethi $r10 0x20000
-       sub b32 $r11 $r10 0x500
        mov $r12 0xf
-       iowr I[$r10 + 0x000] $r12               // 0x93c = 0xf
-       mov $r12 0xb
-       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xb
-       call #strand_wait
-       iowr I[$r10 + 0x000] $r14               // 0x93c = <id>
-       mov $r12 0xa
-       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xa
-       call #strand_wait
+       nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r14)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
        ret
 
 // Initialise strand context data
@@ -332,30 +295,27 @@ strand_set:
 //
 strand_ctx_init:
        trace_set(T_STRINIT)
-       call #strand_pre
+       call(strand_pre)
        mov $r14 3
-       call #strand_set
-       mov $r10 0x46fc
-       sethi $r10 0x20000
-       add b32 $r11 $r10 0x400
-       iowr I[$r10 + 0x100] $r0        // STRAND_FIRST_GENE = 0
-       mov $r12 1
-       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_FIRST_GENE
-       call #strand_wait
+       call(strand_set)
+
+       clear b32 $r12
+       nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_SEEK
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
        sub b32 $r12 $r0 1
-       iowr I[$r10 + 0x000] $r12       // STRAND_GENE_CNT = 0xffffffff
-       mov $r12 2
-       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_GENE_CNT
-       call #strand_wait
-       call #strand_post
+       nv_iowr(NV_PGRAPH_FECS_STRAND_DATA, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_GET_INFO
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
+       call(strand_post)
 
        // read the size of each strand, poke the context offset of
        // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
        // about it later then.
-       mov $r8 0x880
-       shl b32 $r8 6
-       iord $r9 I[$r8 + 0x000]         // STRANDS
-       add b32 $r8 0x2200
+       nv_mkio($r8, NV_PGRAPH_FECS_STRAND_SAVE_SWBASE, 0x00)
+       nv_iord($r9, NV_PGRAPH_FECS_STRANDS_CNT, 0x00)
        shr b32 $r14 $r15 8
        ctx_init_strand_loop:
                iowr I[$r8 + 0x000] $r14        // STRAND_SAVE_SWBASE
index 5547c1b3f4f29414a1334e2a7d5cae9f7452e998..96cbcea3b2c96aa71f2c7ef3d59b3d3184a67e17 100644 (file)
@@ -58,12 +58,9 @@ mmio_list_base:
 //
 error:
        push $r14
-       mov $r14 -0x67ec        // 0x9814
-       sethi $r14 0x400000
-       call #nv_wr32           // HUB_CTXCTL_CC_SCRATCH[5] = error code
-       add b32 $r14 0x41c
+       nv_wr32(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), $r15)
        mov $r15 1
-       call #nv_wr32           // HUB_CTXCTL_INTR_UP_SET
+       nv_wr32(NV_PGRAPH_FECS_INTR_UP_SET, $r15)
        pop $r14
        ret
 
@@ -84,46 +81,40 @@ init:
        mov $sp $r0
 
        // enable fifo access
-       mov $r1 0x1200
-       mov $r2 2
-       iowr I[$r1 + 0x000] $r2         // FIFO_ENABLE
+       mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_ACCESS, 0, $r2)
 
        // setup i0 handler, and route all interrupts to it
        mov $r1 #ih
        mov $iv0 $r1
-       mov $r1 0x400
-       iowr I[$r1 + 0x300] $r0         // INTR_DISPATCH
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE, 0, $r0)
 
        // enable fifo interrupt
-       mov $r2 4
-       iowr I[$r1 + 0x000] $r2         // INTR_EN_SET
+       mov $r2 NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET, 0, $r2)
 
        // enable interrupts
        bset $flags ie0
 
        // figure out which GPC we are, and how many TPCs we have
-       mov $r1 0x608
-       shl b32 $r1 6
-       iord $r2 I[$r1 + 0x000]         // UNITS
+       nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)
        mov $r3 1
        and $r2 0x1f
        shl b32 $r3 $r2
        sub b32 $r3 1
        st b32 D[$r0 + #tpc_count] $r2
        st b32 D[$r0 + #tpc_mask] $r3
-       add b32 $r1 0x400
-       iord $r2 I[$r1 + 0x000]         // MYINDEX
+       nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)
        st b32 D[$r0 + #gpc_id] $r2
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
        // figure out which, and how many, UNKs are actually present
-       mov $r14 0x0c30
-       sethi $r14 0x500000
+       imm32($r14, 0x500c30)
        clear b32 $r2
        clear b32 $r3
        clear b32 $r4
        init_unk_loop:
-               call #nv_rd32
+               call(nv_rd32)
                cmp b32 $r15 0
                bra z #init_unk_next
                        mov $r15 1
@@ -146,23 +137,21 @@ init:
 
        // set mmctx base addresses now so we don't have to do it later,
        // they don't currently ever change
-       mov $r4 0x700
-       shl b32 $r4 6
        shr b32 $r5 $r2 8
-       iowr I[$r4 + 0x000] $r5         // MMCTX_SAVE_SWBASE
-       iowr I[$r4 + 0x100] $r5         // MMCTX_LOAD_SWBASE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE, 0, $r5)
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE, 0, $r5)
 
        // calculate GPC mmio context size
        ld b32 $r14 D[$r0 + #gpc_mmio_list_head]
        ld b32 $r15 D[$r0 + #gpc_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        add b32 $r2 $r15
        add b32 $r3 $r15
 
        // calculate per-TPC mmio context size
        ld b32 $r14 D[$r0 + #tpc_mmio_list_head]
        ld b32 $r15 D[$r0 + #tpc_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        ld b32 $r14 D[$r0 + #tpc_count]
        mulu $r14 $r15
        add b32 $r2 $r14
@@ -172,7 +161,7 @@ init:
        // calculate per-UNK mmio context size
        ld b32 $r14 D[$r0 + #unk_mmio_list_head]
        ld b32 $r15 D[$r0 + #unk_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        ld b32 $r14 D[$r0 + #unk_count]
        mulu $r14 $r15
        add b32 $r2 $r14
@@ -180,9 +169,8 @@ init:
 #endif
 
        // round up base/size to 256 byte boundary (for strand SWBASE)
-       add b32 $r4 0x1300
        shr b32 $r3 2
-       iowr I[$r4 + 0x000] $r3         // MMCTX_LOAD_COUNT, wtf for?!?
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT, 0, $r3) // wtf for?!
        shr b32 $r2 8
        shr b32 $r3 6
        add b32 $r2 1
@@ -192,7 +180,7 @@ init:
 
        // calculate size of strand context data
        mov b32 $r15 $r2
-       call #strand_ctx_init
+       call(strand_ctx_init)
        add b32 $r3 $r15
 
        // save context size, and tell HUB we're done
@@ -208,7 +196,7 @@ main:
        bset $flags $p0
        sleep $p0
        mov $r13 #cmd_queue
-       call #queue_get
+       call(queue_get)
        bra $p1 #main
 
        // 0x0000-0x0003 are all context transfers
@@ -224,13 +212,13 @@ main:
                or $r1 $r14
                mov $flags $r1
                // transfer context data
-               call #ctx_xfer
+               call(ctx_xfer)
                bra #main
 
        main_not_ctx_xfer:
        shl b32 $r15 $r14 16
        or $r15 E_BAD_COMMAND
-       call #error
+       call(error)
        bra #main
 
 // interrupt handler
@@ -247,22 +235,20 @@ ih:
        clear b32 $r0
 
        // incoming fifo command?
-       iord $r10 I[$r0 + 0x200]        // INTR
-       and $r11 $r10 0x00000004
+       nv_iord($r10, NV_PGRAPH_GPCX_GPCCS_INTR, 0)
+       and $r11 $r10 NV_PGRAPH_GPCX_GPCCS_INTR_FIFO
        bra e #ih_no_fifo
                // queue incoming fifo command for later processing
-               mov $r11 0x1900
                mov $r13 #cmd_queue
-               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
-               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
-               call #queue_put
-               add b32 $r11 0x400
+               nv_iord($r14, NV_PGRAPH_GPCX_GPCCS_FIFO_CMD, 0)
+               nv_iord($r15, NV_PGRAPH_GPCX_GPCCS_FIFO_DATA, 0)
+               call(queue_put)
                mov $r14 1
-               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+               nv_iowr(NV_PGRAPH_GPCX_GPCCS_FIFO_ACK, 0, $r14)
 
        // ack, and wake up main()
        ih_no_fifo:
-       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ACK, 0, $r10)
 
        pop $r15
        pop $r14
@@ -283,9 +269,7 @@ hub_barrier_done:
        mov $r15 1
        ld b32 $r14 D[$r0 + #gpc_id]
        shl b32 $r15 $r14
-       mov $r14 -0x6be8        // 0x409418 - HUB_BAR_SET
-       sethi $r14 0x400000
-       call #nv_wr32
+       nv_wr32(0x409418, $r15) // 0x409418 - HUB_BAR_SET
        ret
 
 // Disables various things, waits a bit, and re-enables them..
@@ -295,16 +279,15 @@ hub_barrier_done:
 // funny things happen.
 //
 ctx_redswitch:
-       mov $r14 0x614
-       shl b32 $r14 6
-       mov $r15 0x020
-       iowr I[$r14] $r15       // GPC_RED_SWITCH = POWER
-       mov $r15 8
+       mov $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
+       mov $r14 8
        ctx_redswitch_delay:
-               sub b32 $r15 1
+               sub b32 $r14 1
                bra ne #ctx_redswitch_delay
-       mov $r15 0xa20
-       iowr I[$r14] $r15       // GPC_RED_SWITCH = UNK11, ENABLE, POWER
+       or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11
+       or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
        ret
 
 // Transfer GPC context data between GPU and storage area
@@ -317,46 +300,37 @@ ctx_redswitch:
 //
 ctx_xfer:
        // set context base address
-       mov $r1 0xa04
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r15// MEM_BASE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)
        bra not $p1 #ctx_xfer_not_load
-               call #ctx_redswitch
+               call(ctx_redswitch)
        ctx_xfer_not_load:
 
        // strands
-       mov $r1 0x4afc
-       sethi $r1 0x20000
-       mov $r2 0xc
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
-       call #strand_wait
-       mov $r2 0x47fc
-       sethi $r2 0x20000
-       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
-       xbit $r2 $flags $p1
-       add b32 $r2 3
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+       call(strand_pre)
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT, 0x3f, $r2)
+       xbit $r2 $flags $p1     // SAVE/LOAD
+       add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)
 
        // mmio context
        xbit $r10 $flags $p1    // direction
        or $r10 2               // first
-       mov $r11 0x0000
-       sethi $r11 0x500000
+       imm32($r11,0x500000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn
        ld b32 $r12 D[$r0 + #gpc_mmio_list_head]
        ld b32 $r13 D[$r0 + #gpc_mmio_list_tail]
        mov $r14 0              // not multi
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
        // per-TPC mmio context
        xbit $r10 $flags $p1    // direction
 #if !NV_PGRAPH_GPCX_UNK__SIZE
        or $r10 4               // last
 #endif
-       mov $r11 0x4000
-       sethi $r11 0x500000     // base = NV_PGRAPH_GPC0_TPC0
+       imm32($r11, 0x504000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn_TPC0
@@ -364,14 +338,13 @@ ctx_xfer:
        ld b32 $r13 D[$r0 + #tpc_mmio_list_tail]
        ld b32 $r15 D[$r0 + #tpc_mask]
        mov $r14 0x800          // stride = 0x800
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
        // per-UNK mmio context
        xbit $r10 $flags $p1    // direction
        or $r10 4               // last
-       mov $r11 0x3000
-       sethi $r11 0x500000     // base = NV_PGRAPH_GPC0_UNK0
+       imm32($r11, 0x503000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn_UNK0
@@ -379,11 +352,11 @@ ctx_xfer:
        ld b32 $r13 D[$r0 + #unk_mmio_list_tail]
        ld b32 $r15 D[$r0 + #unk_mask]
        mov $r14 0x200          // stride = 0x200
-       call #mmctx_xfer
+       call(mmctx_xfer)
 #endif
 
        // wait for strands to finish
-       call #strand_wait
+       call(strand_wait)
 
        // if load, or a save without a load following, do some
        // unknown stuff that's done after finishing a block of
@@ -391,14 +364,10 @@ ctx_xfer:
        bra $p1 #ctx_xfer_post
        bra not $p2 #ctx_xfer_done
        ctx_xfer_post:
-               mov $r1 0x4afc
-               sethi $r1 0x20000
-               mov $r2 0xd
-               iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0d
-               call #strand_wait
+               call(strand_post)
 
        // mark completion in HUB's barrier
        ctx_xfer_done:
-       call #hub_barrier_done
+       call(hub_barrier_done)
        ret
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5
new file mode 100644 (file)
index 0000000..bd30262
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000001
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grgpc_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "gpc.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grgpc_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "gpc.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
new file mode 100644 (file)
index 0000000..27dc128
--- /dev/null
@@ -0,0 +1,473 @@
+uint32_t nv108_grgpc_data[] = {
+/* 0x0000: gpc_mmio_list_head */
+       0x0000006c,
+/* 0x0004: gpc_mmio_list_tail */
+/* 0x0004: tpc_mmio_list_head */
+       0x0000006c,
+/* 0x0008: tpc_mmio_list_tail */
+/* 0x0008: unk_mmio_list_head */
+       0x0000006c,
+/* 0x000c: unk_mmio_list_tail */
+       0x0000006c,
+/* 0x0010: gpc_id */
+       0x00000000,
+/* 0x0014: tpc_count */
+       0x00000000,
+/* 0x0018: tpc_mask */
+       0x00000000,
+/* 0x001c: unk_count */
+       0x00000000,
+/* 0x0020: unk_mask */
+       0x00000000,
+/* 0x0024: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+uint32_t nv108_grgpc_code[] = {
+       0x03140ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e02,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0xffb2e0f9,
+       0x4098148e,
+       0x00008f7e,
+       0xffb2010f,
+       0x409c1c8e,
+       0x00008f7e,
+       0x00f8e0fc,
+/* 0x0314: init */
+       0x04fe04bd,
+       0x40020200,
+       0x02f61200,
+       0x4104bd00,
+       0x10fe0465,
+       0x07004000,
+       0xbd0000f6,
+       0x40040204,
+       0x02f60400,
+       0xf404bd00,
+       0x00821031,
+       0x22cf0182,
+       0xf0010300,
+       0x32bb1f24,
+       0x0132b604,
+       0xb50502b5,
+       0x00820603,
+       0x22cf0186,
+       0x0402b500,
+       0x500c308e,
+       0x34bd24bd,
+/* 0x036a: init_unk_loop */
+       0x657e44bd,
+       0xf6b00000,
+       0x0e0bf400,
+       0xf2bb010f,
+       0x054ffd04,
+/* 0x037f: init_unk_next */
+       0xb60130b6,
+       0xe0b60120,
+       0x0126b004,
+/* 0x038b: init_unk_done */
+       0xb5e21bf4,
+       0x04b50703,
+       0x01008208,
+       0x0022cf02,
+       0x259534bd,
+       0xc0008008,
+       0x0005f601,
+       0x008004bd,
+       0x05f601c1,
+       0x9804bd00,
+       0x0f98000e,
+       0x01207e01,
+       0x002fbb00,
+       0x98003fbb,
+       0x0f98010e,
+       0x01207e02,
+       0x050e9800,
+       0xbb00effd,
+       0x3ebb002e,
+       0x020e9800,
+       0x7e030f98,
+       0x98000120,
+       0xeffd070e,
+       0x002ebb00,
+       0xb6003ebb,
+       0x00800235,
+       0x03f601d3,
+       0xb604bd00,
+       0x35b60825,
+       0x0120b606,
+       0xb60130b6,
+       0x34b60824,
+       0x7e2fb208,
+       0xbb000268,
+       0x0080003f,
+       0x03f60201,
+       0xbd04bd00,
+       0x1f29f024,
+       0x02300080,
+       0xbd0002f6,
+/* 0x0429: main */
+       0x0031f404,
+       0x0d0028f4,
+       0x00377e24,
+       0xf401f400,
+       0xf404e4b0,
+       0x81fe1d18,
+       0xbd060201,
+       0x0412fd20,
+       0xfd01e4b6,
+       0x18fe051e,
+       0x04fc7e00,
+       0xd40ef400,
+/* 0x0458: main_not_ctx_xfer */
+       0xf010ef94,
+       0xf87e01f5,
+       0x0ef40002,
+/* 0x0465: ih */
+       0xfe80f9c7,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0x004a04bd,
+       0x00aacf02,
+       0xf404abc4,
+       0x240d1f0b,
+       0xcf1a004e,
+       0x004f00ee,
+       0x00ffcf19,
+       0x0000047e,
+       0x0040010e,
+       0x000ef61d,
+/* 0x04a2: ih_no_fifo */
+       0x004004bd,
+       0x000af601,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x04c2: hub_barrier_done */
+       0x010f01f8,
+       0xbb040e98,
+       0xffb204fe,
+       0x4094188e,
+       0x00008f7e,
+/* 0x04d6: ctx_redswitch */
+       0x200f00f8,
+       0x01850080,
+       0xbd000ff6,
+/* 0x04e3: ctx_redswitch_delay */
+       0xb6080e04,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x85008002,
+       0x000ff601,
+       0x00f804bd,
+/* 0x04fc: ctx_xfer */
+       0x02810080,
+       0xbd000ff6,
+       0x0711f404,
+       0x0004d67e,
+/* 0x050c: ctx_xfer_not_load */
+       0x0002167e,
+       0xfc8024bd,
+       0x02f60247,
+       0xf004bd00,
+       0x20b6012c,
+       0x4afc8003,
+       0x0002f602,
+       0xacf004bd,
+       0x02a5f001,
+       0x5000008b,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x000c9800,
+       0x0e010d98,
+       0x013d7e00,
+       0x01acf000,
+       0x5040008b,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0x004e060f,
+       0x013d7e08,
+       0x01acf000,
+       0x8b04a5f0,
+       0x98503000,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98020c98,
+       0x0f98030d,
+       0x02004e08,
+       0x00013d7e,
+       0x00020a7e,
+       0xf40601f4,
+/* 0x0596: ctx_xfer_post */
+       0x277e0712,
+/* 0x059a: ctx_xfer_done */
+       0xc27e0002,
+       0x00f80004,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index f2b0dea80116fd7b42de0a2d1ff8fad4dbd26b96..0e7b01efae8d2979cdffac5bbf4e4a4030580d2d 100644 (file)
@@ -37,14 +37,14 @@ uint32_t nvc0_grgpc_data[] = {
 };
 
 uint32_t nvc0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -68,184 +68,214 @@ uint32_t nvc0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -259,167 +289,199 @@ uint32_t nvc0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe042617,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0xd517f104,
+       0x0010fe04,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x40b7003e,
-       0x35b61300,
-       0x0043d002,
-       0xb60825b6,
-       0x20b60635,
-       0x0130b601,
-       0xb60824b6,
-       0x2fb90834,
-       0x7121f502,
-       0x003fbb02,
-       0x010007f1,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
+       0x2ebb00ef,
+       0x003ebb00,
+       0xf10235b6,
+       0xf0d30007,
+       0x03d00103,
+       0xb604bd00,
+       0x35b60825,
+       0x0120b606,
+       0xb60130b6,
+       0x34b60824,
+       0x022fb908,
+       0x02d321f5,
+       0xf1003fbb,
+       0xf0010007,
+       0x03d00203,
+       0xbd04bd00,
+       0x1f29f024,
+       0x080007f1,
        0xd00203f0,
-       0x04bd0003,
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-/* 0x03e9: main */
-       0x0031f404,
-       0xf00028f4,
-       0x21f41cd7,
-       0xf401f439,
-       0xf404e4b0,
-       0x81fe1e18,
-       0x0627f001,
-       0x12fd20bd,
-       0x01e4b604,
-       0xfe051efd,
-       0x21f50018,
-       0x0ef404ad,
-/* 0x0419: main_not_ctx_xfer */
-       0x10ef94d3,
-       0xf501f5f0,
-       0xf402fe21,
-/* 0x0426: ih */
-       0x80f9c60e,
-       0xf90188fe,
-       0xf990f980,
-       0xf9b0f9a0,
-       0xf9e0f9d0,
-       0xcf04bdf0,
-       0xabc4800a,
-       0x1d0bf404,
-       0x1900b7f1,
-       0xcf1cd7f0,
-       0xbfcf40be,
+       0x04bd0002,
+/* 0x0498: main */
+       0xf40031f4,
+       0xd7f00028,
+       0x3921f41c,
+       0xb0f401f4,
+       0x18f404e4,
+       0x0181fe1e,
+       0xbd0627f0,
+       0x0412fd20,
+       0xfd01e4b6,
+       0x18fe051e,
+       0x8d21f500,
+       0xd30ef405,
+/* 0x04c8: main_not_ctx_xfer */
+       0xf010ef94,
+       0x21f501f5,
+       0x0ef4037e,
+/* 0x04d5: ih */
+       0xfe80f9c6,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0xa7f104bd,
+       0xa3f00200,
+       0x00aacf00,
+       0xf404abc4,
+       0xd7f02c0b,
+       0x00e7f11c,
+       0x00e3f01a,
+       0xf100eecf,
+       0xf01900f7,
+       0xffcf00f3,
        0x0421f400,
-       0x0400b0b7,
-       0xd001e7f0,
-/* 0x045e: ih_no_fifo */
-       0x0ad000be,
-       0xfcf0fc40,
-       0xfcd0fce0,
-       0xfca0fcb0,
-       0xfe80fc90,
-       0x80fc0088,
-       0xf80032f4,
-/* 0x0479: hub_barrier_done */
-       0x01f7f001,
-       0xbb040e98,
-       0xe7f104fe,
-       0xe3f09418,
-       0x8d21f440,
-/* 0x048e: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x20f7f006,
-       0xf000efd0,
-/* 0x049e: ctx_redswitch_delay */
-       0xf2b608f7,
-       0xfd1bf401,
-       0x0a20f7f1,
-       0xf800efd0,
-/* 0x04ad: ctx_xfer */
-       0x0417f100,
-       0x0614b60a,
-       0xf4001fd0,
-       0x21f50711,
-/* 0x04be: ctx_xfer_not_load */
-       0x17f1048e,
-       0x13f04afc,
-       0x0c27f002,
-       0xf50012d0,
-       0xf1021521,
-       0xf047fc27,
-       0x20d00223,
-       0x012cf000,
-       0xd00320b6,
-       0xacf00012,
-       0x02a5f001,
-       0xf000b7f0,
-       0x0c9850b3,
-       0x0fc4b604,
-       0x9800bcbb,
-       0x0d98000c,
-       0x00e7f001,
-       0x016621f5,
+       0xf101e7f0,
+       0xf01d0007,
+       0x0ed00003,
+/* 0x0523: ih_no_fifo */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
+       0xfce0fcf0,
+       0xfcb0fcd0,
+       0xfc90fca0,
+       0x0088fe80,
+       0x32f480fc,
+/* 0x0547: hub_barrier_done */
+       0xf001f800,
+       0x0e9801f7,
+       0x04febb04,
+       0xf102ffb9,
+       0xf09418e7,
+       0x21f440e3,
+/* 0x055f: ctx_redswitch */
+       0xf000f89d,
+       0x07f120f7,
+       0x03f08500,
+       0x000fd001,
+       0xe7f004bd,
+/* 0x0571: ctx_redswitch_delay */
+       0x01e2b608,
+       0xf1fd1bf4,
+       0xf10800f5,
+       0xf10200f5,
+       0xf0850007,
+       0x0fd00103,
+       0xf804bd00,
+/* 0x058d: ctx_xfer */
+       0x0007f100,
+       0x0203f081,
+       0xbd000fd0,
+       0x0711f404,
+       0x055f21f5,
+/* 0x05a0: ctx_xfer_not_load */
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
+       0x0320b601,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xf001acf0,
-       0xb7f104a5,
-       0xb3f04000,
+       0xb7f102a5,
+       0xb3f00000,
        0x040c9850,
        0xbb0fc4b6,
        0x0c9800bc,
-       0x020d9801,
-       0xf1060f98,
-       0xf50800e7,
-       0xf5016621,
-       0xf4021521,
-       0x12f40601,
-/* 0x0535: ctx_xfer_post */
-       0xfc17f114,
-       0x0213f04a,
-       0xd00d27f0,
-       0x21f50012,
-/* 0x0546: ctx_xfer_done */
-       0x21f50215,
-       0x00f80479,
+       0x010d9800,
+       0xf500e7f0,
+       0xf0016f21,
+       0xa5f001ac,
+       0x00b7f104,
+       0x50b3f040,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0xe7f1060f,
+       0x21f50800,
+       0x21f5016f,
+       0x01f4025e,
+       0x0712f406,
+/* 0x0618: ctx_xfer_post */
+       0x027f21f5,
+/* 0x061c: ctx_xfer_done */
+       0x054721f5,
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index dd346c2a16245849b773e382bad75499a85aa00a..84dd32db28a02cff0118eec2bae837ddf56dcc90 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nvd7_grgpc_data[] = {
 };
 
 uint32_t nvd7_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvd7_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvd7_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40126b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40126,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0080007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f00800,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index 7ff5ef6b08048e0d0b12d8b1cf788f97d4f01143..b6da800ee9c2ddbd2baae4cf5812c681c09fccc6 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nve0_grgpc_data[] = {
 };
 
 uint32_t nve0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nve0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nve0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40126b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40126,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0080007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f00800,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index f870507be88019cd9167d82a2fd85b3626f820d3..6316ebaf5d9a581dae8ac9e5a6d0464d0f8ec478 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nvf0_grgpc_data[] = {
 };
 
 uint32_t nvf0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvf0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f03700,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f03700,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f037,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf0370007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f03700,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvf0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40226b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40226,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0300007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f03000,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index b82d2ae8991742e7eb58902f4935663590fbe795..c8ddb8d71b915c668c7b116f1b7f9cf9547289b3 100644 (file)
@@ -68,60 +68,57 @@ error:
 //
 init:
        clear b32 $r0
-       mov $sp $r0
        mov $xdbase $r0
 
+       // setup stack
+       nv_iord($r1, NV_PGRAPH_FECS_CAPS, 0)
+       extr $r1 $r1 9:17
+       shl b32 $r1 8
+       mov $sp $r1
+
        // enable fifo access
-       mov $r1 0x1200
-       mov $r2 2
-       iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
+       mov $r2 NV_PGRAPH_FECS_ACCESS_FIFO
+       nv_iowr(NV_PGRAPH_FECS_ACCESS, 0, $r2)
 
        // setup i0 handler, and route all interrupts to it
        mov $r1 #ih
        mov $iv0 $r1
-       mov $r1 0x400
-       iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
 
-       // route HUB_CHANNEL_SWITCH to fuc interrupt 8
-       mov $r3 0x404
-       shl b32 $r3 6
-       mov $r2 0x2003          // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
-       iowr I[$r3 + 0x000] $r2
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_INTR_ROUTE, 0, $r2)
+
+       // route HUB_CHSW_PULSE to fuc interrupt 8
+       mov $r2 0x2003          // { HUB_CHSW_PULSE, ZERO } -> intr 8
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 0, $r2)
 
        // not sure what these are, route them because NVIDIA does, and
        // the IRQ handler will signal the host if we ever get one.. we
        // may find out if/why we need to handle these if so..
        //
-       mov $r2 0x2004
-       iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
-       mov $r2 0x200b
-       iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
-       mov $r2 0x200c
-       iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+       mov $r2 0x2004          // { 0x04, ZERO } -> intr 9
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 1, $r2)
+       mov $r2 0x200b          // { HUB_FIRMWARE_MTHD, ZERO } -> intr 10
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 2, $r2)
+       mov $r2 0x200c          // { 0x0c, ZERO } -> intr 15
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 7, $r2)
 
        // enable all INTR_UP interrupts
-       mov $r2 0xc24
-       shl b32 $r2 6
-       not b32 $r3 $r0
-       iowr I[$r2] $r3
+       sub b32 $r3 $r0 1
+       nv_iowr(NV_PGRAPH_FECS_INTR_UP_EN, 0, $r3)
 
-       // enable fifo, ctxsw, 9, 10, 15 interrupts
-       mov $r2 -0x78fc         // 0x8704
-       sethi $r2 0
-       iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
+       // enable fifo, ctxsw, 9, fwmthd, 15 interrupts
+       imm32($r2, 0x8704)
+       nv_iowr(NV_PGRAPH_FECS_INTR_EN_SET, 0, $r2)
 
        // fifo level triggered, rest edge
-       sub b32 $r1 0x100
-       mov $r2 4
-       iowr I[$r1] $r2
+       mov $r2 NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL
+       nv_iowr(NV_PGRAPH_FECS_INTR_MODE, 0, $r2)
 
        // enable interrupts
        bset $flags ie0
 
        // fetch enabled GPC/ROP counts
-       mov $r14 -0x69fc        // 0x409604
-       sethi $r14 0x400000
-       call #nv_rd32
+       nv_rd32($r14, 0x409604)
        extr $r1 $r15 16:20
        st b32 D[$r0 + #rop_count] $r1
        and $r15 0x1f
@@ -131,37 +128,40 @@ init:
        mov $r1 1
        shl b32 $r1 $r15
        sub b32 $r1 1
-       mov $r2 0x40c
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r1
-       iowr I[$r2 + 0x100] $r1
+       nv_iowr(NV_PGRAPH_FECS_BAR_MASK0, 0, $r1)
+       nv_iowr(NV_PGRAPH_FECS_BAR_MASK1, 0, $r1)
 
        // context size calculation, reserve first 256 bytes for use by fuc
        mov $r1 256
 
+       //
+       mov $r15 2
+       call(ctx_4170s)
+       call(ctx_4170w)
+       mov $r15 0x10
+       call(ctx_86c)
+
        // calculate size of mmio context data
        ld b32 $r14 D[$r0 + #hub_mmio_list_head]
        ld b32 $r15 D[$r0 + #hub_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
 
        // set mmctx base addresses now so we don't have to do it later,
        // they don't (currently) ever change
-       mov $r3 0x700
-       shl b32 $r3 6
        shr b32 $r4 $r1 8
-       iowr I[$r3 + 0x000] $r4         // MMCTX_SAVE_SWBASE
-       iowr I[$r3 + 0x100] $r4         // MMCTX_LOAD_SWBASE
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE, 0, $r4)
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE, 0, $r4)
        add b32 $r3 0x1300
        add b32 $r1 $r15
        shr b32 $r15 2
-       iowr I[$r3 + 0x000] $r15        // MMCTX_LOAD_COUNT, wtf for?!?
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_COUNT, 0, $r15) // wtf??
 
        // strands, base offset needs to be aligned to 256 bytes
        shr b32 $r1 8
        add b32 $r1 1
        shl b32 $r1 8
        mov b32 $r15 $r1
-       call #strand_ctx_init
+       call(strand_ctx_init)
        add b32 $r1 $r15
 
        // initialise each GPC in sequence by passing in the offset of its
@@ -173,30 +173,29 @@ init:
        // in GPCn_CC_SCRATCH[1]
        //
        ld b32 $r3 D[$r0 + #gpc_count]
-       mov $r4 0x2000
-       sethi $r4 0x500000
+       imm32($r4, 0x502000)
        init_gpc:
                // setup, and start GPC ucode running
                add b32 $r14 $r4 0x804
                mov b32 $r15 $r1
-               call #nv_wr32                   // CC_SCRATCH[1] = ctx offset
+               call(nv_wr32)                   // CC_SCRATCH[1] = ctx offset
                add b32 $r14 $r4 0x10c
                clear b32 $r15
-               call #nv_wr32
+               call(nv_wr32)
                add b32 $r14 $r4 0x104
-               call #nv_wr32                   // ENTRY
+               call(nv_wr32)                   // ENTRY
                add b32 $r14 $r4 0x100
                mov $r15 2                      // CTRL_START_TRIGGER
-               call #nv_wr32                   // CTRL
+               call(nv_wr32)                   // CTRL
 
                // wait for it to complete, and adjust context size
                add b32 $r14 $r4 0x800
                init_gpc_wait:
-                       call #nv_rd32
+                       call(nv_rd32)
                        xbit $r15 $r15 31
                        bra e #init_gpc_wait
                add b32 $r14 $r4 0x804
-               call #nv_rd32
+               call(nv_rd32)
                add b32 $r1 $r15
 
                // next!
@@ -204,6 +203,12 @@ init:
                sub b32 $r3 1
                bra ne #init_gpc
 
+       //
+       mov $r15 0
+       call(ctx_86c)
+       mov $r15 0
+       call(ctx_4170s)
+
        // save context size, and tell host we're ready
        nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(1), 0, $r1)
        clear b32 $r1
@@ -218,17 +223,15 @@ main:
        bset $flags $p0
        sleep $p0
        mov $r13 #cmd_queue
-       call #queue_get
+       call(queue_get)
        bra $p1 #main
 
        // context switch, requested by GPU?
        cmpu b32 $r14 0x4001
        bra ne #main_not_ctx_switch
                trace_set(T_AUTO)
-               mov $r1 0xb00
-               shl b32 $r1 6
-               iord $r2 I[$r1 + 0x100]         // CHAN_NEXT
-               iord $r1 I[$r1 + 0x000]         // CHAN_CUR
+               nv_iord($r1, NV_PGRAPH_FECS_CHAN_ADDR, 0)
+               nv_iord($r2, NV_PGRAPH_FECS_CHAN_NEXT, 0)
 
                xbit $r3 $r1 31
                bra e #chsw_no_prev
@@ -239,12 +242,12 @@ main:
                                trace_set(T_SAVE)
                                bclr $flags $p1
                                bset $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                trace_clr(T_SAVE);
                                pop $r2
                                trace_set(T_LOAD);
                                bset $flags $p1
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                trace_clr(T_LOAD);
                                bra #chsw_done
                        chsw_prev_no_next:
@@ -252,25 +255,21 @@ main:
                                mov b32 $r2 $r1
                                bclr $flags $p1
                                bclr $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                pop $r2
-                               mov $r1 0xb00
-                               shl b32 $r1 6
-                               iowr I[$r1] $r2
+                               nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
                                bra #chsw_done
                chsw_no_prev:
                        xbit $r3 $r2 31
                        bra e #chsw_done
                                bset $flags $p1
                                bclr $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
 
                // ack the context switch request
                chsw_done:
-               mov $r1 0xb0c
-               shl b32 $r1 6
-               mov $r2 1
-               iowr I[$r1 + 0x000] $r2         // 0x409b0c
+               mov $r2 NV_PGRAPH_FECS_CHSW_ACK
+               nv_iowr(NV_PGRAPH_FECS_CHSW, 0, $r2)
                trace_clr(T_AUTO)
                bra #main
 
@@ -279,7 +278,7 @@ main:
        cmpu b32 $r14 0x0001
        bra ne #main_not_ctx_chan
                mov b32 $r2 $r15
-               call #ctx_chan
+               call(ctx_chan)
                bra #main_done
 
        // request to store current channel context?
@@ -289,14 +288,14 @@ main:
                trace_set(T_SAVE)
                bclr $flags $p1
                bclr $flags $p2
-               call #ctx_xfer
+               call(ctx_xfer)
                trace_clr(T_SAVE)
                bra #main_done
 
        main_not_ctx_save:
                shl b32 $r15 $r14 16
                or $r15 E_BAD_COMMAND
-               call #error
+               call(error)
                bra #main
 
        main_done:
@@ -319,41 +318,46 @@ ih:
        clear b32 $r0
 
        // incoming fifo command?
-       iord $r10 I[$r0 + 0x200]        // INTR
-       and $r11 $r10 0x00000004
+       nv_iord($r10, NV_PGRAPH_FECS_INTR, 0)
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_FIFO
        bra e #ih_no_fifo
                // queue incoming fifo command for later processing
-               mov $r11 0x1900
                mov $r13 #cmd_queue
-               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
-               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
-               call #queue_put
+               nv_iord($r14, NV_PGRAPH_FECS_FIFO_CMD, 0)
+               nv_iord($r15, NV_PGRAPH_FECS_FIFO_DATA, 0)
+               call(queue_put)
                add b32 $r11 0x400
                mov $r14 1
-               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+               nv_iowr(NV_PGRAPH_FECS_FIFO_ACK, 0, $r14)
 
        // context switch request?
        ih_no_fifo:
-       and $r11 $r10 0x00000100
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_CHSW
        bra e #ih_no_ctxsw
                // enqueue a context switch for later processing
                mov $r13 #cmd_queue
                mov $r14 0x4001
-               call #queue_put
+               call(queue_put)
 
-       // anything we didn't handle, bring it to the host's attention
+       // firmware method?
        ih_no_ctxsw:
-       mov $r11 0x104
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_FWMTHD
+       bra e #ih_no_fwmthd
+               // none we handle, ack, and fall-through to unhandled
+               mov $r11 0x100
+               nv_wr32(0x400144, $r11)
+
+       // anything we didn't handle, bring it to the host's attention
+       ih_no_fwmthd:
+       mov $r11 0x104 // FIFO | CHSW
        not b32 $r11
        and $r11 $r10 $r11
        bra e #ih_no_other
-               mov $r10 0xc1c
-               shl b32 $r10 6
-               iowr I[$r10] $r11       // INTR_UP_SET
+               nv_iowr(NV_PGRAPH_FECS_INTR_UP_SET, 0, $r11)
 
        // ack, and wake up main()
        ih_no_other:
-       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+       nv_iowr(NV_PGRAPH_FECS_INTR_ACK, 0, $r10)
 
        pop $r15
        pop $r14
@@ -370,12 +374,10 @@ ih:
 #if CHIPSET < GK100
 // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
 ctx_4160s:
-       mov $r14 0x4160
-       sethi $r14 0x400000
        mov $r15 1
-       call #nv_wr32
+       nv_wr32(0x404160, $r15)
        ctx_4160s_wait:
-               call #nv_rd32
+               nv_rd32($r15, 0x404160)
                xbit $r15 $r15 4
                bra e #ctx_4160s_wait
        ret
@@ -384,10 +386,8 @@ ctx_4160s:
 // to hang with STATUS=0x00000007 until it's cleared.. fbcon can
 // still function with it set however...
 ctx_4160c:
-       mov $r14 0x4160
-       sethi $r14 0x400000
        clear b32 $r15
-       call #nv_wr32
+       nv_wr32(0x404160, $r15)
        ret
 #endif
 
@@ -396,18 +396,14 @@ ctx_4160c:
 // In: $r15 value to set 0x404170 to
 //
 ctx_4170s:
-       mov $r14 0x4170
-       sethi $r14 0x400000
        or $r15 0x10
-       call #nv_wr32
+       nv_wr32(0x404170, $r15)
        ret
 
 // Waits for a ctx_4170s() call to complete
 //
 ctx_4170w:
-       mov $r14 0x4170
-       sethi $r14 0x400000
-       call #nv_rd32
+       nv_rd32($r15, 0x404170)
        and $r15 0x10
        bra ne #ctx_4170w
        ret
@@ -419,16 +415,18 @@ ctx_4170w:
 // funny things happen.
 //
 ctx_redswitch:
-       mov $r14 0x614
-       shl b32 $r14 6
-       mov $r15 0x270
-       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+       mov $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN
+       nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
        mov $r15 8
        ctx_redswitch_delay:
                sub b32 $r15 1
                bra ne #ctx_redswitch_delay
-       mov $r15 0x770
-       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN
+       nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
        ret
 
 // Not a clue what this is for, except that unless the value is 0x10, the
@@ -437,15 +435,18 @@ ctx_redswitch:
 // In: $r15 value to set to (0x00/0x10 are used)
 //
 ctx_86c:
-       mov $r14 0x86c
-       shl b32 $r14 6
-       iowr I[$r14] $r15       // HUB(0x86c) = val
-       mov $r14 -0x75ec
-       sethi $r14 0x400000
-       call #nv_wr32           // ROP(0xa14) = val
-       mov $r14 -0x5794
-       sethi $r14 0x410000
-       call #nv_wr32           // GPC(0x86c) = val
+       nv_iowr(NV_PGRAPH_FECS_UNK86C, 0, $r15)
+       nv_wr32(0x408a14, $r15)
+       nv_wr32(NV_PGRAPH_GPCX_GPCCS_UNK86C, $r15)
+       ret
+
+// In: $r15 NV_PGRAPH_FECS_MEM_CMD_*
+ctx_mem:
+       nv_iowr(NV_PGRAPH_FECS_MEM_CMD, 0, $r15)
+       ctx_mem_wait:
+               nv_iord($r15, NV_PGRAPH_FECS_MEM_CMD, 0)
+               or $r15 $r15
+               bra ne #ctx_mem_wait
        ret
 
 // ctx_load - load's a channel's ctxctl data, and selects its vm
@@ -457,23 +458,14 @@ ctx_load:
 
        // switch to channel, somewhat magic in parts..
        mov $r10 12             // DONE_UNK12
-       call #wait_donez
-       mov $r1 0xa24
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r0 // 0x409a24
-       mov $r3 0xb00
-       shl b32 $r3 6
-       iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
-       mov $r1 0xa0c
-       shl b32 $r1 6
-       mov $r4 7
-       iowr I[$r1 + 0x000] $r2 // MEM_CHAN
-       iowr I[$r1 + 0x100] $r4 // MEM_CMD
-       ctx_chan_wait_0:
-               iord $r4 I[$r1 + 0x100]
-               and $r4 0x1f
-               bra ne #ctx_chan_wait_0
-       iowr I[$r3 + 0x000] $r2 // CHAN_CUR
+       call(wait_donez)
+       clear b32 $r15
+       nv_iowr(0x409a24, 0, $r15)
+       nv_iowr(NV_PGRAPH_FECS_CHAN_NEXT, 0, $r2)
+       nv_iowr(NV_PGRAPH_FECS_MEM_CHAN, 0, $r2)
+       mov $r15 NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN
+       call(ctx_mem)
+       nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
 
        // load channel header, fetch PGRAPH context pointer
        mov $xtargets $r0
@@ -482,14 +474,10 @@ ctx_load:
        add b32 $r2 2
 
        trace_set(T_LCHAN)
-       mov $r1 0xa04
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r2         // MEM_BASE
-       mov $r1 0xa20
-       shl b32 $r1 6
-       mov $r2 0x0002
-       sethi $r2 0x80000000
-       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vram
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r2)
+       imm32($r2, NV_PGRAPH_FECS_MEM_TARGET_UNK31)
+       or  $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM
+       nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
        mov $r1 0x10                    // chan + 0x0210
        mov $r2 #xfer_data
        sethi $r2 0x00020000            // 16 bytes
@@ -507,13 +495,9 @@ ctx_load:
 
        // set transfer base to start of context, and fetch context header
        trace_set(T_LCTXH)
-       mov $r2 0xa04
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r1         // MEM_BASE
-       mov $r2 1
-       mov $r1 0xa20
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vm
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r1)
+       mov $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VM
+       nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
        mov $r1 #chan_data
        sethi $r1 0x00060000            // 256 bytes
        xdld $r0 $r1
@@ -532,21 +516,15 @@ ctx_load:
 //
 ctx_chan:
 #if CHIPSET < GK100
-       call #ctx_4160s
+       call(ctx_4160s)
 #endif
-       call #ctx_load
+       call(ctx_load)
        mov $r10 12                     // DONE_UNK12
-       call #wait_donez
-       mov $r1 0xa10
-       shl b32 $r1 6
-       mov $r2 5
-       iowr I[$r1 + 0x000] $r2         // MEM_CMD = 5 (???)
-       ctx_chan_wait:
-               iord $r2 I[$r1 + 0x000]
-               or $r2 $r2
-               bra ne #ctx_chan_wait
+       call(wait_donez)
+       mov $r15 5 // MEM_CMD 5 ???
+       call(ctx_mem)
 #if CHIPSET < GK100
-       call #ctx_4160c
+       call(ctx_4160c)
 #endif
        ret
 
@@ -562,9 +540,7 @@ ctx_chan:
 ctx_mmio_exec:
        // set transfer base to be the mmio list
        ld b32 $r3 D[$r0 + #chan_mmio_address]
-       mov $r2 0xa04
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
        clear b32 $r3
        ctx_mmio_loop:
@@ -580,7 +556,7 @@ ctx_mmio_exec:
                ctx_mmio_pull:
                ld b32 $r14 D[$r4 + #xfer_data + 0x00]
                ld b32 $r15 D[$r4 + #xfer_data + 0x04]
-               call #nv_wr32
+               call(nv_wr32)
 
                // next!
                add b32 $r3 8
@@ -590,7 +566,7 @@ ctx_mmio_exec:
        // set transfer base back to the current context
        ctx_mmio_done:
        ld b32 $r3 D[$r0 + #ctx_current]
-       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
        // disable the mmio list now, we don't need/want to execute it again
        st b32 D[$r0 + #chan_mmio_count] $r0
@@ -610,12 +586,10 @@ ctx_mmio_exec:
 //
 ctx_xfer:
        // according to mwk, some kind of wait for idle
-       mov $r15 0xc00
-       shl b32 $r15 6
        mov $r14 4
-       iowr I[$r15 + 0x200] $r14
+       nv_iowr(0x409c08, 0, $r14)
        ctx_xfer_idle:
-               iord $r14 I[$r15 + 0x000]
+               nv_iord($r14, 0x409c00, 0)
                and $r14 0x2000
                bra ne #ctx_xfer_idle
 
@@ -623,50 +597,42 @@ ctx_xfer:
        bra $p2 #ctx_xfer_pre_load
        ctx_xfer_pre:
                mov $r15 0x10
-               call #ctx_86c
+               call(ctx_86c)
 #if CHIPSET < GK100
-               call #ctx_4160s
+               call(ctx_4160s)
 #endif
                bra not $p1 #ctx_xfer_exec
 
        ctx_xfer_pre_load:
                mov $r15 2
-               call #ctx_4170s
-               call #ctx_4170w
-               call #ctx_redswitch
+               call(ctx_4170s)
+               call(ctx_4170w)
+               call(ctx_redswitch)
                clear b32 $r15
-               call #ctx_4170s
-               call #ctx_load
+               call(ctx_4170s)
+               call(ctx_load)
 
        // fetch context pointer, and initiate xfer on all GPCs
        ctx_xfer_exec:
        ld b32 $r1 D[$r0 + #ctx_current]
-       mov $r2 0x414
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
-       mov $r14 -0x5b00
-       sethi $r14 0x410000
-       mov b32 $r15 $r1
-       call #nv_wr32           // GPC_BCAST_WRCMD_DATA = ctx pointer
-       add b32 $r14 4
+
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_BAR, 0, $r2)
+
+       nv_wr32(0x41a500, $r1)  // GPC_BCAST_WRCMD_DATA = ctx pointer
        xbit $r15 $flags $p1
        xbit $r2 $flags $p2
        shl b32 $r2 1
        or $r15 $r2
-       call #nv_wr32           // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+       nv_wr32(0x41a504, $r15) // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
 
        // strands
-       mov $r1 0x4afc
-       sethi $r1 0x20000
-       mov $r2 0xc
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
-       call #strand_wait
-       mov $r2 0x47fc
-       sethi $r2 0x20000
-       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
-       xbit $r2 $flags $p1
-       add b32 $r2 3
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+       call(strand_pre)
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r2)
+       xbit $r2 $flags $p1     // SAVE/LOAD
+       add b32 $r2 NV_PGRAPH_FECS_STRAND_CMD_SAVE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r2)
 
        // mmio context
        xbit $r10 $flags $p1    // direction
@@ -675,48 +641,42 @@ ctx_xfer:
        ld b32 $r12 D[$r0 + #hub_mmio_list_head]
        ld b32 $r13 D[$r0 + #hub_mmio_list_tail]
        mov $r14 0              // not multi
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
        // wait for GPCs to all complete
        mov $r10 8              // DONE_BAR
-       call #wait_doneo
+       call(wait_doneo)
 
        // wait for strand xfer to complete
-       call #strand_wait
+       call(strand_wait)
 
        // post-op
        bra $p1 #ctx_xfer_post
                mov $r10 12             // DONE_UNK12
-               call #wait_donez
-               mov $r1 0xa10
-               shl b32 $r1 6
-               mov $r2 5
-               iowr I[$r1] $r2         // MEM_CMD
-               ctx_xfer_post_save_wait:
-                       iord $r2 I[$r1]
-                       or $r2 $r2
-                       bra ne #ctx_xfer_post_save_wait
+               call(wait_donez)
+               mov $r15 5 // MEM_CMD 5 ???
+               call(ctx_mem)
 
        bra $p2 #ctx_xfer_done
        ctx_xfer_post:
                mov $r15 2
-               call #ctx_4170s
+               call(ctx_4170s)
                clear b32 $r15
-               call #ctx_86c
-               call #strand_post
-               call #ctx_4170w
+               call(ctx_86c)
+               call(strand_post)
+               call(ctx_4170w)
                clear b32 $r15
-               call #ctx_4170s
+               call(ctx_4170s)
 
                bra not $p1 #ctx_xfer_no_post_mmio
                ld b32 $r1 D[$r0 + #chan_mmio_count]
                or $r1 $r1
                bra e #ctx_xfer_no_post_mmio
-                       call #ctx_mmio_exec
+                       call(ctx_mmio_exec)
 
                ctx_xfer_no_post_mmio:
 #if CHIPSET < GK100
-               call #ctx_4160c
+               call(ctx_4160c)
 #endif
 
        ctx_xfer_done:
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5
new file mode 100644 (file)
index 0000000..7c5d256
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grhub_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "hub.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grhub_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "hub.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
new file mode 100644 (file)
index 0000000..4750984
--- /dev/null
@@ -0,0 +1,916 @@
+uint32_t nv108_grhub_data[] = {
+/* 0x0000: hub_mmio_list_head */
+       0x00000300,
+/* 0x0004: hub_mmio_list_tail */
+       0x00000304,
+/* 0x0008: gpc_count */
+       0x00000000,
+/* 0x000c: rop_count */
+       0x00000000,
+/* 0x0010: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0058: ctx_current */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0100: chan_data */
+/* 0x0100: chan_mmio_count */
+       0x00000000,
+/* 0x0104: chan_mmio_address */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0200: xfer_data */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0300: hub_mmio_list_base */
+       0x0417e91c,
+};
+
+uint32_t nv108_grhub_code[] = {
+       0x030e0ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e02,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0x02050080,
+       0xbd000ff6,
+       0x80010f04,
+       0xf6030700,
+       0x04bd000f,
+/* 0x030e: init */
+       0x04bd00f8,
+       0x410007fe,
+       0x11cf4200,
+       0x0911e700,
+       0x0814b601,
+       0x020014fe,
+       0x12004002,
+       0xbd0002f6,
+       0x05c94104,
+       0xbd0010fe,
+       0x07004024,
+       0xbd0002f6,
+       0x20034204,
+       0x01010080,
+       0xbd0002f6,
+       0x20044204,
+       0x01010480,
+       0xbd0002f6,
+       0x200b4204,
+       0x01010880,
+       0xbd0002f6,
+       0x200c4204,
+       0x01011c80,
+       0xbd0002f6,
+       0x01039204,
+       0x03090080,
+       0xbd0003f6,
+       0x87044204,
+       0xf6040040,
+       0x04bd0002,
+       0x00400402,
+       0x0002f603,
+       0x31f404bd,
+       0x96048e10,
+       0x00657e40,
+       0xc7feb200,
+       0x01b590f1,
+       0x1ff4f003,
+       0x01020fb5,
+       0x041fbb01,
+       0x800112b6,
+       0xf6010300,
+       0x04bd0001,
+       0x01040080,
+       0xbd0001f6,
+       0x01004104,
+       0x627e020f,
+       0x717e0006,
+       0x100f0006,
+       0x0006b37e,
+       0x98000e98,
+       0x207e010f,
+       0x14950001,
+       0xc0008008,
+       0x0004f601,
+       0x008004bd,
+       0x04f601c1,
+       0xb704bd00,
+       0xbb130030,
+       0xf5b6001f,
+       0xd3008002,
+       0x000ff601,
+       0x15b604bd,
+       0x0110b608,
+       0xb20814b6,
+       0x02687e1f,
+       0x001fbb00,
+       0x84020398,
+/* 0x041f: init_gpc */
+       0xb8502000,
+       0x0008044e,
+       0x8f7e1fb2,
+       0x4eb80000,
+       0xbd00010c,
+       0x008f7ef4,
+       0x044eb800,
+       0x8f7e0001,
+       0x4eb80000,
+       0x0f000100,
+       0x008f7e02,
+       0x004eb800,
+/* 0x044e: init_gpc_wait */
+       0x657e0008,
+       0xffc80000,
+       0xf90bf41f,
+       0x08044eb8,
+       0x00657e00,
+       0x001fbb00,
+       0x800040b7,
+       0xf40132b6,
+       0x000fb41b,
+       0x0006b37e,
+       0x627e000f,
+       0x00800006,
+       0x01f60201,
+       0xbd04bd00,
+       0x1f19f014,
+       0x02300080,
+       0xbd0001f6,
+/* 0x0491: main */
+       0x0031f404,
+       0x0d0028f4,
+       0x00377e10,
+       0xf401f400,
+       0x4001e4b1,
+       0x00c71bf5,
+       0x99f094bd,
+       0x37008004,
+       0x0009f602,
+       0x008104bd,
+       0x11cf02c0,
+       0xc1008200,
+       0x0022cf02,
+       0xf41f13c8,
+       0x23c8770b,
+       0x550bf41f,
+       0x12b220f9,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0231f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x20fc04bd,
+       0x99f094bd,
+       0x37008006,
+       0x0009f602,
+       0x31f404bd,
+       0x08367e01,
+       0xf094bd00,
+       0x00800699,
+       0x09f60217,
+       0xf404bd00,
+/* 0x0522: chsw_prev_no_next */
+       0x20f92f0e,
+       0x32f412b2,
+       0x0232f401,
+       0x0008367e,
+       0x008020fc,
+       0x02f602c0,
+       0xf404bd00,
+/* 0x053e: chsw_no_prev */
+       0x23c8130e,
+       0x0d0bf41f,
+       0xf40131f4,
+       0x367e0232,
+/* 0x054e: chsw_done */
+       0x01020008,
+       0x02c30080,
+       0xbd0002f6,
+       0xf094bd04,
+       0x00800499,
+       0x09f60217,
+       0xf504bd00,
+/* 0x056b: main_not_ctx_switch */
+       0xb0ff2a0e,
+       0x1bf401e4,
+       0x7ef2b20c,
+       0xf40007d6,
+/* 0x057a: main_not_ctx_chan */
+       0xe4b0400e,
+       0x2c1bf402,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0232f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x0ef404bd,
+/* 0x05a9: main_not_ctx_save */
+       0x10ef9411,
+       0x7e01f5f0,
+       0xf50002f8,
+/* 0x05b7: main_done */
+       0xbdfede0e,
+       0x1f29f024,
+       0x02300080,
+       0xbd0002f6,
+       0xcc0ef504,
+/* 0x05c9: ih */
+       0xfe80f9fe,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0x004a04bd,
+       0x00aacf02,
+       0xf404abc4,
+       0x100d230b,
+       0xcf1a004e,
+       0x004f00ee,
+       0x00ffcf19,
+       0x0000047e,
+       0x0400b0b7,
+       0x0040010e,
+       0x000ef61d,
+/* 0x060a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x4e100d0c,
+       0x047e4001,
+/* 0x061a: ih_no_ctxsw */
+       0xabe40000,
+       0x0bf40400,
+       0x01004b10,
+       0x448ebfb2,
+       0x8f7e4001,
+/* 0x062e: ih_no_fwmthd */
+       0x044b0000,
+       0xffb0bd01,
+       0x0bf4b4ab,
+       0x0700800c,
+       0x000bf603,
+/* 0x0642: ih_no_other */
+       0x004004bd,
+       0x000af601,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x0662: ctx_4170s */
+       0xf5f001f8,
+       0x8effb210,
+       0x7e404170,
+       0xf800008f,
+/* 0x0671: ctx_4170w */
+       0x41708e00,
+       0x00657e40,
+       0xf0ffb200,
+       0x1bf410f4,
+/* 0x0683: ctx_redswitch */
+       0x4e00f8f3,
+       0xe5f00200,
+       0x20e5f040,
+       0x8010e5f0,
+       0xf6018500,
+       0x04bd000e,
+/* 0x069a: ctx_redswitch_delay */
+       0xf2b6080f,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x01850080,
+       0xbd000ef6,
+/* 0x06b3: ctx_86c */
+       0x8000f804,
+       0xf6022300,
+       0x04bd000f,
+       0x148effb2,
+       0x8f7e408a,
+       0xffb20000,
+       0x41a88c8e,
+       0x00008f7e,
+/* 0x06d2: ctx_mem */
+       0x008000f8,
+       0x0ff60284,
+/* 0x06db: ctx_mem_wait */
+       0x8f04bd00,
+       0xcf028400,
+       0xfffd00ff,
+       0xf61bf405,
+/* 0x06ea: ctx_load */
+       0x94bd00f8,
+       0x800599f0,
+       0xf6023700,
+       0x04bd0009,
+       0xb87e0c0a,
+       0xf4bd0000,
+       0x02890080,
+       0xbd000ff6,
+       0xc1008004,
+       0x0002f602,
+       0x008004bd,
+       0x02f60283,
+       0x0f04bd00,
+       0x06d27e07,
+       0xc0008000,
+       0x0002f602,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0x800899f0,
+       0xf6023700,
+       0x04bd0009,
+       0x02810080,
+       0xbd0002f6,
+       0x0000d204,
+       0x25f08000,
+       0x88008002,
+       0x0002f602,
+       0x100104bd,
+       0xf0020042,
+       0x12fa0223,
+       0xbd03f805,
+       0x0899f094,
+       0x02170080,
+       0xbd0009f6,
+       0x81019804,
+       0x981814b6,
+       0x25b68002,
+       0x0512fd08,
+       0xbd1601b5,
+       0x0999f094,
+       0x02370080,
+       0xbd0009f6,
+       0x81008004,
+       0x0001f602,
+       0x010204bd,
+       0x02880080,
+       0xbd0002f6,
+       0x01004104,
+       0xfa0613f0,
+       0x03f80501,
+       0x99f094bd,
+       0x17008009,
+       0x0009f602,
+       0x94bd04bd,
+       0x800599f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x07d6: ctx_chan */
+       0xea7e00f8,
+       0x0c0a0006,
+       0x0000b87e,
+       0xd27e050f,
+       0x00f80006,
+/* 0x07e8: ctx_mmio_exec */
+       0x80410398,
+       0xf6028100,
+       0x04bd0003,
+/* 0x07f6: ctx_mmio_loop */
+       0x34c434bd,
+       0x0e1bf4ff,
+       0xf0020045,
+       0x35fa0653,
+/* 0x0807: ctx_mmio_pull */
+       0x9803f805,
+       0x4f98804e,
+       0x008f7e81,
+       0x0830b600,
+       0xf40112b6,
+/* 0x081a: ctx_mmio_done */
+       0x0398df1b,
+       0x81008016,
+       0x0003f602,
+       0x00b504bd,
+       0x01004140,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x0836: ctx_xfer */
+       0x040e00f8,
+       0x03020080,
+       0xbd000ef6,
+/* 0x0841: ctx_xfer_idle */
+       0x00008e04,
+       0x00eecf03,
+       0x2000e4f1,
+       0xf4f51bf4,
+       0x02f40611,
+/* 0x0855: ctx_xfer_pre */
+       0x7e100f0c,
+       0xf40006b3,
+/* 0x085e: ctx_xfer_pre_load */
+       0x020f1b11,
+       0x0006627e,
+       0x0006717e,
+       0x0006837e,
+       0x627ef4bd,
+       0xea7e0006,
+/* 0x0876: ctx_xfer_exec */
+       0x01980006,
+       0x8024bd16,
+       0xf6010500,
+       0x04bd0002,
+       0x008e1fb2,
+       0x8f7e41a5,
+       0xfcf00000,
+       0x022cf001,
+       0xfd0124b6,
+       0xffb205f2,
+       0x41a5048e,
+       0x00008f7e,
+       0x0002167e,
+       0xfc8024bd,
+       0x02f60247,
+       0xf004bd00,
+       0x20b6012c,
+       0x4afc8003,
+       0x0002f602,
+       0xacf004bd,
+       0x06a5f001,
+       0x0c98000b,
+       0x010d9800,
+       0x3d7e000e,
+       0x080a0001,
+       0x0000ec7e,
+       0x00020a7e,
+       0x0a1201f4,
+       0x00b87e0c,
+       0x7e050f00,
+       0xf40006d2,
+/* 0x08f2: ctx_xfer_post */
+       0x020f2d02,
+       0x0006627e,
+       0xb37ef4bd,
+       0x277e0006,
+       0x717e0002,
+       0xf4bd0006,
+       0x0006627e,
+       0x981011f4,
+       0x11fd4001,
+       0x070bf405,
+       0x0007e87e,
+/* 0x091c: ctx_xfer_no_post_mmio */
+/* 0x091c: ctx_xfer_done */
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index b59f694c0423e35afddc26e2388ae8a7d6514472..132f684b1946a9357697eace024fa866af43b72f 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvc0_grhub_data[] = {
 };
 
 uint32_t nvc0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvc0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvc0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvc0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0xb521f502,
+       0xc721f507,
+       0x10f7f007,
+       0x081421f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x081421f5,
+       0xf500f7f0,
+       0xf107b521,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvc0_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd082f,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x2f21f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x082f21f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1082f21,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09e821f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09e821,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09e821f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd082f,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x7821f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4160s */
-       0xf101f800,
-       0xf04160e7,
-       0xf7f040e3,
-       0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-       0xc86821f4,
-       0x0bf404ff,
-/* 0x0643: ctx_4160c */
-       0xf100f8fa,
+/* 0x077f: ctx_4160s */
+       0xf001f800,
+       0xffb901f7,
+       0x60e7f102,
+       0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+       0xf19d21f4,
        0xf04160e7,
-       0xf4bd40e3,
-       0xf88d21f4,
-/* 0x0651: ctx_4170s */
-       0x70e7f100,
+       0x21f440e3,
+       0x02ffb968,
+       0xf404ffc8,
+       0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+       0xffb9f4bd,
+       0x60e7f102,
        0x40e3f041,
-       0xf410f5f0,
-       0x00f88d21,
-/* 0x0660: ctx_4170w */
-       0x4170e7f1,
-       0xf440e3f0,
-       0xf4f06821,
-       0xf31bf410,
-/* 0x0672: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x70f7f106,
-       0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-       0xb608f7f0,
-       0x1bf401f2,
-       0x70f7f1fd,
-       0x00efd007,
-/* 0x0692: ctx_86c */
-       0xe7f100f8,
-       0xe4b6086c,
-       0x00efd006,
-       0x8a14e7f1,
-       0xf440e3f0,
-       0xe7f18d21,
-       0xe3f0a86c,
-       0x8d21f441,
-/* 0x06b2: ctx_load */
+       0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+       0x10f5f000,
+       0xf102ffb9,
+       0xf04170e7,
+       0x21f440e3,
+/* 0x07c7: ctx_4170w */
+       0xf100f89d,
+       0xf04170e7,
+       0x21f440e3,
+       0x02ffb968,
+       0xf410f4f0,
+       0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+       0x0200e7f1,
+       0xf040e5f0,
+       0xe5f020e5,
+       0x0007f110,
+       0x0103f085,
+       0xbd000ed0,
+       0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+       0xf401f2b6,
+       0xe5f1fd1b,
+       0xe5f10400,
+       0x07f10100,
+       0x03f08500,
+       0x000ed001,
+       0x00f804bd,
+/* 0x0814: ctx_86c */
+       0x1b0007f1,
+       0xd00203f0,
+       0x04bd000f,
+       0xf102ffb9,
+       0xf08a14e7,
+       0x21f440e3,
+       0x02ffb99d,
+       0xa86ce7f1,
+       0xf441e3f0,
+       0x00f89d21,
+/* 0x083c: ctx_mem */
+       0x840007f1,
+       0xd00203f0,
+       0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+       0x8400f7f1,
+       0xcf02f3f0,
+       0xfffd00ff,
+       0xf31bf405,
+/* 0x085a: ctx_load */
        0x94bd00f8,
        0xf10599f0,
        0xf00f0007,
        0x09d00203,
        0xf004bd00,
        0x21f40ca7,
-       0x2417f1c9,
-       0x0614b60a,
-       0xf10010d0,
-       0xb60b0037,
-       0x32d00634,
-       0x0c17f140,
-       0x0614b60a,
-       0xd00747f0,
-       0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-       0x4014cf40,
-       0xf41f44f0,
-       0x32d0fa1b,
-       0x000bfe00,
-       0xb61f2af0,
-       0x20b60424,
-       0xf094bd02,
+       0xf1f4bdd0,
+       0xf0890007,
+       0x0fd00203,
+       0xf104bd00,
+       0xf0c10007,
+       0x02d00203,
+       0xf104bd00,
+       0xf0830007,
+       0x02d00203,
+       0xf004bd00,
+       0x21f507f7,
+       0x07f1083c,
+       0x03f0c000,
+       0x0002d002,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0xf10899f0,
+       0xf00f0007,
+       0x09d00203,
+       0xf104bd00,
+       0xf0810007,
+       0x02d00203,
+       0xf104bd00,
+       0xf1000027,
+       0xf0800023,
+       0x07f10225,
+       0x03f08800,
+       0x0002d002,
+       0x17f004bd,
+       0x0027f110,
+       0x0223f002,
+       0xf80512fa,
+       0xf094bd03,
        0x07f10899,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x17f104bd,
-       0x14b60a04,
-       0x0012d006,
-       0x0a2017f1,
-       0xf00614b6,
-       0x23f10227,
-       0x12d08000,
-       0x1017f000,
-       0x020027f1,
-       0xfa0223f0,
-       0x03f80512,
+       0x019804bd,
+       0x1814b681,
+       0xb6800298,
+       0x12fd0825,
+       0x16018005,
        0x99f094bd,
-       0x0007f108,
-       0x0203f017,
+       0x0007f109,
+       0x0203f00f,
        0xbd0009d0,
-       0x81019804,
-       0x981814b6,
-       0x25b68002,
-       0x0512fd08,
-       0xbd160180,
-       0x0999f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0x0a0427f1,
-       0xd00624b6,
-       0x27f00021,
-       0x2017f101,
-       0x0614b60a,
-       0xf10012d0,
-       0xf0010017,
-       0x01fa0613,
-       0xbd03f805,
-       0x0999f094,
-       0x170007f1,
+       0x0007f104,
+       0x0203f081,
+       0xbd0001d0,
+       0x0127f004,
+       0x880007f1,
        0xd00203f0,
-       0x04bd0009,
+       0x04bd0002,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80501,
        0x99f094bd,
-       0x0007f105,
+       0x0007f109,
        0x0203f017,
        0xbd0009d0,
-/* 0x07bb: ctx_chan */
-       0xf500f804,
-       0xf5062b21,
-       0xf006b221,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf5fa1bf4,
-       0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-       0x41039800,
-       0x0a0427f1,
-       0xd00624b6,
-       0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+       0xf094bd04,
+       0x07f10599,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0978: ctx_chan */
+       0x077f21f5,
+       0x085a21f5,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+       0x9800f807,
+       0x07f14103,
+       0x03f08100,
+       0x0003d002,
+       0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
        0xf4ff34c4,
        0x57f10f1b,
        0x53f00200,
        0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
        0x4e9803f8,
        0x814f9880,
-       0xb68d21f4,
+       0xb69d21f4,
        0x12b60830,
        0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-       0xd0160398,
-       0x00800023,
-       0x0017f140,
-       0x0613f001,
-       0xf80601fa,
-/* 0x082f: ctx_xfer */
-       0xf100f803,
-       0xb60c00f7,
-       0xe7f006f4,
-       0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-       0xf100fecf,
-       0xf42000e4,
-       0x11f4f91b,
-       0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-       0xf510f7f0,
-       0xf5069221,
-       0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-       0xf7f01c11,
-       0x5121f502,
-       0x6021f506,
-       0x7221f506,
-       0xf5f4bd06,
-       0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-       0x9806b221,
-       0x27f11601,
-       0x24b60414,
-       0x0020d006,
-       0xa500e7f1,
-       0xb941e3f0,
-       0x21f4021f,
-       0x04e0b68d,
-       0xf001fcf0,
-       0x24b6022c,
-       0x05f2fd01,
-       0xf18d21f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00c,
-       0x021521f5,
-       0x47fc27f1,
-       0xd00223f0,
-       0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+       0xf1160398,
+       0xf0810007,
+       0x03d00203,
+       0x8004bd00,
+       0x17f14000,
+       0x13f00100,
+       0x0601fa06,
+       0x00f803f8,
+/* 0x09e8: ctx_xfer */
+       0xf104e7f0,
+       0xf0020007,
+       0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+       0xf104bd00,
+       0xf00000e7,
+       0xeecf03e3,
+       0x00e4f100,
+       0xf21bf420,
+       0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+       0xf7f01102,
+       0x1421f510,
+       0x7f21f508,
+       0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+       0xf502f7f0,
+       0xf507b521,
+       0xf507c721,
+       0xbd07dc21,
+       0xb521f5f4,
+       0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+       0x16019808,
+       0x07f124bd,
+       0x03f00500,
+       0x0002d001,
+       0x1fb904bd,
+       0x00e7f102,
+       0x41e3f0a5,
+       0xf09d21f4,
+       0x2cf001fc,
+       0x0124b602,
+       0xb905f2fd,
+       0xe7f102ff,
+       0xe3f0a504,
+       0x9d21f441,
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
        0x0320b601,
-       0xf00012d0,
-       0xa5f001ac,
-       0x00b7f006,
-       0x98000c98,
-       0xe7f0010d,
-       0x6621f500,
-       0x08a7f001,
-       0x010921f5,
-       0x021521f5,
-       0xf02201f4,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-       0xf7f03202,
-       0x5121f502,
-       0xf5f4bd06,
-       0xf5069221,
-       0xf5023421,
-       0xbd066021,
-       0x5121f5f4,
-       0x1011f406,
-       0xfd400198,
-       0x0bf40511,
-       0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-       0x4321f507,
-/* 0x0935: ctx_xfer_done */
-       0x0000f806,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf001acf0,
+       0xb7f006a5,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xa7f0016f,
+       0x1021f508,
+       0x5e21f501,
+       0x1301f402,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+       0xf502f7f0,
+       0xbd07b521,
+       0x1421f5f4,
+       0x7f21f508,
+       0xc721f502,
+       0xf5f4bd07,
+       0xf407b521,
+       0x01981011,
+       0x0511fd40,
+       0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+       0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+       0xf807a421,
        0x00000000,
        0x00000000,
        0x00000000,
index a1b9f763996a349d0def2c0770568accbfea9b8d..84af8241898764bfef6116d881c0425346684ee2 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvd7_grhub_data[] = {
 };
 
 uint32_t nvd7_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvd7_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvd7_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvd7_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0xb521f502,
+       0xc721f507,
+       0x10f7f007,
+       0x081421f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x081421f5,
+       0xf500f7f0,
+       0xf107b521,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvd7_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd082f,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x2f21f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x082f21f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1082f21,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09e821f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09e821,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09e821f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd082f,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x7821f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4160s */
-       0xf101f800,
-       0xf04160e7,
-       0xf7f040e3,
-       0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-       0xc86821f4,
-       0x0bf404ff,
-/* 0x0643: ctx_4160c */
-       0xf100f8fa,
+/* 0x077f: ctx_4160s */
+       0xf001f800,
+       0xffb901f7,
+       0x60e7f102,
+       0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+       0xf19d21f4,
        0xf04160e7,
-       0xf4bd40e3,
-       0xf88d21f4,
-/* 0x0651: ctx_4170s */
-       0x70e7f100,
+       0x21f440e3,
+       0x02ffb968,
+       0xf404ffc8,
+       0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+       0xffb9f4bd,
+       0x60e7f102,
        0x40e3f041,
-       0xf410f5f0,
-       0x00f88d21,
-/* 0x0660: ctx_4170w */
-       0x4170e7f1,
-       0xf440e3f0,
-       0xf4f06821,
-       0xf31bf410,
-/* 0x0672: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x70f7f106,
-       0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-       0xb608f7f0,
-       0x1bf401f2,
-       0x70f7f1fd,
-       0x00efd007,
-/* 0x0692: ctx_86c */
-       0xe7f100f8,
-       0xe4b6086c,
-       0x00efd006,
-       0x8a14e7f1,
-       0xf440e3f0,
-       0xe7f18d21,
-       0xe3f0a86c,
-       0x8d21f441,
-/* 0x06b2: ctx_load */
+       0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+       0x10f5f000,
+       0xf102ffb9,
+       0xf04170e7,
+       0x21f440e3,
+/* 0x07c7: ctx_4170w */
+       0xf100f89d,
+       0xf04170e7,
+       0x21f440e3,
+       0x02ffb968,
+       0xf410f4f0,
+       0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+       0x0200e7f1,
+       0xf040e5f0,
+       0xe5f020e5,
+       0x0007f110,
+       0x0103f085,
+       0xbd000ed0,
+       0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+       0xf401f2b6,
+       0xe5f1fd1b,
+       0xe5f10400,
+       0x07f10100,
+       0x03f08500,
+       0x000ed001,
+       0x00f804bd,
+/* 0x0814: ctx_86c */
+       0x1b0007f1,
+       0xd00203f0,
+       0x04bd000f,
+       0xf102ffb9,
+       0xf08a14e7,
+       0x21f440e3,
+       0x02ffb99d,
+       0xa86ce7f1,
+       0xf441e3f0,
+       0x00f89d21,
+/* 0x083c: ctx_mem */
+       0x840007f1,
+       0xd00203f0,
+       0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+       0x8400f7f1,
+       0xcf02f3f0,
+       0xfffd00ff,
+       0xf31bf405,
+/* 0x085a: ctx_load */
        0x94bd00f8,
        0xf10599f0,
        0xf00f0007,
        0x09d00203,
        0xf004bd00,
        0x21f40ca7,
-       0x2417f1c9,
-       0x0614b60a,
-       0xf10010d0,
-       0xb60b0037,
-       0x32d00634,
-       0x0c17f140,
-       0x0614b60a,
-       0xd00747f0,
-       0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-       0x4014cf40,
-       0xf41f44f0,
-       0x32d0fa1b,
-       0x000bfe00,
-       0xb61f2af0,
-       0x20b60424,
-       0xf094bd02,
+       0xf1f4bdd0,
+       0xf0890007,
+       0x0fd00203,
+       0xf104bd00,
+       0xf0c10007,
+       0x02d00203,
+       0xf104bd00,
+       0xf0830007,
+       0x02d00203,
+       0xf004bd00,
+       0x21f507f7,
+       0x07f1083c,
+       0x03f0c000,
+       0x0002d002,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0xf10899f0,
+       0xf00f0007,
+       0x09d00203,
+       0xf104bd00,
+       0xf0810007,
+       0x02d00203,
+       0xf104bd00,
+       0xf1000027,
+       0xf0800023,
+       0x07f10225,
+       0x03f08800,
+       0x0002d002,
+       0x17f004bd,
+       0x0027f110,
+       0x0223f002,
+       0xf80512fa,
+       0xf094bd03,
        0x07f10899,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x17f104bd,
-       0x14b60a04,
-       0x0012d006,
-       0x0a2017f1,
-       0xf00614b6,
-       0x23f10227,
-       0x12d08000,
-       0x1017f000,
-       0x020027f1,
-       0xfa0223f0,
-       0x03f80512,
+       0x019804bd,
+       0x1814b681,
+       0xb6800298,
+       0x12fd0825,
+       0x16018005,
        0x99f094bd,
-       0x0007f108,
-       0x0203f017,
+       0x0007f109,
+       0x0203f00f,
        0xbd0009d0,
-       0x81019804,
-       0x981814b6,
-       0x25b68002,
-       0x0512fd08,
-       0xbd160180,
-       0x0999f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0x0a0427f1,
-       0xd00624b6,
-       0x27f00021,
-       0x2017f101,
-       0x0614b60a,
-       0xf10012d0,
-       0xf0010017,
-       0x01fa0613,
-       0xbd03f805,
-       0x0999f094,
-       0x170007f1,
+       0x0007f104,
+       0x0203f081,
+       0xbd0001d0,
+       0x0127f004,
+       0x880007f1,
        0xd00203f0,
-       0x04bd0009,
+       0x04bd0002,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80501,
        0x99f094bd,
-       0x0007f105,
+       0x0007f109,
        0x0203f017,
        0xbd0009d0,
-/* 0x07bb: ctx_chan */
-       0xf500f804,
-       0xf5062b21,
-       0xf006b221,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf5fa1bf4,
-       0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-       0x41039800,
-       0x0a0427f1,
-       0xd00624b6,
-       0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+       0xf094bd04,
+       0x07f10599,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0978: ctx_chan */
+       0x077f21f5,
+       0x085a21f5,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+       0x9800f807,
+       0x07f14103,
+       0x03f08100,
+       0x0003d002,
+       0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
        0xf4ff34c4,
        0x57f10f1b,
        0x53f00200,
        0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
        0x4e9803f8,
        0x814f9880,
-       0xb68d21f4,
+       0xb69d21f4,
        0x12b60830,
        0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-       0xd0160398,
-       0x00800023,
-       0x0017f140,
-       0x0613f001,
-       0xf80601fa,
-/* 0x082f: ctx_xfer */
-       0xf100f803,
-       0xb60c00f7,
-       0xe7f006f4,
-       0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-       0xf100fecf,
-       0xf42000e4,
-       0x11f4f91b,
-       0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-       0xf510f7f0,
-       0xf5069221,
-       0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-       0xf7f01c11,
-       0x5121f502,
-       0x6021f506,
-       0x7221f506,
-       0xf5f4bd06,
-       0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-       0x9806b221,
-       0x27f11601,
-       0x24b60414,
-       0x0020d006,
-       0xa500e7f1,
-       0xb941e3f0,
-       0x21f4021f,
-       0x04e0b68d,
-       0xf001fcf0,
-       0x24b6022c,
-       0x05f2fd01,
-       0xf18d21f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00c,
-       0x021521f5,
-       0x47fc27f1,
-       0xd00223f0,
-       0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+       0xf1160398,
+       0xf0810007,
+       0x03d00203,
+       0x8004bd00,
+       0x17f14000,
+       0x13f00100,
+       0x0601fa06,
+       0x00f803f8,
+/* 0x09e8: ctx_xfer */
+       0xf104e7f0,
+       0xf0020007,
+       0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+       0xf104bd00,
+       0xf00000e7,
+       0xeecf03e3,
+       0x00e4f100,
+       0xf21bf420,
+       0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+       0xf7f01102,
+       0x1421f510,
+       0x7f21f508,
+       0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+       0xf502f7f0,
+       0xf507b521,
+       0xf507c721,
+       0xbd07dc21,
+       0xb521f5f4,
+       0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+       0x16019808,
+       0x07f124bd,
+       0x03f00500,
+       0x0002d001,
+       0x1fb904bd,
+       0x00e7f102,
+       0x41e3f0a5,
+       0xf09d21f4,
+       0x2cf001fc,
+       0x0124b602,
+       0xb905f2fd,
+       0xe7f102ff,
+       0xe3f0a504,
+       0x9d21f441,
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
        0x0320b601,
-       0xf00012d0,
-       0xa5f001ac,
-       0x00b7f006,
-       0x98000c98,
-       0xe7f0010d,
-       0x6621f500,
-       0x08a7f001,
-       0x010921f5,
-       0x021521f5,
-       0xf02201f4,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-       0xf7f03202,
-       0x5121f502,
-       0xf5f4bd06,
-       0xf5069221,
-       0xf5023421,
-       0xbd066021,
-       0x5121f5f4,
-       0x1011f406,
-       0xfd400198,
-       0x0bf40511,
-       0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-       0x4321f507,
-/* 0x0935: ctx_xfer_done */
-       0x0000f806,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf001acf0,
+       0xb7f006a5,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xa7f0016f,
+       0x1021f508,
+       0x5e21f501,
+       0x1301f402,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+       0xf502f7f0,
+       0xbd07b521,
+       0x1421f5f4,
+       0x7f21f508,
+       0xc721f502,
+       0xf5f4bd07,
+       0xf407b521,
+       0x01981011,
+       0x0511fd40,
+       0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+       0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+       0xf807a421,
        0x00000000,
        0x00000000,
        0x00000000,
index eb7bc0e9576eab1a841bb93fcb3af4e3f924b6d0..1c179bdd48cc2a0ddd3228a3e8bfc0005f1bf06a 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nve0_grhub_data[] = {
 };
 
 uint32_t nve0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nve0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nve0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nve0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0x7f21f502,
+       0x9121f507,
+       0x10f7f007,
+       0x07de21f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x07de21f5,
+       0xf500f7f0,
+       0xf1077f21,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nve0_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd0801,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x0121f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x080121f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1080121,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09aa21f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09aa21,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09aa21f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd0801,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x4221f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4170s */
-       0xf101f800,
-       0xf04170e7,
-       0xf5f040e3,
-       0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+       0xf001f800,
+       0xffb910f5,
+       0x70e7f102,
+       0x40e3f041,
+       0xf89d21f4,
+/* 0x0791: ctx_4170w */
+       0x70e7f100,
+       0x40e3f041,
+       0xb96821f4,
+       0xf4f002ff,
+       0xf01bf410,
+/* 0x07a6: ctx_redswitch */
        0xe7f100f8,
-       0xe3f04170,
-       0x6821f440,
-       0xf410f4f0,
+       0xe5f00200,
+       0x20e5f040,
+       0xf110e5f0,
+       0xf0850007,
+       0x0ed00103,
+       0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+       0xf2b608f7,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000e,
+/* 0x07de: ctx_86c */
+       0x07f100f8,
+       0x03f01b00,
+       0x000fd002,
+       0xffb904bd,
+       0x14e7f102,
+       0x40e3f08a,
+       0xb99d21f4,
+       0xe7f102ff,
+       0xe3f0a86c,
+       0x9d21f441,
+/* 0x0806: ctx_mem */
+       0x07f100f8,
+       0x03f08400,
+       0x000fd002,
+/* 0x0812: ctx_mem_wait */
+       0xf7f104bd,
+       0xf3f08400,
+       0x00ffcf02,
+       0xf405fffd,
        0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-       0x0614e7f1,
-       0xf106e4b6,
-       0xd00270f7,
-       0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-       0x01f2b608,
-       0xf1fd1bf4,
-       0xd00770f7,
-       0x00f800ef,
-/* 0x066c: ctx_86c */
-       0x086ce7f1,
-       0xd006e4b6,
-       0xe7f100ef,
-       0xe3f08a14,
-       0x8d21f440,
-       0xa86ce7f1,
-       0xf441e3f0,
-       0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
        0x99f094bd,
        0x0007f105,
        0x0203f00f,
        0xbd0009d0,
        0x0ca7f004,
-       0xf1c921f4,
-       0xb60a2417,
-       0x10d00614,
-       0x0037f100,
-       0x0634b60b,
-       0xf14032d0,
-       0xb60a0c17,
-       0x47f00614,
-       0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-       0xcf4014d0,
-       0x44f04014,
-       0xfa1bf41f,
-       0xfe0032d0,
-       0x2af0000b,
-       0x0424b61f,
-       0xbd0220b6,
+       0xbdd021f4,
+       0x0007f1f4,
+       0x0203f089,
+       0xbd000fd0,
+       0x0007f104,
+       0x0203f0c1,
+       0xbd0002d0,
+       0x0007f104,
+       0x0203f083,
+       0xbd0002d0,
+       0x07f7f004,
+       0x080621f5,
+       0xc00007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf0000bfe,
+       0x24b61f2a,
+       0x0220b604,
+       0x99f094bd,
+       0x0007f108,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f081,
+       0xbd0002d0,
+       0x0027f104,
+       0x0023f100,
+       0x0225f080,
+       0x880007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf11017f0,
+       0xf0020027,
+       0x12fa0223,
+       0xbd03f805,
        0x0899f094,
-       0x0f0007f1,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0a0417f1,
-       0xd00614b6,
-       0x17f10012,
-       0x14b60a20,
-       0x0227f006,
-       0x800023f1,
-       0xf00012d0,
-       0x27f11017,
-       0x23f00200,
-       0x0512fa02,
-       0x94bd03f8,
-       0xf10899f0,
-       0xf0170007,
+       0xb6810198,
+       0x02981814,
+       0x0825b680,
+       0x800512fd,
+       0x94bd1601,
+       0xf10999f0,
+       0xf00f0007,
        0x09d00203,
-       0x9804bd00,
-       0x14b68101,
-       0x80029818,
-       0xfd0825b6,
-       0x01800512,
-       0xf094bd16,
-       0x07f10999,
-       0x03f00f00,
-       0x0009d002,
-       0x27f104bd,
-       0x24b60a04,
-       0x0021d006,
-       0xf10127f0,
-       0xb60a2017,
-       0x12d00614,
-       0x0017f100,
-       0x0613f001,
-       0xf80501fa,
-       0xf094bd03,
-       0x07f10999,
-       0x03f01700,
-       0x0009d002,
-       0x94bd04bd,
-       0xf10599f0,
+       0xf104bd00,
+       0xf0810007,
+       0x01d00203,
+       0xf004bd00,
+       0x07f10127,
+       0x03f08800,
+       0x0002d002,
+       0x17f104bd,
+       0x13f00100,
+       0x0501fa06,
+       0x94bd03f8,
+       0xf10999f0,
        0xf0170007,
        0x09d00203,
-       0xf804bd00,
-/* 0x0795: ctx_chan */
-       0x8c21f500,
-       0x0ca7f006,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-       0xfd0012cf,
-       0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-       0x9800f8fa,
-       0x27f14103,
-       0x24b60a04,
-       0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+       0xbd04bd00,
+       0x0599f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x0942: ctx_chan */
+       0x21f500f8,
+       0xa7f00824,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+       0x41039800,
+       0x810007f1,
+       0xd00203f0,
+       0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
        0x34c434bd,
        0x0f1bf4ff,
        0x020057f1,
        0xfa0653f0,
        0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
        0x98804e98,
        0x21f4814f,
-       0x0830b68d,
+       0x0830b69d,
        0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
        0x0398df1b,
-       0x0023d016,
-       0xf1400080,
-       0xf0010017,
-       0x01fa0613,
-       0xf803f806,
-/* 0x0801: ctx_xfer */
-       0x00f7f100,
-       0x06f4b60c,
-       0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-       0xfecf80fe,
-       0x00e4f100,
-       0xf91bf420,
-       0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-       0xf7f00d02,
-       0x6c21f510,
-       0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-       0xf502f7f0,
-       0xf5062b21,
-       0xf5063a21,
-       0xbd064c21,
-       0x2b21f5f4,
-       0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-       0x16019806,
-       0x041427f1,
-       0xd00624b6,
-       0xe7f10020,
-       0xe3f0a500,
-       0x021fb941,
-       0xb68d21f4,
-       0xfcf004e0,
-       0x022cf001,
-       0xfd0124b6,
-       0x21f405f2,
-       0xfc17f18d,
-       0x0213f04a,
-       0xd00c27f0,
-       0x21f50012,
-       0x27f10215,
-       0x23f047fc,
-       0x0020d002,
+       0x0007f116,
+       0x0203f081,
+       0xbd0003d0,
+       0x40008004,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x09aa: ctx_xfer */
+       0xe7f000f8,
+       0x0007f104,
+       0x0303f002,
+       0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+       0x00e7f104,
+       0x03e3f000,
+       0xf100eecf,
+       0xf42000e4,
+       0x11f4f21b,
+       0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+       0xf510f7f0,
+       0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+       0xf7f01c11,
+       0x7f21f502,
+       0x9121f507,
+       0xa621f507,
+       0xf5f4bd07,
+       0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+       0x98082421,
+       0x24bd1601,
+       0x050007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1021fb9,
+       0xf0a500e7,
+       0x21f441e3,
+       0x01fcf09d,
+       0xb6022cf0,
+       0xf2fd0124,
+       0x02ffb905,
+       0xa504e7f1,
+       0xf441e3f0,
+       0x21f59d21,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xb6012cf0,
-       0x12d00320,
-       0x01acf000,
-       0xf006a5f0,
-       0x0c9800b7,
-       0x010d9800,
-       0xf500e7f0,
-       0xf0016621,
-       0x21f508a7,
-       0x21f50109,
-       0x01f40215,
-       0x0ca7f022,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-       0xfd0012cf,
-       0x1bf40522,
-       0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-       0xf502f7f0,
-       0xbd062b21,
-       0x6c21f5f4,
-       0x3421f506,
-       0x3a21f502,
-       0xf5f4bd06,
-       0xf4062b21,
-       0x01981011,
-       0x0511fd40,
-       0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-       0xf807b721,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x06a5f001,
+       0x9800b7f0,
+       0x0d98000c,
+       0x00e7f001,
+       0x016f21f5,
+       0xf508a7f0,
+       0xf5011021,
+       0xf4025e21,
+       0xa7f01301,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+       0xf7f02e02,
+       0x7f21f502,
+       0xf5f4bd07,
+       0xf507de21,
+       0xf5027f21,
+       0xbd079121,
+       0x7f21f5f4,
+       0x1011f407,
+       0xfd400198,
+       0x0bf40511,
+       0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+       0x0000f809,
        0x00000000,
        0x00000000,
        0x00000000,
index 438506d1474992af9d35ee538282594984a4d81f..229c0ae3722844c16d39e33fb669b677bcefa13c 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvf0_grhub_data[] = {
 };
 
 uint32_t nvf0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvf0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f03700,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f03700,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f037,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf0370007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f03700,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvf0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvf0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0x7f21f502,
+       0x9121f507,
+       0x10f7f007,
+       0x07de21f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x07de21f5,
+       0xf500f7f0,
+       0xf1077f21,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nvf0_grhub_code[] = {
        0x300007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x370007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x370007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd0801,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf0370007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f03700,
-       0x0009d002,
-       0x31f404bd,
-       0x0121f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x080121f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1080121,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f037,
+       0xbd0009d0,
+       0x0131f404,
+       0x09aa21f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x370007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09aa21,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09aa21f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd0801,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x4221f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf0370007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f030,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x300007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4170s */
-       0xf101f800,
-       0xf04170e7,
-       0xf5f040e3,
-       0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+       0xf001f800,
+       0xffb910f5,
+       0x70e7f102,
+       0x40e3f041,
+       0xf89d21f4,
+/* 0x0791: ctx_4170w */
+       0x70e7f100,
+       0x40e3f041,
+       0xb96821f4,
+       0xf4f002ff,
+       0xf01bf410,
+/* 0x07a6: ctx_redswitch */
        0xe7f100f8,
-       0xe3f04170,
-       0x6821f440,
-       0xf410f4f0,
+       0xe5f00200,
+       0x20e5f040,
+       0xf110e5f0,
+       0xf0850007,
+       0x0ed00103,
+       0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+       0xf2b608f7,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000e,
+/* 0x07de: ctx_86c */
+       0x07f100f8,
+       0x03f02300,
+       0x000fd002,
+       0xffb904bd,
+       0x14e7f102,
+       0x40e3f08a,
+       0xb99d21f4,
+       0xe7f102ff,
+       0xe3f0a88c,
+       0x9d21f441,
+/* 0x0806: ctx_mem */
+       0x07f100f8,
+       0x03f08400,
+       0x000fd002,
+/* 0x0812: ctx_mem_wait */
+       0xf7f104bd,
+       0xf3f08400,
+       0x00ffcf02,
+       0xf405fffd,
        0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-       0x0614e7f1,
-       0xf106e4b6,
-       0xd00270f7,
-       0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-       0x01f2b608,
-       0xf1fd1bf4,
-       0xd00770f7,
-       0x00f800ef,
-/* 0x066c: ctx_86c */
-       0x086ce7f1,
-       0xd006e4b6,
-       0xe7f100ef,
-       0xe3f08a14,
-       0x8d21f440,
-       0xa86ce7f1,
-       0xf441e3f0,
-       0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
        0x99f094bd,
        0x0007f105,
        0x0203f037,
        0xbd0009d0,
        0x0ca7f004,
-       0xf1c921f4,
-       0xb60a2417,
-       0x10d00614,
-       0x0037f100,
-       0x0634b60b,
-       0xf14032d0,
-       0xb60a0c17,
-       0x47f00614,
-       0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-       0xcf4014d0,
-       0x44f04014,
-       0xfa1bf41f,
-       0xfe0032d0,
-       0x2af0000b,
-       0x0424b61f,
-       0xbd0220b6,
+       0xbdd021f4,
+       0x0007f1f4,
+       0x0203f089,
+       0xbd000fd0,
+       0x0007f104,
+       0x0203f0c1,
+       0xbd0002d0,
+       0x0007f104,
+       0x0203f083,
+       0xbd0002d0,
+       0x07f7f004,
+       0x080621f5,
+       0xc00007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf0000bfe,
+       0x24b61f2a,
+       0x0220b604,
+       0x99f094bd,
+       0x0007f108,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f081,
+       0xbd0002d0,
+       0x0027f104,
+       0x0023f100,
+       0x0225f080,
+       0x880007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf11017f0,
+       0xf0020027,
+       0x12fa0223,
+       0xbd03f805,
        0x0899f094,
-       0x370007f1,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0a0417f1,
-       0xd00614b6,
-       0x17f10012,
-       0x14b60a20,
-       0x0227f006,
-       0x800023f1,
-       0xf00012d0,
-       0x27f11017,
-       0x23f00200,
-       0x0512fa02,
-       0x94bd03f8,
-       0xf10899f0,
-       0xf0170007,
+       0xb6810198,
+       0x02981814,
+       0x0825b680,
+       0x800512fd,
+       0x94bd1601,
+       0xf10999f0,
+       0xf0370007,
        0x09d00203,
-       0x9804bd00,
-       0x14b68101,
-       0x80029818,
-       0xfd0825b6,
-       0x01800512,
-       0xf094bd16,
-       0x07f10999,
-       0x03f03700,
-       0x0009d002,
-       0x27f104bd,
-       0x24b60a04,
-       0x0021d006,
-       0xf10127f0,
-       0xb60a2017,
-       0x12d00614,
-       0x0017f100,
-       0x0613f001,
-       0xf80501fa,
-       0xf094bd03,
-       0x07f10999,
-       0x03f01700,
-       0x0009d002,
-       0x94bd04bd,
-       0xf10599f0,
+       0xf104bd00,
+       0xf0810007,
+       0x01d00203,
+       0xf004bd00,
+       0x07f10127,
+       0x03f08800,
+       0x0002d002,
+       0x17f104bd,
+       0x13f00100,
+       0x0501fa06,
+       0x94bd03f8,
+       0xf10999f0,
        0xf0170007,
        0x09d00203,
-       0xf804bd00,
-/* 0x0795: ctx_chan */
-       0x8c21f500,
-       0x0ca7f006,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-       0xfd0012cf,
-       0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-       0x9800f8fa,
-       0x27f14103,
-       0x24b60a04,
-       0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+       0xbd04bd00,
+       0x0599f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x0942: ctx_chan */
+       0x21f500f8,
+       0xa7f00824,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+       0x41039800,
+       0x810007f1,
+       0xd00203f0,
+       0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
        0x34c434bd,
        0x0f1bf4ff,
        0x020057f1,
        0xfa0653f0,
        0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
        0x98804e98,
        0x21f4814f,
-       0x0830b68d,
+       0x0830b69d,
        0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
        0x0398df1b,
-       0x0023d016,
-       0xf1400080,
-       0xf0010017,
-       0x01fa0613,
-       0xf803f806,
-/* 0x0801: ctx_xfer */
-       0x00f7f100,
-       0x06f4b60c,
-       0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-       0xfecf80fe,
-       0x00e4f100,
-       0xf91bf420,
-       0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-       0xf7f00d02,
-       0x6c21f510,
-       0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-       0xf502f7f0,
-       0xf5062b21,
-       0xf5063a21,
-       0xbd064c21,
-       0x2b21f5f4,
-       0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-       0x16019806,
-       0x041427f1,
-       0xd00624b6,
-       0xe7f10020,
-       0xe3f0a500,
-       0x021fb941,
-       0xb68d21f4,
-       0xfcf004e0,
-       0x022cf001,
-       0xfd0124b6,
-       0x21f405f2,
-       0xfc17f18d,
-       0x0213f04a,
-       0xd00c27f0,
-       0x21f50012,
-       0x27f10215,
-       0x23f047fc,
-       0x0020d002,
+       0x0007f116,
+       0x0203f081,
+       0xbd0003d0,
+       0x40008004,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x09aa: ctx_xfer */
+       0xe7f000f8,
+       0x0007f104,
+       0x0303f002,
+       0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+       0x00e7f104,
+       0x03e3f000,
+       0xf100eecf,
+       0xf42000e4,
+       0x11f4f21b,
+       0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+       0xf510f7f0,
+       0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+       0xf7f01c11,
+       0x7f21f502,
+       0x9121f507,
+       0xa621f507,
+       0xf5f4bd07,
+       0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+       0x98082421,
+       0x24bd1601,
+       0x050007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1021fb9,
+       0xf0a500e7,
+       0x21f441e3,
+       0x01fcf09d,
+       0xb6022cf0,
+       0xf2fd0124,
+       0x02ffb905,
+       0xa504e7f1,
+       0xf441e3f0,
+       0x21f59d21,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xb6012cf0,
-       0x12d00320,
-       0x01acf000,
-       0xf006a5f0,
-       0x0c9800b7,
-       0x010d9800,
-       0xf500e7f0,
-       0xf0016621,
-       0x21f508a7,
-       0x21f50109,
-       0x01f40215,
-       0x0ca7f022,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-       0xfd0012cf,
-       0x1bf40522,
-       0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-       0xf502f7f0,
-       0xbd062b21,
-       0x6c21f5f4,
-       0x3421f506,
-       0x3a21f502,
-       0xf5f4bd06,
-       0xf4062b21,
-       0x01981011,
-       0x0511fd40,
-       0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-       0xf807b721,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x06a5f001,
+       0x9800b7f0,
+       0x0d98000c,
+       0x00e7f001,
+       0x016f21f5,
+       0xf508a7f0,
+       0xf5011021,
+       0xf4025e21,
+       0xa7f01301,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+       0xf7f02e02,
+       0x7f21f502,
+       0xf5f4bd07,
+       0xf507de21,
+       0xf5027f21,
+       0xbd079121,
+       0x7f21f5f4,
+       0x1011f407,
+       0xfd400198,
+       0x0bf40511,
+       0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+       0x0000f809,
        0x00000000,
        0x00000000,
        0x00000000,
index 33a5a82eccbd6e8114f55d8d8766d22929474d80..6ffe28307dbd6e420a019d0e7dd4ac891f531fd7 100644 (file)
 #define GF117 0xd7
 #define GK100 0xe0
 #define GK110 0xf0
+#define GK208 0x108
 
+#define NV_PGRAPH_FECS_INTR_ACK                                        0x409004
+#define NV_PGRAPH_FECS_INTR                                            0x409008
+#define NV_PGRAPH_FECS_INTR_FWMTHD                                   0x00000400
+#define NV_PGRAPH_FECS_INTR_CHSW                                     0x00000100
+#define NV_PGRAPH_FECS_INTR_FIFO                                     0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE                                       0x40900c
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO                                0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL                          0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_EDGE                           0x00000000
+#define NV_PGRAPH_FECS_INTR_EN_SET                                     0x409010
+#define NV_PGRAPH_FECS_INTR_EN_SET_FIFO                              0x00000004
+#define NV_PGRAPH_FECS_INTR_ROUTE                                      0x40901c
+#define NV_PGRAPH_FECS_ACCESS                                          0x409048
+#define NV_PGRAPH_FECS_ACCESS_FIFO                                   0x00000002
+#define NV_PGRAPH_FECS_FIFO_DATA                                       0x409064
+#define NV_PGRAPH_FECS_FIFO_CMD                                        0x409068
+#define NV_PGRAPH_FECS_FIFO_ACK                                        0x409074
+#define NV_PGRAPH_FECS_CAPS                                            0x409108
 #define NV_PGRAPH_FECS_SIGNAL                                          0x409400
+#define NV_PGRAPH_FECS_IROUTE                                          0x409404
+#define NV_PGRAPH_FECS_BAR_MASK0                                       0x40940c
+#define NV_PGRAPH_FECS_BAR_MASK1                                       0x409410
+#define NV_PGRAPH_FECS_BAR                                             0x409414
+#define NV_PGRAPH_FECS_BAR_SET                                         0x409418
+#define NV_PGRAPH_FECS_RED_SWITCH                                      0x409614
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP                         0x00000400
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC                         0x00000200
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN                        0x00000100
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP                          0x00000040
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC                          0x00000020
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN                         0x00000010
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_GPC                          0x00000002
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_MAIN                         0x00000001
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_BASE                                      0x409710
+#define NV_PGRAPH_FECS_MMCTX_CTRL                                      0x409714
+#define NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE                              0x409718
+#define NV_PGRAPH_FECS_MMCTX_MULTI_MASK                                0x40971c
+#define NV_PGRAPH_FECS_MMCTX_QUEUE                                     0x409720
+#define NV_PGRAPH_FECS_MMIO_CTRL                                       0x409728
+#define NV_PGRAPH_FECS_MMIO_RDVAL                                      0x40972c
+#define NV_PGRAPH_FECS_MMIO_WRVAL                                      0x409730
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
 #if CHIPSET < GK110
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x409820)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40986c
 #else
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40988c
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x4098c0)
 #endif
+#define NV_PGRAPH_FECS_STRANDS_CNT                                     0x409880
+#define NV_PGRAPH_FECS_STRAND_SAVE_SWBASE                              0x409908
+#define NV_PGRAPH_FECS_STRAND_LOAD_SWBASE                              0x40990c
+#define NV_PGRAPH_FECS_STRAND_WORDS                                    0x409910
+#define NV_PGRAPH_FECS_STRAND_DATA                                     0x409918
+#define NV_PGRAPH_FECS_STRAND_SELECT                                   0x40991c
+#define NV_PGRAPH_FECS_STRAND_CMD                                      0x409928
+#define NV_PGRAPH_FECS_STRAND_CMD_SEEK                               0x00000001
+#define NV_PGRAPH_FECS_STRAND_CMD_GET_INFO                           0x00000002
+#define NV_PGRAPH_FECS_STRAND_CMD_SAVE                               0x00000003
+#define NV_PGRAPH_FECS_STRAND_CMD_LOAD                               0x00000004
+#define NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER                    0x0000000a
+#define NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER                  0x0000000b
+#define NV_PGRAPH_FECS_STRAND_CMD_ENABLE                             0x0000000c
+#define NV_PGRAPH_FECS_STRAND_CMD_DISABLE                            0x0000000d
+#define NV_PGRAPH_FECS_STRAND_FILTER                                   0x40993c
+#define NV_PGRAPH_FECS_MEM_BASE                                        0x409a04
+#define NV_PGRAPH_FECS_MEM_CHAN                                        0x409a0c
+#define NV_PGRAPH_FECS_MEM_CMD                                         0x409a10
+#define NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN                             0x00000007
+#define NV_PGRAPH_FECS_MEM_TARGET                                      0x409a20
+#define NV_PGRAPH_FECS_MEM_TARGET_UNK31                              0x80000000
+#define NV_PGRAPH_FECS_MEM_TARGET_AS                                 0x0000001f
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VM                              0x00000001
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM                            0x00000002
+#define NV_PGRAPH_FECS_CHAN_ADDR                                       0x409b00
+#define NV_PGRAPH_FECS_CHAN_NEXT                                       0x409b04
+#define NV_PGRAPH_FECS_CHSW                                            0x409b0c
+#define NV_PGRAPH_FECS_CHSW_ACK                                      0x00000001
 #define NV_PGRAPH_FECS_INTR_UP_SET                                     0x409c1c
+#define NV_PGRAPH_FECS_INTR_UP_EN                                      0x409c24
 
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ACK                                  0x41a004
+#define NV_PGRAPH_GPCX_GPCCS_INTR                                      0x41a008
+#define NV_PGRAPH_GPCX_GPCCS_INTR_FIFO                               0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET                               0x41a010
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO                        0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE                                0x41a01c
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS                                    0x41a048
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO                             0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_DATA                                 0x41a064
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD                                  0x41a068
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK                                  0x41a074
+#define NV_PGRAPH_GPCX_GPCCS_UNITS                                     0x41a608
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH                                0x41a614
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11                        0x00000800
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE                       0x00000200
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER                        0x00000020
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_PAUSE                        0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_MYINDEX                                   0x41a618
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE                         0x41a700
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE                         0x41a704
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT                          0x41a74c
 #if CHIPSET < GK110
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a820)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a86c
 #else
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a88c
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a8c0)
 #endif
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT                             0x41a91c
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD                                0x41a928
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE                         0x00000003
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_LOAD                         0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_MEM_BASE                                  0x41aa04
 
 #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r)
 #define queue_init      .skip 72 // (2 * 4) + ((8 * 4) * 2)
 #define T_LCHAN   8
 #define T_LCTXH   9
 
-#define nv_mkmm(rv,r) /*
-*/     movw rv  ((r) & 0x0000fffc) /*
-*/     sethi rv ((r) & 0x00ff0000)
+#if CHIPSET < GK208
+#define imm32(reg,val) /*
+*/     movw reg  ((val) & 0x0000ffff) /*
+*/     sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/     mov reg (val)
+#endif
+
 #define nv_mkio(rv,r,i) /*
-*/     nv_mkmm(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+*/     imm32(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+
+#define hash #
+#define fn(a) a
+#if CHIPSET < GK208
+#define call(a) call fn(hash)a
+#else
+#define call(a) lcall fn(hash)a
+#endif
 
 #define nv_iord(rv,r,i) /*
 */     nv_mkio(rv,r,i) /*
 */     iord rv I[rv]
+
 #define nv_iowr(r,i,rv) /*
 */     nv_mkio($r0,r,i) /*
 */     iowr I[$r0] rv /*
 */     clear b32 $r0
 
+#define nv_rd32(reg,addr) /*
+*/     imm32($r14, addr) /*
+*/     call(nv_rd32) /*
+*/     mov b32 reg $r15
+
+#define nv_wr32(addr,reg) /*
+*/     mov b32 $r15 reg /*
+*/     imm32($r14, addr) /*
+*/     call(nv_wr32)
+
 #define trace_set(bit) /*
 */     clear b32 $r9 /*
 */     bset $r9 bit /*
 */     nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_SET(7), 0, $r9)
+
 #define trace_clr(bit) /*
 */     clear b32 $r9 /*
 */     bset $r9 bit /*
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
new file mode 100644 (file)
index 0000000..e1af65e
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+/*******************************************************************************
+ * Graphics object classes
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nv108_graph_sclass[] = {
+       { 0x902d, &nouveau_object_ofuncs },
+       { 0xa140, &nouveau_object_ofuncs },
+       { 0xa197, &nouveau_object_ofuncs },
+       { 0xa1c0, &nouveau_object_ofuncs },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static struct nvc0_graph_init
+nv108_graph_init_regs[] = {
+       { 0x400080,   1, 0x04, 0x003083c2 },
+       { 0x400088,   1, 0x04, 0x0001bfe7 },
+       { 0x40008c,   1, 0x04, 0x00000000 },
+       { 0x400090,   1, 0x04, 0x00000030 },
+       { 0x40013c,   1, 0x04, 0x003901f7 },
+       { 0x400140,   1, 0x04, 0x00000100 },
+       { 0x400144,   1, 0x04, 0x00000000 },
+       { 0x400148,   1, 0x04, 0x00000110 },
+       { 0x400138,   1, 0x04, 0x00000000 },
+       { 0x400130,   2, 0x04, 0x00000000 },
+       { 0x400124,   1, 0x04, 0x00000002 },
+       {}
+};
+
+struct nvc0_graph_init
+nv108_graph_init_unk58xx[] = {
+       { 0x405844,   1, 0x04, 0x00ffffff },
+       { 0x405850,   1, 0x04, 0x00000000 },
+       { 0x405900,   1, 0x04, 0x00000000 },
+       { 0x405908,   1, 0x04, 0x00000000 },
+       { 0x405928,   1, 0x04, 0x00000000 },
+       { 0x40592c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_gpc[] = {
+       { 0x418408,   1, 0x04, 0x00000000 },
+       { 0x4184a0,   3, 0x04, 0x00000000 },
+       { 0x418604,   1, 0x04, 0x00000000 },
+       { 0x418680,   1, 0x04, 0x00000000 },
+       { 0x418714,   1, 0x04, 0x00000000 },
+       { 0x418384,   2, 0x04, 0x00000000 },
+       { 0x418814,   3, 0x04, 0x00000000 },
+       { 0x418b04,   1, 0x04, 0x00000000 },
+       { 0x4188c8,   2, 0x04, 0x00000000 },
+       { 0x4188d0,   1, 0x04, 0x00010000 },
+       { 0x4188d4,   1, 0x04, 0x00000201 },
+       { 0x418910,   1, 0x04, 0x00010001 },
+       { 0x418914,   1, 0x04, 0x00000301 },
+       { 0x418918,   1, 0x04, 0x00800000 },
+       { 0x418980,   1, 0x04, 0x77777770 },
+       { 0x418984,   3, 0x04, 0x77777777 },
+       { 0x418c04,   1, 0x04, 0x00000000 },
+       { 0x418c64,   2, 0x04, 0x00000000 },
+       { 0x418c88,   1, 0x04, 0x00000000 },
+       { 0x418cb4,   2, 0x04, 0x00000000 },
+       { 0x418d00,   1, 0x04, 0x00000000 },
+       { 0x418d28,   2, 0x04, 0x00000000 },
+       { 0x418f00,   1, 0x04, 0x00000400 },
+       { 0x418f08,   1, 0x04, 0x00000000 },
+       { 0x418f20,   2, 0x04, 0x00000000 },
+       { 0x418e00,   1, 0x04, 0x00000000 },
+       { 0x418e08,   1, 0x04, 0x00000000 },
+       { 0x418e1c,   2, 0x04, 0x00000000 },
+       { 0x41900c,   1, 0x04, 0x00000000 },
+       { 0x419018,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_tpc[] = {
+       { 0x419d0c,   1, 0x04, 0x00000000 },
+       { 0x419d10,   1, 0x04, 0x00000014 },
+       { 0x419ab0,   1, 0x04, 0x00000000 },
+       { 0x419ac8,   1, 0x04, 0x00000000 },
+       { 0x419ab8,   1, 0x04, 0x000000e7 },
+       { 0x419abc,   2, 0x04, 0x00000000 },
+       { 0x419ab4,   1, 0x04, 0x00000000 },
+       { 0x419aa8,   2, 0x04, 0x00000000 },
+       { 0x41980c,   1, 0x04, 0x00000010 },
+       { 0x419844,   1, 0x04, 0x00000000 },
+       { 0x419850,   1, 0x04, 0x00000004 },
+       { 0x419854,   2, 0x04, 0x00000000 },
+       { 0x419c98,   1, 0x04, 0x00000000 },
+       { 0x419ca8,   1, 0x04, 0x00000000 },
+       { 0x419cb0,   1, 0x04, 0x01000000 },
+       { 0x419cb4,   1, 0x04, 0x00000000 },
+       { 0x419cb8,   1, 0x04, 0x00b08bea },
+       { 0x419c84,   1, 0x04, 0x00010384 },
+       { 0x419cbc,   1, 0x04, 0x281b3646 },
+       { 0x419cc0,   2, 0x04, 0x00000000 },
+       { 0x419c80,   1, 0x04, 0x00000230 },
+       { 0x419ccc,   2, 0x04, 0x00000000 },
+       { 0x419c0c,   1, 0x04, 0x00000000 },
+       { 0x419e00,   1, 0x04, 0x00000080 },
+       { 0x419ea0,   1, 0x04, 0x00000000 },
+       { 0x419ee4,   1, 0x04, 0x00000000 },
+       { 0x419ea4,   1, 0x04, 0x00000100 },
+       { 0x419ea8,   1, 0x04, 0x00000000 },
+       { 0x419eb4,   1, 0x04, 0x00000000 },
+       { 0x419ebc,   2, 0x04, 0x00000000 },
+       { 0x419edc,   1, 0x04, 0x00000000 },
+       { 0x419f00,   1, 0x04, 0x00000000 },
+       { 0x419ed0,   1, 0x04, 0x00003234 },
+       { 0x419f74,   1, 0x04, 0x00015555 },
+       { 0x419f80,   4, 0x04, 0x00000000 },
+       {}
+};
+
+static int
+nv108_graph_fini(struct nouveau_object *object, bool suspend)
+{
+       struct nvc0_graph_priv *priv = (void *)object;
+       static const struct {
+               u32 addr;
+               u32 data;
+       } magic[] = {
+               { 0x020520, 0xfffffffc },
+               { 0x020524, 0xfffffffe },
+               { 0x020524, 0xfffffffc },
+               { 0x020524, 0xfffffff8 },
+               { 0x020524, 0xffffffe0 },
+               { 0x020530, 0xfffffffe },
+               { 0x02052c, 0xfffffffa },
+               { 0x02052c, 0xfffffff0 },
+               { 0x02052c, 0xffffffc0 },
+               { 0x02052c, 0xffffff00 },
+               { 0x02052c, 0xfffffc00 },
+               { 0x02052c, 0xfffcfc00 },
+               { 0x02052c, 0xfff0fc00 },
+               { 0x02052c, 0xff80fc00 },
+               { 0x020528, 0xfffffffe },
+               { 0x020528, 0xfffffffc },
+       };
+       int i;
+
+       nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
+       nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000);
+       for (i = 0; i < ARRAY_SIZE(magic); i++) {
+               nv_wr32(priv, magic[i].addr, magic[i].data);
+               nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000);
+       }
+
+       return nouveau_graph_fini(&priv->base, suspend);
+}
+
+static struct nvc0_graph_init *
+nv108_graph_init_mmio[] = {
+       nv108_graph_init_regs,
+       nvf0_graph_init_unk40xx,
+       nvc0_graph_init_unk44xx,
+       nvc0_graph_init_unk78xx,
+       nvc0_graph_init_unk60xx,
+       nvd9_graph_init_unk64xx,
+       nv108_graph_init_unk58xx,
+       nvc0_graph_init_unk80xx,
+       nvf0_graph_init_unk70xx,
+       nvf0_graph_init_unk5bxx,
+       nv108_graph_init_gpc,
+       nv108_graph_init_tpc,
+       nve4_graph_init_unk,
+       nve4_graph_init_unk88xx,
+       NULL
+};
+
+#include "fuc/hubnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_fecs_ucode = {
+       .code.data = nv108_grhub_code,
+       .code.size = sizeof(nv108_grhub_code),
+       .data.data = nv108_grhub_data,
+       .data.size = sizeof(nv108_grhub_data),
+};
+
+#include "fuc/gpcnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_gpccs_ucode = {
+       .code.data = nv108_grgpc_code,
+       .code.size = sizeof(nv108_grgpc_code),
+       .data.data = nv108_grgpc_data,
+       .data.size = sizeof(nv108_grgpc_data),
+};
+
+struct nouveau_oclass *
+nv108_graph_oclass = &(struct nvc0_graph_oclass) {
+       .base.handle = NV_ENGINE(GR, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_ctor,
+               .dtor = nvc0_graph_dtor,
+               .init = nve4_graph_init,
+               .fini = nv108_graph_fini,
+       },
+       .cclass = &nv108_grctx_oclass,
+       .sclass =  nv108_graph_sclass,
+       .mmio = nv108_graph_init_mmio,
+       .fecs.ucode = &nv108_graph_fecs_ucode,
+       .gpccs.ucode = &nv108_graph_gpccs_ucode,
+}.base;
index 03de5175dd9f8bcdb1a2ad48c18de965cf31a3c1..30ed19c52e05ca0cd6a1e759a8fc426f61f246a7 100644 (file)
@@ -304,12 +304,28 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine)
        return timeout ? -EBUSY : 0;
 }
 
-static const struct nouveau_enum nv50_mp_exec_error_names[] = {
-       { 3, "STACK_UNDERFLOW", NULL },
-       { 4, "QUADON_ACTIVE", NULL },
-       { 8, "TIMEOUT", NULL },
-       { 0x10, "INVALID_OPCODE", NULL },
-       { 0x40, "BREAKPOINT", NULL },
+static const struct nouveau_bitfield nv50_mp_exec_errors[] = {
+       { 0x01, "STACK_UNDERFLOW" },
+       { 0x02, "STACK_MISMATCH" },
+       { 0x04, "QUADON_ACTIVE" },
+       { 0x08, "TIMEOUT" },
+       { 0x10, "INVALID_OPCODE" },
+       { 0x20, "PM_OVERFLOW" },
+       { 0x40, "BREAKPOINT" },
+       {}
+};
+
+static const struct nouveau_bitfield nv50_mpc_traps[] = {
+       { 0x0000001, "LOCAL_LIMIT_READ" },
+       { 0x0000010, "LOCAL_LIMIT_WRITE" },
+       { 0x0000040, "STACK_LIMIT" },
+       { 0x0000100, "GLOBAL_LIMIT_READ" },
+       { 0x0001000, "GLOBAL_LIMIT_WRITE" },
+       { 0x0010000, "MP0" },
+       { 0x0020000, "MP1" },
+       { 0x0040000, "GLOBAL_LIMIT_RED" },
+       { 0x0400000, "GLOBAL_LIMIT_ATOM" },
+       { 0x4000000, "MP2" },
        {}
 };
 
@@ -396,6 +412,60 @@ static const struct nouveau_bitfield nv50_graph_intr_name[] = {
        {}
 };
 
+static const struct nouveau_bitfield nv50_graph_trap_prop[] = {
+       { 0x00000004, "SURF_WIDTH_OVERRUN" },
+       { 0x00000008, "SURF_HEIGHT_OVERRUN" },
+       { 0x00000010, "DST2D_FAULT" },
+       { 0x00000020, "ZETA_FAULT" },
+       { 0x00000040, "RT_FAULT" },
+       { 0x00000080, "CUDA_FAULT" },
+       { 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
+       { 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
+       { 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
+       { 0x00000800, "DST2D_LINEAR_MISMATCH" },
+       { 0x00001000, "RT_LINEAR_MISMATCH" },
+       {}
+};
+
+static void
+nv50_priv_prop_trap(struct nv50_graph_priv *priv,
+                   u32 ustatus_addr, u32 ustatus, u32 tp)
+{
+       u32 e0c = nv_rd32(priv, ustatus_addr + 0x04);
+       u32 e10 = nv_rd32(priv, ustatus_addr + 0x08);
+       u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c);
+       u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
+       u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
+       u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
+       u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
+
+       /* CUDA memory: l[], g[] or stack. */
+       if (ustatus & 0x00000080) {
+               if (e18 & 0x80000000) {
+                       /* g[] read fault? */
+                       nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
+                                        tp, e14, e10 | ((e18 >> 24) & 0x1f));
+                       e18 &= ~0x1f000000;
+               } else if (e18 & 0xc) {
+                       /* g[] write fault? */
+                       nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
+                                tp, e14, e10 | ((e18 >> 7) & 0x1f));
+                       e18 &= ~0x00000f80;
+               } else {
+                       nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
+                                tp, e14, e10);
+               }
+               ustatus &= ~0x00000080;
+       }
+       if (ustatus) {
+               nv_error(priv, "TRAP_PROP - TP %d -", tp);
+               nouveau_bitfield_print(nv50_graph_trap_prop, ustatus);
+               pr_cont(" - Address %02x%08x\n", e14, e10);
+       }
+       nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+                tp, e0c, e18, e1c, e20, e24);
+}
+
 static void
 nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
 {
@@ -420,8 +490,8 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
                        oplow = nv_rd32(priv, addr + 0x70);
                        ophigh = nv_rd32(priv, addr + 0x74);
                        nv_error(priv, "TRAP_MP_EXEC - "
-                                       "TP %d MP %d: ", tpid, i);
-                       nouveau_enum_print(nv50_mp_exec_error_names, status);
+                                       "TP %d MP %d:", tpid, i);
+                       nouveau_bitfield_print(nv50_mp_exec_errors, status);
                        pr_cont(" at %06x warp %d, opcode %08x %08x\n",
                                        pc&0xffffff, pc >> 24,
                                        oplow, ophigh);
@@ -468,60 +538,19 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
                                nv50_priv_mp_trap(priv, i, display);
                                ustatus &= ~0x04030000;
                        }
-                       break;
-               case 8: /* TPDMA error */
-                       {
-                       u32 e0c = nv_rd32(priv, ustatus_addr + 4);
-                       u32 e10 = nv_rd32(priv, ustatus_addr + 8);
-                       u32 e14 = nv_rd32(priv, ustatus_addr + 0xc);
-                       u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
-                       u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
-                       u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
-                       u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
-                       /* 2d engine destination */
-                       if (ustatus & 0x00000010) {
-                               if (display) {
-                                       nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
-                                                       i, e14, e10);
-                                       nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000010;
-                       }
-                       /* Render target */
-                       if (ustatus & 0x00000040) {
-                               if (display) {
-                                       nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
-                                                       i, e14, e10);
-                                       nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000040;
-                       }
-                       /* CUDA memory: l[], g[] or stack. */
-                       if (ustatus & 0x00000080) {
-                               if (display) {
-                                       if (e18 & 0x80000000) {
-                                               /* g[] read fault? */
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
-                                                               i, e14, e10 | ((e18 >> 24) & 0x1f));
-                                               e18 &= ~0x1f000000;
-                                       } else if (e18 & 0xc) {
-                                               /* g[] write fault? */
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
-                                                               i, e14, e10 | ((e18 >> 7) & 0x1f));
-                                               e18 &= ~0x00000f80;
-                                       } else {
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
-                                                               i, e14, e10);
-                                       }
-                                       nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000080;
-                       }
+                       if (ustatus && display) {
+                               nv_error("%s - TP%d:", name, i);
+                               nouveau_bitfield_print(nv50_mpc_traps, ustatus);
+                               pr_cont("\n");
+                               ustatus = 0;
                        }
                        break;
+               case 8: /* PROP error */
+                       if (display)
+                               nv50_priv_prop_trap(
+                                               priv, ustatus_addr, ustatus, i);
+                       ustatus = 0;
+                       break;
                }
                if (ustatus) {
                        if (display)
@@ -727,11 +756,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
                status &= ~0x080;
        }
 
-       /* TPDMA:  Handles TP-initiated uncached memory accesses:
+       /* PROP:  Handles TP-initiated uncached memory accesses:
         * l[], g[], stack, 2d surfaces, render targets. */
        if (status & 0x100) {
                nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display,
-                                   "TRAP_TPDMA");
+                                   "TRAP_PROP");
                nv_wr32(priv, 0x400108, 0x100);
                status &= ~0x100;
        }
@@ -760,7 +789,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
        u32 mthd = (addr & 0x00001ffc);
        u32 data = nv_rd32(priv, 0x400708);
        u32 class = nv_rd32(priv, 0x400814);
-       u32 show = stat;
+       u32 show = stat, show_bitfield = stat;
        int chid;
 
        engctx = nouveau_engctx_get(engine, inst);
@@ -778,21 +807,26 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
                nv_error(priv, "DATA_ERROR ");
                nouveau_enum_print(nv50_data_error_names, ecode);
                pr_cont("\n");
+               show_bitfield &= ~0x00100000;
        }
 
        if (stat & 0x00200000) {
                if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,
                                engctx))
                        show &= ~0x00200000;
+               show_bitfield &= ~0x00200000;
        }
 
        nv_wr32(priv, 0x400100, stat);
        nv_wr32(priv, 0x400500, 0x00010001);
 
        if (show) {
-               nv_error(priv, "%s", "");
-               nouveau_bitfield_print(nv50_graph_intr_name, show);
-               pr_cont("\n");
+               show &= show_bitfield;
+               if (show) {
+                       nv_error(priv, "%s", "");
+                       nouveau_bitfield_print(nv50_graph_intr_name, show);
+                       pr_cont("\n");
+               }
                nv_error(priv,
                         "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
                         chid, (u64)inst << 12, nouveau_client_name(engctx),
index 434bb4b0fa2e650a130a98cc940f5ca7727cfeac..a73ab209ea88c85121fe3580e9daa189b29de46e 100644 (file)
@@ -334,7 +334,7 @@ nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds)
        while ((mthd = &mthds[i++]) && (init = mthd->init)) {
                u32  addr = 0x80000000 | mthd->oclass;
                for (data = 0; init->count; init++) {
-                       if (data != init->data) {
+                       if (init == mthd->init || data != init->data) {
                                nv_wr32(priv, 0x40448c, init->data);
                                data = init->data;
                        }
@@ -901,6 +901,9 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
                }
 
                return 0;
+       } else
+       if (!oclass->fecs.ucode) {
+               return -ENOSYS;
        }
 
        /* load HUB microcode */
index ea17a80ad7fce3d7bcee48013ac6ba8c65acc4c7..b0ab6de270b2ea9d148b483b8249bc11efa27496 100644 (file)
@@ -205,6 +205,11 @@ extern struct nvc0_graph_init nve4_graph_init_regs[];
 extern struct nvc0_graph_init nve4_graph_init_unk[];
 extern struct nvc0_graph_init nve4_graph_init_unk88xx[];
 
+extern struct nvc0_graph_init nvf0_graph_init_unk40xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk70xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_graph_init_tpc[];
+
 int  nvc0_grctx_generate(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
@@ -266,6 +271,11 @@ extern struct nvc0_graph_init nve4_grctx_init_unk80xx[];
 extern struct nvc0_graph_init nve4_grctx_init_unk90xx[];
 
 extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nvc0_graph_init nvf0_grctx_init_unk44xx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk60xx[];
+
+extern struct nouveau_oclass *nv108_grctx_oclass;
 
 #define mmio_data(s,a,p) do {                                                  \
        info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
index 2f0ac78322345a0d5dd997f5dc3d83327ba4b809..b1acb9939d95cfe460cea8e9aa2475d85256c20f 100644 (file)
@@ -41,7 +41,7 @@ nvf0_graph_sclass[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk40xx[] = {
        { 0x40415c,   1, 0x04, 0x00000000 },
        { 0x404170,   1, 0x04, 0x00000000 },
@@ -60,7 +60,7 @@ nvf0_graph_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk70xx[] = {
        { 0x407010,   1, 0x04, 0x00000000 },
        { 0x407040,   1, 0x04, 0x80440424 },
@@ -68,7 +68,7 @@ nvf0_graph_init_unk70xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk5bxx[] = {
        { 0x405b44,   1, 0x04, 0x00000000 },
        { 0x405b50,   1, 0x04, 0x00000000 },
@@ -114,7 +114,7 @@ nvf0_graph_init_gpc[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_tpc[] = {
        { 0x419d0c,   1, 0x04, 0x00000000 },
        { 0x419d10,   1, 0x04, 0x00000014 },
@@ -243,6 +243,6 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
        .cclass = &nvf0_grctx_oclass,
        .sclass =  nvf0_graph_sclass,
        .mmio = nvf0_graph_init_mmio,
-       .fecs.ucode = 0 ? &nvf0_graph_fecs_ucode : NULL,
+       .fecs.ucode = &nvf0_graph_fecs_ucode,
        .gpccs.ucode = &nvf0_graph_gpccs_ucode,
 }.base;
index ac2881d1776ac1a071371a84f379ea57ea8ee856..7b8ea221b00dc7bf0d88021fc5443ae059401cbb 100644 (file)
@@ -38,7 +38,8 @@ enum nv_subdev_type {
        NVDEV_SUBDEV_THERM,
        NVDEV_SUBDEV_CLOCK,
 
-       NVDEV_ENGINE_DMAOBJ,
+       NVDEV_ENGINE_FIRST,
+       NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
        NVDEV_ENGINE_FIFO,
        NVDEV_ENGINE_SW,
        NVDEV_ENGINE_GR,
@@ -70,6 +71,7 @@ struct nouveau_device {
        const char *dbgopt;
        const char *name;
        const char *cname;
+       u64 disable_mask;
 
        enum {
                NV_04    = 0x04,
index 8c32cf4d83c78bb39773cd11233e59941da52699..26b6b2bb11121e28d4de88f08d4f308ab02fed7a 100644 (file)
@@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass;
 extern struct nouveau_oclass *nv84_fifo_oclass;
 extern struct nouveau_oclass *nvc0_fifo_oclass;
 extern struct nouveau_oclass *nve0_fifo_oclass;
+extern struct nouveau_oclass *nv108_fifo_oclass;
 
 void nv04_fifo_intr(struct nouveau_subdev *);
 int  nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *);
index 8e1b52312ddc5cb2675696223ea8344548452ef1..97705618de979e9fe1f810ca3ee5f557d5dd19e2 100644 (file)
@@ -69,6 +69,7 @@ extern struct nouveau_oclass *nvd7_graph_oclass;
 extern struct nouveau_oclass *nvd9_graph_oclass;
 extern struct nouveau_oclass *nve4_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
+extern struct nouveau_oclass *nv108_graph_oclass;
 
 extern const struct nouveau_bitfield nv04_graph_nsource[];
 extern struct nouveau_ofuncs nv04_graph_ofuncs;
index 4f4ff4502c3d2f284e2e6424abe05a923fbc6ff7..9faa98e67ad8c9057273eff0a7fc0f145799abf8 100644 (file)
@@ -4,8 +4,7 @@
 #include <core/subdev.h>
 #include <core/device.h>
 
-#include <subdev/fb.h>
-
+struct nouveau_mem;
 struct nouveau_vma;
 
 struct nouveau_bar {
@@ -29,27 +28,7 @@ nouveau_bar(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR];
 }
 
-#define nouveau_bar_create(p,e,o,d)                                            \
-       nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_bar_init(p)                                                    \
-       nouveau_subdev_init(&(p)->base)
-#define nouveau_bar_fini(p,s)                                                  \
-       nouveau_subdev_fini(&(p)->base, (s))
-
-int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
-void nouveau_bar_destroy(struct nouveau_bar *);
-
-void _nouveau_bar_dtor(struct nouveau_object *);
-#define _nouveau_bar_init _nouveau_subdev_init
-#define _nouveau_bar_fini _nouveau_subdev_fini
-
 extern struct nouveau_oclass nv50_bar_oclass;
 extern struct nouveau_oclass nvc0_bar_oclass;
 
-int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
-                     struct nouveau_mem *, struct nouveau_object **);
-
-void nv84_bar_flush(struct nouveau_bar *);
-
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
new file mode 100644 (file)
index 0000000..c5e6d1e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __NVBIOS_RAMCFG_H__
+#define __NVBIOS_RAMCFG_H__
+
+struct nouveau_bios;
+
+struct nvbios_ramcfg {
+       unsigned rammap_11_08_01:1;
+       unsigned rammap_11_08_0c:2;
+       unsigned rammap_11_08_10:1;
+       unsigned rammap_11_11_0c:2;
+
+       unsigned ramcfg_11_01_01:1;
+       unsigned ramcfg_11_01_02:1;
+       unsigned ramcfg_11_01_04:1;
+       unsigned ramcfg_11_01_08:1;
+       unsigned ramcfg_11_01_10:1;
+       unsigned ramcfg_11_01_20:1;
+       unsigned ramcfg_11_01_40:1;
+       unsigned ramcfg_11_01_80:1;
+       unsigned ramcfg_11_02_03:2;
+       unsigned ramcfg_11_02_04:1;
+       unsigned ramcfg_11_02_08:1;
+       unsigned ramcfg_11_02_10:1;
+       unsigned ramcfg_11_02_40:1;
+       unsigned ramcfg_11_02_80:1;
+       unsigned ramcfg_11_03_0f:4;
+       unsigned ramcfg_11_03_30:2;
+       unsigned ramcfg_11_03_c0:2;
+       unsigned ramcfg_11_03_f0:4;
+       unsigned ramcfg_11_04:8;
+       unsigned ramcfg_11_06:8;
+       unsigned ramcfg_11_07_02:1;
+       unsigned ramcfg_11_07_04:1;
+       unsigned ramcfg_11_07_08:1;
+       unsigned ramcfg_11_07_10:1;
+       unsigned ramcfg_11_07_40:1;
+       unsigned ramcfg_11_07_80:1;
+       unsigned ramcfg_11_08_01:1;
+       unsigned ramcfg_11_08_02:1;
+       unsigned ramcfg_11_08_04:1;
+       unsigned ramcfg_11_08_08:1;
+       unsigned ramcfg_11_08_10:1;
+       unsigned ramcfg_11_08_20:1;
+       unsigned ramcfg_11_09:8;
+
+       unsigned timing[11];
+       unsigned timing_20_2e_03:2;
+       unsigned timing_20_2e_30:2;
+       unsigned timing_20_2e_c0:2;
+       unsigned timing_20_2f_03:2;
+       unsigned timing_20_2c_003f:6;
+       unsigned timing_20_2c_1fc0:7;
+       unsigned timing_20_30_f8:5;
+       unsigned timing_20_30_07:3;
+       unsigned timing_20_31_0007:3;
+       unsigned timing_20_31_0078:4;
+       unsigned timing_20_31_0780:4;
+       unsigned timing_20_31_0800:1;
+       unsigned timing_20_31_7000:3;
+       unsigned timing_20_31_8000:1;
+};
+
+u8 nvbios_ramcfg_count(struct nouveau_bios *);
+u8 nvbios_ramcfg_index(struct nouveau_bios *);
+
+#endif
index bc15e03208773cea8a16ce3a62a84e4cea702ec3..5bdf8e4db40a137df8b00f4a0183424929ad828c 100644 (file)
@@ -1,11 +1,25 @@
 #ifndef __NVBIOS_RAMMAP_H__
 #define __NVBIOS_RAMMAP_H__
 
-u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr,
-                       u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
-u16 nvbios_rammap_entry(struct nouveau_bios *, int idx,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_rammap_match(struct nouveau_bios *, u16 khz,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+struct nvbios_ramcfg;
+
+u32 nvbios_rammapTe(struct nouveau_bios *, u8 *ver, u8 *hdr,
+                   u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+
+u32 nvbios_rammapEe(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEm(struct nouveau_bios *, u16 mhz,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEp(struct nouveau_bios *, u16 mhz,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+                   struct nvbios_ramcfg *);
+
+u32 nvbios_rammapSe(struct nouveau_bios *, u32 data,
+                   u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+                   u8 *ver, u8 *hdr);
+u32 nvbios_rammapSp(struct nouveau_bios *, u32 data,
+                   u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+                   u8 *ver, u8 *hdr,
+                   struct nvbios_ramcfg *);
 
 #endif
index 963694b5422492ea17526f88ef14ce5e30b70554..76d914b67ab5cc9c0a435d5fc77654cbbfb884e3 100644 (file)
@@ -1,8 +1,14 @@
 #ifndef __NVBIOS_TIMING_H__
 #define __NVBIOS_TIMING_H__
 
-u16 nvbios_timing_table(struct nouveau_bios *,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_timing_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
+struct nvbios_ramcfg;
+
+u16 nvbios_timingTe(struct nouveau_bios *,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+u16 nvbios_timingEe(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u16 nvbios_timingEp(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+                   struct nvbios_ramcfg *);
 
 #endif
index 685c9b12ee4cff48a682f373b7dbd94d5ea0bb24..ed1ac68c38b354a58211c386e1c9bc450b8501ab 100644 (file)
@@ -9,7 +9,6 @@ struct nouveau_devinit {
        bool post;
        void (*meminit)(struct nouveau_devinit *);
        int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
-
 };
 
 static inline struct nouveau_devinit *
@@ -18,32 +17,16 @@ nouveau_devinit(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT];
 }
 
-#define nouveau_devinit_create(p,e,o,d)                                        \
-       nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_devinit_destroy(p)                                             \
-       nouveau_subdev_destroy(&(p)->base)
-#define nouveau_devinit_init(p) ({                                             \
-       struct nouveau_devinit *d = (p);                                       \
-       _nouveau_devinit_init(nv_object(d));                                   \
-})
-#define nouveau_devinit_fini(p,s) ({                                           \
-       struct nouveau_devinit *d = (p);                                       \
-       _nouveau_devinit_fini(nv_object(d), (s));                              \
-})
-
-int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
-                           struct nouveau_oclass *, int, void **);
-#define _nouveau_devinit_dtor _nouveau_subdev_dtor
-int _nouveau_devinit_init(struct nouveau_object *);
-int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
-
-extern struct nouveau_oclass nv04_devinit_oclass;
-extern struct nouveau_oclass nv05_devinit_oclass;
-extern struct nouveau_oclass nv10_devinit_oclass;
-extern struct nouveau_oclass nv1a_devinit_oclass;
-extern struct nouveau_oclass nv20_devinit_oclass;
-extern struct nouveau_oclass nv50_devinit_oclass;
-extern struct nouveau_oclass nva3_devinit_oclass;
-extern struct nouveau_oclass nvc0_devinit_oclass;
+extern struct nouveau_oclass *nv04_devinit_oclass;
+extern struct nouveau_oclass *nv05_devinit_oclass;
+extern struct nouveau_oclass *nv10_devinit_oclass;
+extern struct nouveau_oclass *nv1a_devinit_oclass;
+extern struct nouveau_oclass *nv20_devinit_oclass;
+extern struct nouveau_oclass *nv50_devinit_oclass;
+extern struct nouveau_oclass *nv84_devinit_oclass;
+extern struct nouveau_oclass *nv98_devinit_oclass;
+extern struct nouveau_oclass *nva3_devinit_oclass;
+extern struct nouveau_oclass *nvaf_devinit_oclass;
+extern struct nouveau_oclass *nvc0_devinit_oclass;
 
 #endif
index 8541aa382ff224136d8c1cedff00db0595a753c2..d7ecafbae1ca1c1b0a43192673fbf5ae582ffa60 100644 (file)
@@ -75,6 +75,11 @@ struct nouveau_fb {
 static inline struct nouveau_fb *
 nouveau_fb(void *obj)
 {
+       /* fbram uses this before device subdev pointer is valid */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_FB)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];
 }
 
@@ -101,6 +106,13 @@ extern struct nouveau_oclass *nvaf_fb_oclass;
 extern struct nouveau_oclass *nvc0_fb_oclass;
 extern struct nouveau_oclass *nve0_fb_oclass;
 
+#include <subdev/bios/ramcfg.h>
+
+struct nouveau_ram_data {
+       struct nvbios_ramcfg bios;
+       u32 freq;
+};
+
 struct nouveau_ram {
        struct nouveau_object base;
        enum {
@@ -137,6 +149,12 @@ struct nouveau_ram {
        } rammap, ramcfg, timing;
        u32 freq;
        u32 mr[16];
+       u32 mr1_nuts;
+
+       struct nouveau_ram_data *next;
+       struct nouveau_ram_data former;
+       struct nouveau_ram_data xition;
+       struct nouveau_ram_data target;
 };
 
 #endif
index 9fa5da72387192467ba80c9f9f9a7f2a0adbe339..7f50a858b16f68395a3fe0b84c5bd9f275e8849f 100644 (file)
@@ -73,7 +73,7 @@ struct nouveau_i2c {
        int (*identify)(struct nouveau_i2c *, int index,
                        const char *what, struct nouveau_i2c_board_info *,
                        bool (*match)(struct nouveau_i2c_port *,
-                                     struct i2c_board_info *));
+                                     struct i2c_board_info *, void *), void *);
        struct list_head ports;
 };
 
index ec7a54e91a087cdea900dd1f94947adc0f6f395c..c1df26f3230c17f8fe6ff2a270b95cbafb441c6f 100644 (file)
@@ -23,21 +23,6 @@ nv_memobj(void *obj)
        return obj;
 }
 
-#define nouveau_instobj_create(p,e,o,d)                                        \
-       nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instobj_init(p)                                                \
-       nouveau_object_init(&(p)->base)
-#define nouveau_instobj_fini(p,s)                                              \
-       nouveau_object_fini(&(p)->base, (s))
-
-int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
-                            struct nouveau_oclass *, int, void **);
-void nouveau_instobj_destroy(struct nouveau_instobj *);
-
-void _nouveau_instobj_dtor(struct nouveau_object *);
-#define _nouveau_instobj_init nouveau_object_init
-#define _nouveau_instobj_fini nouveau_object_fini
-
 struct nouveau_instmem {
        struct nouveau_subdev base;
        struct list_head list;
@@ -50,24 +35,18 @@ struct nouveau_instmem {
 static inline struct nouveau_instmem *
 nouveau_instmem(void *obj)
 {
+       /* nv04/nv40 impls need to create objects in their constructor,
+        * which is before the subdev pointer is valid
+        */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM];
 }
 
-#define nouveau_instmem_create(p,e,o,d)                                        \
-       nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instmem_destroy(p)                                             \
-       nouveau_subdev_destroy(&(p)->base)
-int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
-                           struct nouveau_oclass *, int, void **);
-int nouveau_instmem_init(struct nouveau_instmem *);
-int nouveau_instmem_fini(struct nouveau_instmem *, bool);
-
-#define _nouveau_instmem_dtor _nouveau_subdev_dtor
-int _nouveau_instmem_init(struct nouveau_object *);
-int _nouveau_instmem_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nv04_instmem_oclass;
-extern struct nouveau_oclass nv40_instmem_oclass;
-extern struct nouveau_oclass nv50_instmem_oclass;
+extern struct nouveau_oclass *nv04_instmem_oclass;
+extern struct nouveau_oclass *nv40_instmem_oclass;
+extern struct nouveau_oclass *nv50_instmem_oclass;
 
 #endif
index fcf57fa309bfd54bbcbba86bdfc53ef5fcc481f6..c9509039f94b4b57bff45b718651bbdfd663012c 100644 (file)
@@ -131,9 +131,5 @@ void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
 void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
 void nouveau_vm_unmap(struct nouveau_vma *);
 void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
-void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
-                      struct nouveau_mem *);
-void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
-                    struct nouveau_mem *mem);
 
 #endif
index d70ba342aa2e8f46c5de87c406b223d39ed98194..7098ddd546788c3adca970af4afc1a5a8d122d1a 100644 (file)
  */
 
 #include <core/object.h>
-#include <subdev/bar.h>
+
+#include <subdev/fb.h>
+#include <subdev/vm.h>
+
+#include "priv.h"
 
 struct nouveau_barobj {
        struct nouveau_object base;
index 160d27f3c7b4732fc67a069a415681295a0d8dd4..090d594a21b36ee9633462db5f0ee838547b1557 100644 (file)
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nv50_bar_priv {
        struct nouveau_bar base;
        spinlock_t lock;
index b2ec7411eb2eb7cb43e5434016cad756159c69d6..bac5e754de35acdf838b571bf1d6e25eb8b5faec 100644 (file)
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nvc0_bar_priv {
        struct nouveau_bar base;
        spinlock_t lock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
new file mode 100644 (file)
index 0000000..ffad8f3
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __NVKM_BAR_PRIV_H__
+#define __NVKM_BAR_PRIV_H__
+
+#include <subdev/bar.h>
+
+#define nouveau_bar_create(p,e,o,d)                                            \
+       nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_bar_init(p)                                                    \
+       nouveau_subdev_init(&(p)->base)
+#define nouveau_bar_fini(p,s)                                                  \
+       nouveau_subdev_fini(&(p)->base, (s))
+
+int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
+                       struct nouveau_oclass *, int, void **);
+void nouveau_bar_destroy(struct nouveau_bar *);
+
+void _nouveau_bar_dtor(struct nouveau_object *);
+#define _nouveau_bar_init _nouveau_subdev_init
+#define _nouveau_bar_fini _nouveau_subdev_fini
+
+int  nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
+                      struct nouveau_mem *, struct nouveau_object **);
+
+void nv84_bar_flush(struct nouveau_bar *);
+
+#endif
index 420908cb82b613bbc97fbccb9b123f3449926100..de201baeb053aea79a6632289a865de94fc5dc07 100644 (file)
@@ -9,6 +9,7 @@
 #include <subdev/bios/dp.h>
 #include <subdev/bios/gpio.h>
 #include <subdev/bios/init.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/devinit.h>
 #include <subdev/i2c.h>
 #include <subdev/vga.h>
@@ -365,13 +366,13 @@ static u16
 init_script(struct nouveau_bios *bios, int index)
 {
        struct nvbios_init init = { .bios = bios };
-       u16 data;
+       u16 bmp_ver = bmp_version(bios), data;
 
-       if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
-               if (index > 1)
+       if (bmp_ver && bmp_ver < 0x0510) {
+               if (index > 1 || bmp_ver < 0x0100)
                        return 0x0000;
 
-               data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
+               data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
                return nv_ro16(bios, data + (index * 2));
        }
 
@@ -391,43 +392,14 @@ init_unknown_script(struct nouveau_bios *bios)
        return 0x0000;
 }
 
-static u16
-init_ram_restrict_table(struct nvbios_init *init)
-{
-       struct nouveau_bios *bios = init->bios;
-       struct bit_entry bit_M;
-       u16 data = 0x0000;
-
-       if (!bit_entry(bios, 'M', &bit_M)) {
-               if (bit_M.version == 1 && bit_M.length >= 5)
-                       data = nv_ro16(bios, bit_M.offset + 3);
-               if (bit_M.version == 2 && bit_M.length >= 3)
-                       data = nv_ro16(bios, bit_M.offset + 1);
-       }
-
-       if (data == 0x0000)
-               warn("ram restrict table not found\n");
-       return data;
-}
-
 static u8
 init_ram_restrict_group_count(struct nvbios_init *init)
 {
-       struct nouveau_bios *bios = init->bios;
-       struct bit_entry bit_M;
-
-       if (!bit_entry(bios, 'M', &bit_M)) {
-               if (bit_M.version == 1 && bit_M.length >= 5)
-                       return nv_ro08(bios, bit_M.offset + 2);
-               if (bit_M.version == 2 && bit_M.length >= 3)
-                       return nv_ro08(bios, bit_M.offset + 0);
-       }
-
-       return 0x00;
+       return nvbios_ramcfg_count(init->bios);
 }
 
 static u8
-init_ram_restrict_strap(struct nvbios_init *init)
+init_ram_restrict(struct nvbios_init *init)
 {
        /* This appears to be the behaviour of the VBIOS parser, and *is*
         * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
@@ -438,18 +410,8 @@ init_ram_restrict_strap(struct nvbios_init *init)
         * in case *not* re-reading the strap causes similar breakage.
         */
        if (!init->ramcfg || init->bios->version.major < 0x70)
-               init->ramcfg = init_rd32(init, 0x101000);
-       return (init->ramcfg & 0x00000003c) >> 2;
-}
-
-static u8
-init_ram_restrict(struct nvbios_init *init)
-{
-       u8  strap = init_ram_restrict_strap(init);
-       u16 table = init_ram_restrict_table(init);
-       if (table)
-               return nv_ro08(init->bios, table + strap);
-       return 0x00;
+               init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios);
+       return (init->ramcfg & 0x7fffffff);
 }
 
 static u8
@@ -1294,7 +1256,11 @@ init_jump(struct nvbios_init *init)
        u16 offset = nv_ro16(bios, init->offset + 1);
 
        trace("JUMP\t0x%04x\n", offset);
-       init->offset = offset;
+
+       if (init_exec(init))
+               init->offset = offset;
+       else
+               init->offset += 3;
 }
 
 /**
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
new file mode 100644 (file)
index 0000000..991aedd
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
+
+static u8
+nvbios_ramcfg_strap(struct nouveau_bios *bios)
+{
+       return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
+}
+
+u8
+nvbios_ramcfg_count(struct nouveau_bios *bios)
+{
+       struct bit_entry bit_M;
+
+       if (!bit_entry(bios, 'M', &bit_M)) {
+               if (bit_M.version == 1 && bit_M.length >= 5)
+                       return nv_ro08(bios, bit_M.offset + 2);
+               if (bit_M.version == 2 && bit_M.length >= 3)
+                       return nv_ro08(bios, bit_M.offset + 0);
+       }
+
+       return 0x00;
+}
+
+u8
+nvbios_ramcfg_index(struct nouveau_bios *bios)
+{
+       u8 strap = nvbios_ramcfg_strap(bios);
+       u32 xlat = 0x00000000;
+       struct bit_entry bit_M;
+
+       if (!bit_entry(bios, 'M', &bit_M)) {
+               if (bit_M.version == 1 && bit_M.length >= 5)
+                       xlat = nv_ro16(bios, bit_M.offset + 3);
+               if (bit_M.version == 2 && bit_M.length >= 3)
+                       xlat = nv_ro16(bios, bit_M.offset + 1);
+       }
+
+       if (xlat)
+               strap = nv_ro08(bios, xlat + strap);
+       return strap;
+}
index 916fa9d302b7f2fd108617844db25ddb565e4b5d..1811b2cb047276ead557d6d1025568667a1fbc24 100644 (file)
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/rammap.h>
 
-u16
-nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
-                   u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
+u32
+nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
+               u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
        struct bit_entry bit_P;
        u16 rammap = 0x0000;
@@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
        return 0x0000;
 }
 
-u16
-nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEe(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
        u8  snr, ssz;
-       u16 rammap = nvbios_rammap_table(bios, ver, hdr, cnt, len, &snr, &ssz);
+       u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz);
        if (rammap && idx < *cnt) {
                rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
                *hdr = *len;
@@ -73,16 +74,100 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
        return 0x0000;
 }
 
-u16
-nvbios_rammap_match(struct nouveau_bios *bios, u16 khz,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEm(struct nouveau_bios *bios, u16 khz,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
        int idx = 0;
        u32 data;
-       while ((data = nvbios_rammap_entry(bios, idx++, ver, hdr, cnt, len))) {
+       while ((data = nvbios_rammapEe(bios, idx++, ver, hdr, cnt, len))) {
                if (khz >= nv_ro16(bios, data + 0x00) &&
                    khz <= nv_ro16(bios, data + 0x02))
                        break;
        }
        return data;
 }
+
+u32
+nvbios_rammapEp(struct nouveau_bios *bios, u16 khz,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+               struct nvbios_ramcfg *p)
+{
+       u32 data = nvbios_rammapEm(bios, khz, ver, hdr, cnt, len);
+       memset(p, 0x00, sizeof(*p));
+       switch (!!data * *ver) {
+       case 0x11:
+               p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+               p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2;
+               p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+               p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
+
+u32
+nvbios_rammapSe(struct nouveau_bios *bios, u32 data,
+               u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+               u8 *ver, u8 *hdr)
+{
+       if (idx < ecnt) {
+               data = data + ehdr + (idx * elen);
+               *ver = ever;
+               *hdr = elen;
+               return data;
+       }
+       return 0;
+}
+
+u32
+nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
+               u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+               u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
+{
+       data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr);
+       switch (!!data * *ver) {
+       case 0x11:
+               p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
+               p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1;
+               p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2;
+               p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3;
+               p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4;
+               p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5;
+               p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6;
+               p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7;
+               p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0;
+               p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2;
+               p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3;
+               p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4;
+               p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
+               p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7;
+               p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
+               p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4;
+               p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6;
+               p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4;
+               p->ramcfg_11_04    = (nv_ro08(bios, data + 0x04) & 0xff) >> 0;
+               p->ramcfg_11_06    = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
+               p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1;
+               p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2;
+               p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3;
+               p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4;
+               p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6;
+               p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7;
+               p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+               p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1;
+               p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2;
+               p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3;
+               p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+               p->ramcfg_11_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5;
+               p->ramcfg_11_09    = (nv_ro08(bios, data + 0x09) & 0xff) >> 0;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
index 151c2d6aaee872f1398fcca6aab7ae7b48a928d7..350d44ab2ba24b9e56a9dbf178a86497159cc326 100644 (file)
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/timing.h>
 
 u16
-nvbios_timing_table(struct nouveau_bios *bios,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+nvbios_timingTe(struct nouveau_bios *bios,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
        struct bit_entry bit_P;
        u16 timing = 0x0000;
@@ -47,11 +48,15 @@ nvbios_timing_table(struct nouveau_bios *bios,
                                *hdr = nv_ro08(bios, timing + 1);
                                *cnt = nv_ro08(bios, timing + 2);
                                *len = nv_ro08(bios, timing + 3);
+                               *snr = 0;
+                               *ssz = 0;
                                return timing;
                        case 0x20:
                                *hdr = nv_ro08(bios, timing + 1);
-                               *cnt = nv_ro08(bios, timing + 3);
+                               *cnt = nv_ro08(bios, timing + 5);
                                *len = nv_ro08(bios, timing + 2);
+                               *snr = nv_ro08(bios, timing + 4);
+                               *ssz = nv_ro08(bios, timing + 3);
                                return timing;
                        default:
                                break;
@@ -63,11 +68,60 @@ nvbios_timing_table(struct nouveau_bios *bios,
 }
 
 u16
-nvbios_timing_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
+nvbios_timingEe(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
-       u8  hdr, cnt;
-       u16 timing = nvbios_timing_table(bios, ver, &hdr, &cnt, len);
-       if (timing && idx < cnt)
-               return timing + hdr + (idx * *len);
+       u8  snr, ssz;
+       u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+       if (timing && idx < *cnt) {
+               timing += *hdr + idx * (*len + (snr * ssz));
+               *hdr = *len;
+               *cnt = snr;
+               *len = ssz;
+               return timing;
+       }
        return 0x0000;
 }
+
+u16
+nvbios_timingEp(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+               struct nvbios_ramcfg *p)
+{
+       u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
+       switch (!!data * *ver) {
+       case 0x20:
+               p->timing[0] = nv_ro32(bios, data + 0x00);
+               p->timing[1] = nv_ro32(bios, data + 0x04);
+               p->timing[2] = nv_ro32(bios, data + 0x08);
+               p->timing[3] = nv_ro32(bios, data + 0x0c);
+               p->timing[4] = nv_ro32(bios, data + 0x10);
+               p->timing[5] = nv_ro32(bios, data + 0x14);
+               p->timing[6] = nv_ro32(bios, data + 0x18);
+               p->timing[7] = nv_ro32(bios, data + 0x1c);
+               p->timing[8] = nv_ro32(bios, data + 0x20);
+               p->timing[9] = nv_ro32(bios, data + 0x24);
+               p->timing[10] = nv_ro32(bios, data + 0x28);
+               p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0;
+               p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4;
+               p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6;
+               p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0;
+               temp = nv_ro16(bios, data + 0x2c);
+               p->timing_20_2c_003f = (temp & 0x003f) >> 0;
+               p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6;
+               p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0;
+               p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3;
+               temp = nv_ro16(bios, data + 0x31);
+               p->timing_20_31_0007 = (temp & 0x0007) >> 0;
+               p->timing_20_31_0078 = (temp & 0x0078) >> 3;
+               p->timing_20_31_0780 = (temp & 0x0780) >> 7;
+               p->timing_20_31_0800 = (temp & 0x0800) >> 11;
+               p->timing_20_31_7000 = (temp & 0x7000) >> 12;
+               p->timing_20_31_8000 = (temp & 0x8000) >> 15;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
index e2938a21b06fe8a7ac255e9abe106ce1533dc448..dd62baead39c54c9a906939576553b59bf9355a2 100644 (file)
@@ -182,9 +182,12 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
        clk->pstate = pstatei;
 
        if (pfb->ram->calc) {
-               ret = pfb->ram->calc(pfb, pstate->base.domain[nv_clk_src_mem]);
-               if (ret == 0)
-                       ret = pfb->ram->prog(pfb);
+               int khz = pstate->base.domain[nv_clk_src_mem];
+               do {
+                       ret = pfb->ram->calc(pfb, khz);
+                       if (ret == 0)
+                               ret = pfb->ram->prog(pfb);
+               } while (ret > 0);
                pfb->ram->tidy(pfb);
        }
 
index 30c1f3a4158e3de87fd2bfb24592b9ea685b2d88..b74db6cfc4e21ee8f811a08e54da3dfdc7f824a1 100644 (file)
@@ -25,7 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 #include <subdev/clock.h>
-#include <subdev/devinit/priv.h>
+#include <subdev/devinit/nv04.h>
 
 #include "pll.h"
 
index 4c62e84b96f5f7a4aa65d5e8d37bd25d12b120eb..d3c37c96f0e7eaeed97c08749bc23611642705db 100644 (file)
@@ -457,7 +457,7 @@ nve0_domain[] = {
        { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
        { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
        { nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
-       { nv_clk_src_mem    , 0x03, 0, "memory", 1000 },
+       { nv_clk_src_mem    , 0x03, 0, "memory", 500 },
        { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
        { nv_clk_src_hubk01 , 0x05 },
        { nv_clk_src_vdec   , 0x06 },
index 79c81d3d9bacee32ec45f36dee8b73cee3ac2953..8fa34e8152c20b6ae90f2ca020f6c49a077f2cdd 100644 (file)
 
 #include <core/option.h>
 
-#include <subdev/devinit.h>
 #include <subdev/bios.h>
 #include <subdev/bios/init.h>
+#include <subdev/vga.h>
+
+#include "priv.h"
 
 int
 _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
@@ -37,18 +39,41 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
        if (suspend)
                devinit->post = true;
 
+       /* unlock the extended vga crtc regs */
+       nv_lockvgac(devinit, false);
+
        return nouveau_subdev_fini(&devinit->base, suspend);
 }
 
 int
 _nouveau_devinit_init(struct nouveau_object *object)
 {
+       struct nouveau_devinit_impl *impl = (void *)object->oclass;
        struct nouveau_devinit *devinit = (void *)object;
-       int ret = nouveau_subdev_init(&devinit->base);
+       int ret;
+
+       ret = nouveau_subdev_init(&devinit->base);
+       if (ret)
+               return ret;
+
+       ret = nvbios_init(&devinit->base, devinit->post);
        if (ret)
                return ret;
 
-       return nvbios_init(&devinit->base, devinit->post);
+       if (impl->disable)
+               nv_device(devinit)->disable_mask |= impl->disable(devinit);
+       return 0;
+}
+
+void
+_nouveau_devinit_dtor(struct nouveau_object *object)
+{
+       struct nouveau_devinit *devinit = (void *)object;
+
+       /* lock crtc regs */
+       nv_lockvgac(devinit, true);
+
+       nouveau_subdev_destroy(&devinit->base);
 }
 
 int
@@ -57,6 +82,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
                        struct nouveau_oclass *oclass,
                        int size, void **pobject)
 {
+       struct nouveau_devinit_impl *impl = (void *)oclass;
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_devinit *devinit;
        int ret;
@@ -68,5 +94,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
                return ret;
 
        devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
+       devinit->meminit = impl->meminit;
+       devinit->pll_set = impl->pll_set;
        return 0;
 }
index 27c8235f1a85d08a3128dd3266416461ba08a9a7..7037eae46e445bd5d3278dfc70119dac180cadbb 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv04_devinit_priv {
-       struct nouveau_devinit base;
-       int owner;
-};
+#include "nv04.h"
 
 static void
 nv04_devinit_meminit(struct nouveau_devinit *devinit)
@@ -393,17 +388,21 @@ int
 nv04_devinit_fini(struct nouveau_object *object, bool suspend)
 {
        struct nv04_devinit_priv *priv = (void *)object;
+       int ret;
 
        /* make i2c busses accessible */
        nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
 
-       /* unlock extended vga crtc regs, and unslave crtcs */
-       nv_lockvgac(priv, false);
+       ret = nouveau_devinit_fini(&priv->base, suspend);
+       if (ret)
+               return ret;
+
+       /* unslave crtcs */
        if (priv->owner < 0)
                priv->owner = nv_rdvgaowner(priv);
        nv_wrvgaowner(priv, 0);
 
-       return nouveau_devinit_fini(&priv->base, suspend);
+       return 0;
 }
 
 int
@@ -431,14 +430,13 @@ nv04_devinit_dtor(struct nouveau_object *object)
 {
        struct nv04_devinit_priv *priv = (void *)object;
 
-       /* restore vga owner saved at first init, and lock crtc regs  */
+       /* restore vga owner saved at first init */
        nv_wrvgaowner(priv, priv->owner);
-       nv_lockvgac(priv, true);
 
        nouveau_devinit_destroy(&priv->base);
 }
 
-static int
+int
 nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
                  struct nouveau_object **pobject)
@@ -451,19 +449,19 @@ nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.meminit = nv04_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
        priv->owner = -1;
        return 0;
 }
 
-struct nouveau_oclass
-nv04_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x04),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv04_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h
new file mode 100644 (file)
index 0000000..23470a5
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __NVKM_DEVINIT_NV04_H__
+#define __NVKM_DEVINIT_NV04_H__
+
+#include "priv.h"
+
+struct nv04_devinit_priv {
+       struct nouveau_devinit base;
+       u8 owner;
+};
+
+int  nv04_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+                      struct nouveau_oclass *, void *, u32,
+                      struct nouveau_object **);
+void nv04_devinit_dtor(struct nouveau_object *);
+int  nv04_devinit_init(struct nouveau_object *);
+int  nv04_devinit_fini(struct nouveau_object *, bool);
+int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+
+#endif
index b1912a8a8942129b6292323faed5aa11475bfe3e..98b7e6780dc7f4826c4eb946419d0ceb6cfb5d84 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv05_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv05_devinit_meminit(struct nouveau_devinit *devinit)
@@ -49,7 +44,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
                { 0x06, 0x00 },
                { 0x00, 0x00 }
        };
-       struct nv05_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct io_mapping *fb;
        u32 patt = 0xdeadbeef;
@@ -130,31 +125,15 @@ out:
        fbmem_fini(fb);
 }
 
-static int
-nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv05_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv05_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv05_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x05),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv05_devinit_ctor,
+struct nouveau_oclass *
+nv05_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x05),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv05_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 8d274dba1ef17a363af4d4c33c3cea4451025159..32b3d2131a7f0d14b0e37e8b9888e2b38cf937c5 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv10_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv10_devinit_meminit(struct nouveau_devinit *devinit)
 {
-       struct nv10_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        static const int mem_width[] = { 0x10, 0x00, 0x20 };
        int mem_width_count;
        uint32_t patt = 0xdeadbeef;
@@ -101,31 +96,15 @@ amount_found:
        fbmem_fini(fb);
 }
 
-static int
-nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv10_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv10_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv10_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x10),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv10_devinit_ctor,
+struct nouveau_oclass *
+nv10_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x10),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv10_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index e9743cdabe757df66b92509f295d9c800a6ae919..526d0c6faacd3d2623f1dae3aa2cd1b92087a00e 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv04.h"
 
-struct nv1a_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
-
-static int
-nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv1a_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv1a_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x1a),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv1a_devinit_ctor,
+struct nouveau_oclass *
+nv1a_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x1a),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 6cc6080d3bc01e4e9e461bb5c323f82e48a60908..4689ba303b0bd6620ec080fcfe9fa3defad2f3ff 100644 (file)
  *
  */
 
-#include "priv.h"
+#include "nv04.h"
 #include "fbmem.h"
 
-struct nv20_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
-
 static void
 nv20_devinit_meminit(struct nouveau_devinit *devinit)
 {
-       struct nv20_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        struct nouveau_device *device = nv_device(priv);
        uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900);
        uint32_t amount, off;
@@ -65,31 +60,15 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
        fbmem_fini(fb);
 }
 
-static int
-nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv20_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv20_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv20_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x20),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv20_devinit_ctor,
+struct nouveau_oclass *
+nv20_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x20),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv20_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 6df72247c477b5a7c96214fe28a0d7a40be82696..b46c62a1d5d86a9a44a0db88932dacbca6a10598 100644 (file)
@@ -28,9 +28,9 @@
 #include <subdev/bios/init.h>
 #include <subdev/vga.h>
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
        struct nv50_devinit_priv *priv = (void *)devinit;
@@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return 0;
 }
 
+static u64
+nv50_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000))
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+
+       return disable;
+}
+
 int
 nv50_devinit_init(struct nouveau_object *object)
 {
@@ -120,7 +133,7 @@ nv50_devinit_init(struct nouveau_object *object)
        return 0;
 }
 
-static int
+int
 nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
                  struct nouveau_object **pobject)
@@ -133,17 +146,18 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.pll_set = nv50_devinit_pll_set;
        return 0;
 }
 
-struct nouveau_oclass
-nv50_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x50),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv50_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
new file mode 100644 (file)
index 0000000..141c27e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __NVKM_DEVINIT_NV50_H__
+#define __NVKM_DEVINIT_NV50_H__
+
+#include "priv.h"
+
+struct nv50_devinit_priv {
+       struct nouveau_devinit base;
+};
+
+int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+                      struct nouveau_oclass *, void *, u32,
+                      struct nouveau_object **);
+int  nv50_devinit_init(struct nouveau_object *);
+int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
new file mode 100644 (file)
index 0000000..7874225
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv84_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv84_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x84),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv84_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
new file mode 100644 (file)
index 0000000..2b0e963
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv98_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv98_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x98),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv98_devinit_disable,
+}.base;
index 76a68b29014119f57c909c4770777016e8838250..6dedf1dad7f7bce5b71d33dd01111cac7324621b 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-       struct nva3_devinit_priv *priv = (void *)devinit;
+       struct nv50_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct nvbios_pll info;
        int N, fN, M, P;
@@ -58,30 +58,38 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
-static int
-nva3_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
+static u64
+nva3_devinit_disable(struct nouveau_devinit *devinit)
 {
-       struct nv50_devinit_priv *priv;
-       int ret;
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
 
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
 
-       priv->base.pll_set = nva3_devinit_pll_set;
-       return 0;
+       return disable;
 }
 
-struct nouveau_oclass
-nva3_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0xa3),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nva3_devinit_ctor,
+struct nouveau_oclass *
+nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nva3_devinit_pll_set,
+       .disable = nva3_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
new file mode 100644 (file)
index 0000000..4fc68d2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nvaf_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_VIC);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nvaf_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xaf),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nva3_devinit_pll_set,
+       .disable = nvaf_devinit_disable,
+}.base;
index 19e265bf4574a0ad04086bd99d6fa0c2dd9912f9..fa7e63766b1b19ae47b8557c4581b77cb0ff0a22 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
 static int
 nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-       struct nvc0_devinit_priv *priv = (void *)devinit;
+       struct nv50_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct nvbios_pll info;
        int N, fN, M, P;
@@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
+static u64
+nvc0_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r022500 = nv_rd32(priv, 0x022500);
+       u64 disable = 0ULL;
+
+       if (r022500 & 0x00000001)
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+       if (r022500 & 0x00000002) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (r022500 & 0x00000004)
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (r022500 & 0x00000008)
+               disable |= (1ULL << NVDEV_ENGINE_VENC);
+       if (r022500 & 0x00000100)
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+       if (r022500 & 0x00000200)
+               disable |= (1ULL << NVDEV_ENGINE_COPY1);
+
+       return disable;
+}
+
 static int
 nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -72,19 +99,20 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.pll_set = nvc0_devinit_pll_set;
        if (nv_rd32(priv, 0x022500) & 0x00000001)
                priv->base.post = true;
        return 0;
 }
 
-struct nouveau_oclass
-nvc0_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0xc0),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvc0_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xc0),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvc0_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nvc0_devinit_pll_set,
+       .disable = nvc0_devinit_disable,
+}.base;
index 7d622e2b01712508259e1f4436e0284543da7435..822a2fbf44a5b3d601d5c79eedb7b2af68654d86 100644 (file)
@@ -6,20 +6,32 @@
 #include <subdev/clock/pll.h>
 #include <subdev/devinit.h>
 
-void nv04_devinit_dtor(struct nouveau_object *);
-int  nv04_devinit_init(struct nouveau_object *);
-int  nv04_devinit_fini(struct nouveau_object *, bool);
-int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
-
-void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-
-
-struct nv50_devinit_priv {
-       struct nouveau_devinit base;
+struct nouveau_devinit_impl {
+       struct nouveau_oclass base;
+       void (*meminit)(struct nouveau_devinit *);
+       int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
+       u64  (*disable)(struct nouveau_devinit *);
 };
 
-int  nv50_devinit_init(struct nouveau_object *);
+#define nouveau_devinit_create(p,e,o,d)                                        \
+       nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_devinit_destroy(p) ({                                          \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_dtor(nv_object(d));                                   \
+})
+#define nouveau_devinit_init(p) ({                                             \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_init(nv_object(d));                                   \
+})
+#define nouveau_devinit_fini(p,s) ({                                           \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_fini(nv_object(d), (s));                              \
+})
+
+int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
+                           struct nouveau_oclass *, int, void **);
+void _nouveau_devinit_dtor(struct nouveau_object *);
+int _nouveau_devinit_init(struct nouveau_object *);
+int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
 
 #endif
index 34f9605ffee61321d381d6c3ed7e552f8918c51b..66fe959b4f7431dd2cc1b9ce6520263560fb769f 100644 (file)
 #include <subdev/bios.h>
 #include "priv.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 int
-nouveau_gddr5_calc(struct nouveau_ram *ram)
+nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts)
 {
-       struct nouveau_bios *bios = nouveau_bios(ram);
-       int pd, lf, xd, vh, vr, vo;
-       int WL, CL, WR, at, dt, ds;
+       int pd, lf, xd, vh, vr, vo, l3;
+       int WL, CL, WR, at[2], dt, ds;
        int rq = ram->freq < 1000000; /* XXX */
 
-       switch (!!ram->ramcfg.data * ram->ramcfg.version) {
+       switch (ram->ramcfg.version) {
        case 0x11:
-               pd =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x80) >> 7;
-               lf =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x40) >> 6;
-               xd = !(nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x20);
-               vh =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x10) >> 4;
-               vr =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x04) >> 2;
-               vo =   nv_ro08(bios, ram->ramcfg.data + 0x06) & 0xff;
+               pd =  ram->next->bios.ramcfg_11_01_80;
+               lf =  ram->next->bios.ramcfg_11_01_40;
+               xd = !ram->next->bios.ramcfg_11_01_20;
+               vh =  ram->next->bios.ramcfg_11_02_10;
+               vr =  ram->next->bios.ramcfg_11_02_04;
+               vo =  ram->next->bios.ramcfg_11_06;
+               l3 = !ram->next->bios.ramcfg_11_07_02;
                break;
        default:
                return -ENOSYS;
        }
 
-       switch (!!ram->timing.data * ram->timing.version) {
+       switch (ram->timing.version) {
        case 0x20:
-               WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7;
-               CL =  nv_ro08(bios, ram->timing.data + 0x04) & 0x1f;
-               WR =  nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f;
-               at = (nv_ro08(bios, ram->timing.data + 0x2e) & 0xc0) >> 6;
-               dt =  nv_ro08(bios, ram->timing.data + 0x2e) & 0x03;
-               ds =  nv_ro08(bios, ram->timing.data + 0x2f) & 0x03;
+               WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
+               CL = (ram->next->bios.timing[1] & 0x0000001f);
+               WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
+               at[0] = ram->next->bios.timing_20_2e_c0;
+               at[1] = ram->next->bios.timing_20_2e_30;
+               dt =  ram->next->bios.timing_20_2e_03;
+               ds =  ram->next->bios.timing_20_2f_03;
                break;
        default:
                return -ENOSYS;
@@ -71,13 +80,25 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
 
        ram->mr[1] &= ~0x0bf;
        ram->mr[1] |= (xd & 0x01) << 7;
-       ram->mr[1] |= (at & 0x03) << 4;
+       ram->mr[1] |= (at[0] & 0x03) << 4;
        ram->mr[1] |= (dt & 0x03) << 2;
        ram->mr[1] |= (ds & 0x03) << 0;
 
+       /* this seems wrong, alternate field used for the broadcast
+        * on nuts vs non-nuts configs..  meh, it matches for now.
+        */
+       ram->mr1_nuts = ram->mr[1];
+       if (nuts) {
+               ram->mr[1] &= ~0x030;
+               ram->mr[1] |= (at[1] & 0x03) << 4;
+       }
+
        ram->mr[3] &= ~0x020;
        ram->mr[3] |= (rq & 0x01) << 5;
 
+       ram->mr[5] &= ~0x004;
+       ram->mr[5] |= (l3 << 2);
+
        if (!vo)
                vo = (ram->mr[6] & 0xff0) >> 4;
        if (ram->mr[6] & 0x001)
@@ -86,11 +107,16 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
        ram->mr[6] |= (vo & 0xff) << 4;
        ram->mr[6] |= (pd & 0x01) << 0;
 
-       if (!(ram->mr[7] & 0x100))
-               vr = 0; /* binary driver does this.. bug? */
-       ram->mr[7] &= ~0x188;
-       ram->mr[7] |= (vr & 0x01) << 8;
+       if (NOTE00(vr)) {
+               ram->mr[7] &= ~0x300;
+               ram->mr[7] |= (vr & 0x03) << 8;
+       }
+       ram->mr[7] &= ~0x088;
        ram->mr[7] |= (vh & 0x01) << 7;
        ram->mr[7] |= (lf & 0x01) << 3;
+
+       ram->mr[8] &= ~0x003;
+       ram->mr[8] |= (WR & 0x10) >> 3;
+       ram->mr[8] |= (CL & 0x10) >> 4;
        return 0;
 }
index e5fc37c4caac841977a99e4530059ebd6235b36f..45470e1f0385f4682a654e0c37cb27212d3ba8eb 100644 (file)
@@ -33,6 +33,21 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
        return likely((nvc0_pte_storage_type_map[memtype] != 0xff));
 }
 
+static void
+nvc0_fb_intr(struct nouveau_subdev *subdev)
+{
+       struct nvc0_fb_priv *priv = (void *)subdev;
+       u32 intr = nv_rd32(priv, 0x000100);
+       if (intr & 0x08000000) {
+               nv_debug(priv, "PFFB intr\n");
+               intr &= ~0x08000000;
+       }
+       if (intr & 0x00002000) {
+               nv_debug(priv, "PBFB intr\n");
+               intr &= ~0x00002000;
+       }
+}
+
 int
 nvc0_fb_init(struct nouveau_object *object)
 {
@@ -86,6 +101,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return -EFAULT;
        }
 
+       nv_subdev(priv)->intr = nvc0_fb_intr;
        return 0;
 }
 
index 493125214e88696db12ff1786f88be701e108225..edaf95dee61285d81d468060cd2b284b4da89cc0 100644 (file)
@@ -34,7 +34,7 @@ extern struct nouveau_oclass nvc0_ram_oclass;
 extern struct nouveau_oclass nve0_ram_oclass;
 
 int nouveau_sddr3_calc(struct nouveau_ram *ram);
-int nouveau_gddr5_calc(struct nouveau_ram *ram);
+int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts);
 
 #define nouveau_fb_create(p,e,c,d)                                             \
        nouveau_fb_create_((p), (e), (c), sizeof(**d), (void **)d)
index 76762a17d89cfe46a7b794e510fb83225c4aced7..c7fdb3a9e88b06cdcfa3151abf5ae7331c04e409 100644 (file)
@@ -70,13 +70,11 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nv50_ramseq *hwsq = &ram->hwsq;
        struct nvbios_perfE perfE;
        struct nvbios_pll mpll;
-       struct bit_entry M;
        struct {
                u32 data;
                u8  size;
        } ramcfg, timing;
-       u8  ver, hdr, cnt, strap;
-       u32 data;
+       u8  ver, hdr, cnt, len, strap;
        int N1, M1, N2, M2, P;
        int ret, i;
 
@@ -93,16 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        } while (perfE.memory < freq);
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 1 || M.length < 5) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 3);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -113,7 +102,8 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver, &hdr);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &hdr,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || hdr < 0x12) {
                        nv_error(pfb, "invalid/missing timing entry "
                                 "%02x %04x %02x %02x\n",
index f6292cd9207cf354384738c50a135bea9e0ec562..f4ae8aa46a255948df24c3e4d2f4e259ed583d53 100644 (file)
@@ -79,8 +79,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nva3_ram *ram = (void *)pfb->ram;
        struct nva3_ramfuc *fuc = &ram->fuc;
        struct nva3_clock_info mclk;
-       struct bit_entry M;
-       u8  ver, cnt, strap;
+       u8  ver, cnt, len, strap;
        u32 data;
        struct {
                u32 data;
@@ -91,24 +90,15 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        int ret;
 
        /* lookup memory config data relevant to the target frequency */
-       rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-                                        &cnt, &ramcfg.size);
+       rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+                                    &cnt, &ramcfg.size);
        if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
                nv_error(pfb, "invalid/missing rammap entry\n");
                return -EINVAL;
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -123,8 +113,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver,
-                                                &timing.size);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || timing.size < 0x19) {
                        nv_error(pfb, "invalid/missing timing entry\n");
                        return -EINVAL;
index f464547c6bab70c714626672bfbb015d7512d1a3..0391b824ee767d7629e333c56965366bc15347fd 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
@@ -134,9 +133,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nvc0_ram *ram = (void *)pfb->ram;
        struct nvc0_ramfuc *fuc = &ram->fuc;
-       struct bit_entry M;
-       u8  ver, cnt, strap;
-       u32 data;
+       u8  ver, cnt, len, strap;
        struct {
                u32 data;
                u8  size;
@@ -147,24 +144,15 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        int ret;
 
        /* lookup memory config data relevant to the target frequency */
-       rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-                                        &cnt, &ramcfg.size);
+       rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+                                    &cnt, &ramcfg.size);
        if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
                nv_error(pfb, "invalid/missing rammap entry\n");
                return -EINVAL;
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -179,8 +167,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver,
-                                                &timing.size);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || timing.size < 0x19) {
                        nv_error(pfb, "invalid/missing timing entry\n");
                        return -EINVAL;
index bc86cfd084f66c106c4a46980212a59cdde47dad..3257c522a0219026e5147d37725b1f6a30fcac21 100644 (file)
@@ -25,7 +25,6 @@
 #include <subdev/gpio.h>
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/init.h>
 #include <subdev/bios/rammap.h>
 
 #include "ramfuc.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 struct nve0_ramfuc {
        struct ramfuc base;
 
@@ -104,7 +111,9 @@ struct nve0_ramfuc {
        struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */
 
        struct ramfuc_reg r_0x62c000;
+
        struct ramfuc_reg r_0x10f200;
+
        struct ramfuc_reg r_0x10f210;
        struct ramfuc_reg r_0x10f310;
        struct ramfuc_reg r_0x10f314;
@@ -118,12 +127,17 @@ struct nve0_ramfuc {
        struct ramfuc_reg r_0x10f65c;
        struct ramfuc_reg r_0x10f6bc;
        struct ramfuc_reg r_0x100710;
-       struct ramfuc_reg r_0x10f750;
+       struct ramfuc_reg r_0x100750;
 };
 
 struct nve0_ram {
        struct nouveau_ram base;
        struct nve0_ramfuc fuc;
+
+       u32 parts;
+       u32 pmask;
+       u32 pnuts;
+
        int from;
        int mode;
        int N1, fN1, M1, P1;
@@ -134,17 +148,17 @@ struct nve0_ram {
  * GDDR5
  ******************************************************************************/
 static void
-train(struct nve0_ramfuc *fuc, u32 magic)
+nve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data)
 {
        struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-       struct nouveau_fb *pfb = nouveau_fb(ram);
-       const int mc = nv_rd32(pfb, 0x02243c);
-       int i;
-
-       ram_mask(fuc, 0x10f910, 0xbc0e0000, magic);
-       ram_mask(fuc, 0x10f914, 0xbc0e0000, magic);
-       for (i = 0; i < mc; i++) {
-               const u32 addr = 0x110974 + (i * 0x1000);
+       u32 addr = 0x110974, i;
+
+       ram_mask(fuc, 0x10f910, mask, data);
+       ram_mask(fuc, 0x10f914, mask, data);
+
+       for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) {
+               if (ram->pmask & (1 << i))
+                       continue;
                ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000);
        }
 }
@@ -199,12 +213,12 @@ r1373f4_init(struct nve0_ramfuc *fuc)
 }
 
 static void
-r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
+r1373f4_fini(struct nve0_ramfuc *fuc)
 {
        struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-       struct nouveau_bios *bios = nouveau_bios(ram);
-       u8 v0 = (nv_ro08(bios, ramcfg + 0x03) & 0xc0) >> 6;
-       u8 v1 = (nv_ro08(bios, ramcfg + 0x03) & 0x30) >> 4;
+       struct nouveau_ram_data *next = ram->base.next;
+       u8 v0 = next->bios.ramcfg_11_03_c0;
+       u8 v1 = next->bios.ramcfg_11_03_30;
        u32 tmp;
 
        tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
@@ -220,25 +234,46 @@ r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
        ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
 }
 
+static void
+nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg,
+             u32 _mask, u32 _data, u32 _copy)
+{
+       struct nve0_fb_priv *priv = (void *)nouveau_fb(ram);
+       struct ramfuc *fuc = &ram->fuc.base;
+       u32 addr = 0x110000 + (reg->addr[0] & 0xfff);
+       u32 mask = _mask | _copy;
+       u32 data = (_data & _mask) | (reg->data & _copy);
+       u32 i;
+
+       for (i = 0; i < 16; i++, addr += 0x1000) {
+               if (ram->pnuts & (1 << i)) {
+                       u32 prev = nv_rd32(priv, addr);
+                       u32 next = (prev & ~mask) | data;
+                       nouveau_memx_wr32(fuc->memx, addr, next);
+               }
+       }
+}
+#define ram_nuts(s,r,m,d,c)                                                    \
+       nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c))
+
 static int
 nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
-       const u32 rammap = ram->base.rammap.data;
-       const u32 ramcfg = ram->base.ramcfg.data;
-       const u32 timing = ram->base.timing.data;
-       int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-       int mv = 1; /*XXX*/
+       struct nouveau_ram_data *next = ram->base.next;
+       int vc = !(next->bios.ramcfg_11_02_08);
+       int mv = !(next->bios.ramcfg_11_02_04);
        u32 mask, data;
 
        ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
        ram_wr32(fuc, 0x62c000, 0x0f0f0000);
 
        /* MR1: turn termination on early, for some reason.. */
-       if ((ram->base.mr[1] & 0x03c) != 0x030)
+       if ((ram->base.mr[1] & 0x03c) != 0x030) {
                ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c);
+               ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000);
+       }
 
        if (vc == 1 && ram_have(fuc, gpio2E)) {
                u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
@@ -250,8 +285,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
 
-       ram_mask(fuc, 0x10f914, 0x01020000, 0x000c0000);
-       ram_mask(fuc, 0x10f910, 0x01020000, 0x000c0000);
+       nve0_ram_train(fuc, 0x01020000, 0x000c0000);
 
        ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
        ram_nsec(fuc, 1000);
@@ -280,28 +314,28 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        if (1) {
                data |= 0x800807e0;
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-               case 0xc0: data &= ~0x00000040; break;
-               case 0x80: data &= ~0x00000100; break;
-               case 0x40: data &= ~0x80000000; break;
-               case 0x00: data &= ~0x00000400; break;
+               switch (next->bios.ramcfg_11_03_c0) {
+               case 3: data &= ~0x00000040; break;
+               case 2: data &= ~0x00000100; break;
+               case 1: data &= ~0x80000000; break;
+               case 0: data &= ~0x00000400; break;
                }
 
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-               case 0x30: data &= ~0x00000020; break;
-               case 0x20: data &= ~0x00000080; break;
-               case 0x10: data &= ~0x00080000; break;
-               case 0x00: data &= ~0x00000200; break;
+               switch (next->bios.ramcfg_11_03_30) {
+               case 3: data &= ~0x00000020; break;
+               case 2: data &= ~0x00000080; break;
+               case 1: data &= ~0x00080000; break;
+               case 0: data &= ~0x00000200; break;
                }
        }
 
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+       if (next->bios.ramcfg_11_02_80)
                mask |= 0x03000000;
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+       if (next->bios.ramcfg_11_02_40)
                mask |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+       if (next->bios.ramcfg_11_07_10)
                mask |= 0x00004000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+       if (next->bios.ramcfg_11_07_08)
                mask |= 0x00000003;
        else {
                mask |= 0x34000000;
@@ -314,18 +348,18 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        if (ram->from == 2 && ram->mode != 2) {
                ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000);
-               ram_mask(fuc, 0x10f200, 0x00008000, 0x00008000);
+               ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000);
                ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004);
                ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010);
                ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
                r1373f4_init(fuc);
                ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
                ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001);
        } else
        if (ram->from != 2 && ram->mode != 2) {
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
        }
 
        if (ram_have(fuc, gpioMV)) {
@@ -336,49 +370,54 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                }
        }
 
-       if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-            (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+       if ( (next->bios.ramcfg_11_02_40) ||
+            (next->bios.ramcfg_11_07_10)) {
                ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
                ram_nsec(fuc, 20000);
        }
 
        if (ram->from != 2 && ram->mode == 2) {
+               if (0 /*XXX: Titan */)
+                       ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000);
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
                ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002);
                ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010);
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
                ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000);
                ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000);
        } else
        if (ram->from == 2 && ram->mode == 2) {
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
        }
 
        if (ram->mode != 2) /*XXX*/ {
-               if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+               if (next->bios.ramcfg_11_07_40)
                        ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
        }
 
-       data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-       ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-       ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-       ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+       ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+       ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+       ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
-       data = nv_ro08(bios, ramcfg + 0x04);
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-               ram_wr32(fuc, 0x10f698, 0x01010101 * data);
-               ram_wr32(fuc, 0x10f69c, 0x01010101 * data);
+       if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) {
+               ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04);
+               ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04);
+       } else
+       if (!next->bios.ramcfg_11_07_08) {
+               ram_wr32(fuc, 0x10f698, 0x00000000);
+               ram_wr32(fuc, 0x10f69c, 0x00000000);
        }
 
        if (ram->mode != 2) {
-               u32 temp = ram_rd32(fuc, 0x10f694) & ~0xff00ff00;
-               ram_wr32(fuc, 0x10f694, temp | (0x01000100 * data));
+               u32 data = 0x01000100 * next->bios.ramcfg_11_04;
+               ram_nuke(fuc, 0x10f694);
+               ram_mask(fuc, 0x10f694, 0xff00ff00, data);
        }
 
-       if (ram->mode == 2 && (nv_ro08(bios, ramcfg + 0x08) & 0x10))
+       if (ram->mode == 2 && (next->bios.ramcfg_11_08_10))
                data = 0x00000080;
        else
                data = 0x00000000;
@@ -386,19 +425,19 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        mask = 0x00070000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+       if (!(next->bios.ramcfg_11_02_80))
                data |= 0x03000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+       if (!(next->bios.ramcfg_11_02_40))
                data |= 0x00002000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+       if (!(next->bios.ramcfg_11_07_10))
                data |= 0x00004000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+       if (!(next->bios.ramcfg_11_07_08))
                data |= 0x00000003;
        else
                data |= 0x74000000;
        ram_mask(fuc, 0x10f824, mask, data);
 
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x08)
+       if (next->bios.ramcfg_11_01_08)
                data = 0x00000000;
        else
                data = 0x00001000;
@@ -409,61 +448,90 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000);
        }
 
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+       if (next->bios.ramcfg_11_08_01)
                data = 0x00100000;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
        data = 0x00000000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x08)
+       if (next->bios.ramcfg_11_08_08)
                data |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x04)
+       if (next->bios.ramcfg_11_08_04)
                data |= 0x00001000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x02)
+       if (next->bios.ramcfg_11_08_02)
                data |= 0x00004000;
        ram_mask(fuc, 0x10f830, 0x00007000, data);
 
        /* PFB timing */
-       ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-       ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-       ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-       ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-       ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-       ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-       ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-       ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-       ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-       ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-       ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
-
-       data = (nv_ro08(bios, ramcfg + 0x02) & 0x03) << 8;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-               data |= 0x70000000;
-       ram_mask(fuc, 0x10f604, 0x70000300, data);
-
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
-               data |= 0x00000100;
-       ram_mask(fuc, 0x10f614, 0x70000000, data);
-
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x02)
-               data |= 0x00000100;
-       ram_mask(fuc, 0x10f610, 0x70000000, data);
+       ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+       ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+       ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+       ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+       ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+       ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+       ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+       ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+       ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+       ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+       ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
+
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_08_20)) {
+               if (next->bios.ramcfg_11_08_20)
+                       data |= 0x01000000;
+               mask |= 0x01000000;
+       }
+       ram_mask(fuc, 0x10f200, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_02_03 != 0)) {
+               data |= (next->bios.ramcfg_11_02_03) << 8;
+               mask |= 0x00000300;
+       }
+       if (NOTE00(ramcfg_01_10)) {
+               if (next->bios.ramcfg_11_01_10)
+                       data |= 0x70000000;
+               mask |= 0x70000000;
+       }
+       ram_mask(fuc, 0x10f604, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(timing_30_07 != 0)) {
+               data |= (next->bios.timing_20_30_07) << 28;
+               mask |= 0x70000000;
+       }
+       if (NOTE00(ramcfg_01_01)) {
+               if (next->bios.ramcfg_11_01_01)
+                       data |= 0x00000100;
+               mask |= 0x00000100;
+       }
+       ram_mask(fuc, 0x10f614, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(timing_30_07 != 0)) {
+               data |= (next->bios.timing_20_30_07) << 28;
+               mask |= 0x70000000;
+       }
+       if (NOTE00(ramcfg_01_02)) {
+               if (next->bios.ramcfg_11_01_02)
+                       data |= 0x00000100;
+               mask |= 0x00000100;
+       }
+       ram_mask(fuc, 0x10f610, mask, data);
 
        mask = 0x33f00000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+       if (!(next->bios.ramcfg_11_01_04))
                data |= 0x20200000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if (!(next->bios.ramcfg_11_07_80))
                data |= 0x12800000;
        /*XXX: see note above about there probably being some condition
         *     for the 10f824 stuff that uses ramcfg 3...
         */
-       if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-               if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-                       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if ( (next->bios.ramcfg_11_03_f0)) {
+               if (next->bios.rammap_11_08_0c) {
+                       if (!(next->bios.ramcfg_11_07_80))
                                mask |= 0x00000020;
                        else
                                data |= 0x00000020;
@@ -476,49 +544,53 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f808, mask, data);
 
-       data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-       ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+       ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-       data = nv_ro08(bios, ramcfg + 0x02) & 0x03;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-               data |= 0x00000004;
-       if ((nv_rd32(bios, 0x100770) & 0x00000004) != (data & 0x00000004)) {
-               ram_wr32(fuc, 0x10f750, 0x04000009);
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_02_03 != 0)) {
+               data |= next->bios.ramcfg_11_02_03;
+               mask |= 0x00000003;
+       }
+       if (NOTE00(ramcfg_01_10)) {
+               if (next->bios.ramcfg_11_01_10)
+                       data |= 0x00000004;
+               mask |= 0x00000004;
+       }
+
+       if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) {
+               ram_mask(fuc, 0x100750, 0x00000008, 0x00000008);
                ram_wr32(fuc, 0x100710, 0x00000000);
                ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000);
        }
-       ram_mask(fuc, 0x100770, 0x00000007, data);
 
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 8;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
+       data = (next->bios.timing_20_30_07) << 8;
+       if (next->bios.ramcfg_11_01_01)
                data |= 0x80000000;
        ram_mask(fuc, 0x100778, 0x00000700, data);
 
-       data = nv_ro16(bios, timing + 0x2c);
-       ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
-       ram_mask(fuc, 0x10f24c, 0x7f000000, (data & 0x1fc0) << 18);
-
-       data = nv_ro08(bios, timing + 0x30);
-       ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+       ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
+       data = (next->bios.timing[10] & 0x7f000000) >> 24;
+       if (data < next->bios.timing_20_2c_1fc0)
+               data = next->bios.timing_20_2c_1fc0;
+       ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
+       ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16);
 
-       data = nv_ro16(bios, timing + 0x31);
-       ram_mask(fuc, 0x10fec4, 0x041e0f07, (data & 0x0800) << 15 |
-                                           (data & 0x0780) << 10 |
-                                           (data & 0x0078) <<  5 |
-                                           (data & 0x0007));
-       ram_mask(fuc, 0x10fec8, 0x00000027, (data & 0x8000) >> 10 |
-                                           (data & 0x7000) >> 12);
+       ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 |
+                                           next->bios.timing_20_31_0780 << 17 |
+                                           next->bios.timing_20_31_0078 << 8 |
+                                           next->bios.timing_20_31_0007);
+       ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 |
+                                           next->bios.timing_20_31_7000);
 
        ram_wr32(fuc, 0x10f090, 0x4000007e);
-       ram_nsec(fuc, 1000);
+       ram_nsec(fuc, 2000);
        ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
        ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
-       ram_nsec(fuc, 2000);
        ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
 
-       if ((nv_ro08(bios, ramcfg + 0x08) & 0x10) && (ram->mode == 2) /*XXX*/) {
+       if ((next->bios.ramcfg_11_08_10) && (ram->mode == 2) /*XXX*/) {
                u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000);
-               train(fuc, 0xa4010000); /*XXX*/
+               nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/
                ram_nsec(fuc, 1000);
                ram_wr32(fuc, 0x10f294, temp);
        }
@@ -528,7 +600,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
        ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]);
        ram_nsec(fuc, 1000);
        ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]);
-       ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5]);
+       ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */
        ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]);
        ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]);
 
@@ -544,12 +616,13 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
        ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */
        ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
        ram_nsec(fuc, 1000);
+       ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800);
 
        data  = ram_rd32(fuc, 0x10f978);
        data &= ~0x00046144;
        data |=  0x0000000b;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-               if (!(nv_ro08(bios, ramcfg + 0x07) & 0x04))
+       if (!(next->bios.ramcfg_11_07_08)) {
+               if (!(next->bios.ramcfg_11_07_04))
                        data |= 0x0000200c;
                else
                        data |= 0x00000000;
@@ -563,44 +636,43 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                ram_wr32(fuc, 0x10f830, data);
        }
 
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
+       if (!(next->bios.ramcfg_11_07_08)) {
                data = 0x88020000;
-               if ( (nv_ro08(bios, ramcfg + 0x07) & 0x04))
+               if ( (next->bios.ramcfg_11_07_04))
                        data |= 0x10000000;
-               if (!(nv_ro08(bios, rammap + 0x08) & 0x10))
+               if (!(next->bios.rammap_11_08_10))
                        data |= 0x00080000;
        } else {
                data = 0xa40e0000;
        }
-       train(fuc, data);
-       ram_nsec(fuc, 1000);
+       nve0_ram_train(fuc, 0xbc0f0000, data);
+       if (1) /* XXX: not always? */
+               ram_nsec(fuc, 1000);
 
        if (ram->mode == 2) { /*XXX*/
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004);
        }
 
-       /* MR5: (re)enable LP3 if necessary
-        * XXX: need to find the switch, keeping off for now
-        */
-       ram_mask(fuc, mr[5], 0x00000004, 0x00000000);
+       /* LP3 */
+       if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5])
+               ram_nsec(fuc, 1000);
 
        if (ram->mode != 2) {
                ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000);
                ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
        }
 
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x02) {
-               ram_mask(fuc, 0x10f910, 0x80020000, 0x01000000);
-               ram_mask(fuc, 0x10f914, 0x80020000, 0x01000000);
-       }
+       if (next->bios.ramcfg_11_07_02)
+               nve0_ram_train(fuc, 0x80020000, 0x01000000);
 
        ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-       if (nv_ro08(bios, rammap + 0x08) & 0x01)
+       if (next->bios.rammap_11_08_01)
                data = 0x00000800;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f200, 0x00000800, data);
+       ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800);
        return 0;
 }
 
@@ -611,17 +683,14 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 static int
 nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
        const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1);
        const u32 runk0 = ram->fN1 << 16;
        const u32 runk1 = ram->fN1;
-       const u32 rammap = ram->base.rammap.data;
-       const u32 ramcfg = ram->base.ramcfg.data;
-       const u32 timing = ram->base.timing.data;
-       int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-       int mv = 1; /*XXX*/
+       struct nouveau_ram_data *next = ram->base.next;
+       int vc = !(next->bios.ramcfg_11_02_08);
+       int mv = !(next->bios.ramcfg_11_02_04);
        u32 mask, data;
 
        ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
@@ -636,7 +705,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
        }
 
        ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
-       if ((nv_ro08(bios, ramcfg + 0x03) & 0xf0))
+       if ((next->bios.ramcfg_11_03_f0))
                ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000);
 
        ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
@@ -661,28 +730,28 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
        if (1) {
                mask |= 0x800807e0;
                data |= 0x800807e0;
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-               case 0xc0: data &= ~0x00000040; break;
-               case 0x80: data &= ~0x00000100; break;
-               case 0x40: data &= ~0x80000000; break;
-               case 0x00: data &= ~0x00000400; break;
+               switch (next->bios.ramcfg_11_03_c0) {
+               case 3: data &= ~0x00000040; break;
+               case 2: data &= ~0x00000100; break;
+               case 1: data &= ~0x80000000; break;
+               case 0: data &= ~0x00000400; break;
                }
 
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-               case 0x30: data &= ~0x00000020; break;
-               case 0x20: data &= ~0x00000080; break;
-               case 0x10: data &= ~0x00080000; break;
-               case 0x00: data &= ~0x00000200; break;
+               switch (next->bios.ramcfg_11_03_30) {
+               case 3: data &= ~0x00000020; break;
+               case 2: data &= ~0x00000080; break;
+               case 1: data &= ~0x00080000; break;
+               case 0: data &= ~0x00000200; break;
                }
        }
 
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+       if (next->bios.ramcfg_11_02_80)
                mask |= 0x03000000;
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+       if (next->bios.ramcfg_11_02_40)
                mask |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+       if (next->bios.ramcfg_11_07_10)
                mask |= 0x00004000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+       if (next->bios.ramcfg_11_07_08)
                mask |= 0x00000003;
        else
                mask |= 0x14000000;
@@ -692,7 +761,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010);
        data  = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
-       data |= (nv_ro08(bios, ramcfg + 0x03) & 0x30) << 12;
+       data |= (next->bios.ramcfg_11_03_30) << 12;
        ram_wr32(fuc, 0x1373ec, data);
        ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000);
        ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000);
@@ -724,68 +793,67 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
                }
        }
 
-       if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-            (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+       if ( (next->bios.ramcfg_11_02_40) ||
+            (next->bios.ramcfg_11_07_10)) {
                ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
                ram_nsec(fuc, 20000);
        }
 
        if (ram->mode != 2) /*XXX*/ {
-               if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+               if (next->bios.ramcfg_11_07_40)
                        ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
        }
 
-       data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-       ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-       ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-       ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+       ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+       ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+       ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
        mask = 0x00010000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+       if (!(next->bios.ramcfg_11_02_80))
                data |= 0x03000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+       if (!(next->bios.ramcfg_11_02_40))
                data |= 0x00002000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+       if (!(next->bios.ramcfg_11_07_10))
                data |= 0x00004000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+       if (!(next->bios.ramcfg_11_07_08))
                data |= 0x00000003;
        else
                data |= 0x14000000;
        ram_mask(fuc, 0x10f824, mask, data);
        ram_nsec(fuc, 1000);
 
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+       if (next->bios.ramcfg_11_08_01)
                data = 0x00100000;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
        /* PFB timing */
-       ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-       ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-       ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-       ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-       ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-       ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-       ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-       ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-       ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-       ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-       ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
+       ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+       ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+       ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+       ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+       ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+       ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+       ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+       ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+       ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+       ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+       ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
 
        mask = 0x33f00000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+       if (!(next->bios.ramcfg_11_01_04))
                data |= 0x20200000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if (!(next->bios.ramcfg_11_07_80))
                data |= 0x12800000;
        /*XXX: see note above about there probably being some condition
         *     for the 10f824 stuff that uses ramcfg 3...
         */
-       if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-               if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-                       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if ( (next->bios.ramcfg_11_03_f0)) {
+               if (next->bios.rammap_11_08_0c) {
+                       if (!(next->bios.ramcfg_11_07_80))
                                mask |= 0x00000020;
                        else
                                data |= 0x00000020;
@@ -799,21 +867,16 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f808, mask, data);
 
-       data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-       ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+       ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-       data = nv_ro16(bios, timing + 0x2c);
-       ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
+       ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
 
-       if (((nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6) >
-           ((nv_ro32(bios, timing + 0x28) & 0x7f000000) >> 24))
-               data = (nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6;
-       else
-               data = (nv_ro32(bios, timing + 0x28) & 0x1f000000) >> 24;
+       data = (next->bios.timing[10] & 0x7f000000) >> 24;
+       if (data < next->bios.timing_20_2c_1fc0)
+               data = next->bios.timing_20_2c_1fc0;
        ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
 
-       data = nv_ro08(bios, timing + 0x30);
-       ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+       ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8);
 
        ram_wr32(fuc, 0x10f090, 0x4000007f);
        ram_nsec(fuc, 1000);
@@ -855,7 +918,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-       if (nv_ro08(bios, rammap + 0x08) & 0x01)
+       if (next->bios.rammap_11_08_01)
                data = 0x00000800;
        else
                data = 0x00000000;
@@ -868,21 +931,18 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
  ******************************************************************************/
 
 static int
-nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
+                  struct nouveau_ram_data *data)
 {
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
-       struct nve0_ramfuc *fuc = &ram->fuc;
-       struct bit_entry M;
-       int ret, refclk, strap, i;
-       u32 data;
-       u8  cnt;
+       u8 strap, cnt, len;
 
        /* lookup memory config data relevant to the target frequency */
-       ram->base.rammap.data = nvbios_rammap_match(bios, freq / 1000,
-                                                  &ram->base.rammap.version,
-                                                  &ram->base.rammap.size, &cnt,
-                                                  &ram->base.ramcfg.size);
+       ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000,
+                                              &ram->base.rammap.version,
+                                              &ram->base.rammap.size,
+                                              &cnt, &len, &data->bios);
        if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 ||
             ram->base.rammap.size < 0x09) {
                nv_error(pfb, "invalid/missing rammap entry\n");
@@ -890,24 +950,13 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
-       if (strap >= cnt) {
-               nv_error(pfb, "invalid ramcfg strap\n");
-               return -EINVAL;
-       }
-
-       ram->base.ramcfg.version = ram->base.rammap.version;
-       ram->base.ramcfg.data = ram->base.rammap.data + ram->base.rammap.size +
-                              (ram->base.ramcfg.size * strap);
+       ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
+                                               ram->base.rammap.version,
+                                               ram->base.rammap.size, cnt, len,
+                                               nvbios_ramcfg_index(bios),
+                                               &ram->base.ramcfg.version,
+                                               &ram->base.ramcfg.size,
+                                               &data->bios);
        if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 ||
             ram->base.ramcfg.size < 0x08) {
                nv_error(pfb, "invalid/missing ramcfg entry\n");
@@ -918,9 +967,9 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00);
        if (strap != 0xff) {
                ram->base.timing.data =
-                       nvbios_timing_entry(bios, strap,
-                                          &ram->base.timing.version,
-                                          &ram->base.timing.size);
+                       nvbios_timingEp(bios, strap, &ram->base.timing.version,
+                                      &ram->base.timing.size, &cnt, &len,
+                                      &data->bios);
                if (!ram->base.timing.data ||
                     ram->base.timing.version != 0x20 ||
                     ram->base.timing.size < 0x33) {
@@ -931,11 +980,23 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                ram->base.timing.data = 0;
        }
 
+       data->freq = freq;
+       return 0;
+}
+
+static int
+nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next)
+{
+       struct nve0_ram *ram = (void *)pfb->ram;
+       struct nve0_ramfuc *fuc = &ram->fuc;
+       int refclk, i;
+       int ret;
+
        ret = ram_init(fuc, pfb);
        if (ret)
                return ret;
 
-       ram->mode = (freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
+       ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
        ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f;
 
        /* XXX: this is *not* what nvidia do.  on fermi nvidia generally
@@ -946,7 +1007,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
         * so far, i've seen very weird values being chosen by nvidia on
         * kepler boards, no idea how/why they're chosen.
         */
-       refclk = freq;
+       refclk = next->freq;
        if (ram->mode == 2)
                refclk = fuc->mempll.refclk;
 
@@ -968,7 +1029,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                fuc->mempll.min_p = 1;
                fuc->mempll.max_p = 2;
 
-               ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, freq,
+               ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq,
                                   &ram->N2, NULL, &ram->M2, &ram->P2);
                if (ret <= 0) {
                        nv_error(pfb, "unable to calc mempll\n");
@@ -980,17 +1041,18 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                if (ram_have(fuc, mr[i]))
                        ram->base.mr[i] = ram_rd32(fuc, mr[i]);
        }
+       ram->base.freq = next->freq;
 
        switch (ram->base.type) {
        case NV_MEM_TYPE_DDR3:
                ret = nouveau_sddr3_calc(&ram->base);
                if (ret == 0)
-                       ret = nve0_ram_calc_sddr3(pfb, freq);
+                       ret = nve0_ram_calc_sddr3(pfb, next->freq);
                break;
        case NV_MEM_TYPE_GDDR5:
-               ret = nouveau_gddr5_calc(&ram->base);
+               ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0);
                if (ret == 0)
-                       ret = nve0_ram_calc_gddr5(pfb, freq);
+                       ret = nve0_ram_calc_gddr5(pfb, next->freq);
                break;
        default:
                ret = -ENOSYS;
@@ -1000,6 +1062,48 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        return ret;
 }
 
+static int
+nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+{
+       struct nouveau_clock *clk = nouveau_clock(pfb);
+       struct nve0_ram *ram = (void *)pfb->ram;
+       struct nouveau_ram_data *xits = &ram->base.xition;
+       struct nouveau_ram_data *copy;
+       int ret;
+
+       if (ram->base.next == NULL) {
+               ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem),
+                                       &ram->base.former);
+               if (ret)
+                       return ret;
+
+               ret = nve0_ram_calc_data(pfb, freq, &ram->base.target);
+               if (ret)
+                       return ret;
+
+               if (ram->base.target.freq < ram->base.former.freq) {
+                       *xits = ram->base.target;
+                       copy = &ram->base.former;
+               } else {
+                       *xits = ram->base.former;
+                       copy = &ram->base.target;
+               }
+
+               xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04;
+               xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03;
+               xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07;
+
+               ram->base.next = &ram->base.target;
+               if (memcmp(xits, &ram->base.former, sizeof(xits->bios)))
+                       ram->base.next = &ram->base.xition;
+       } else {
+               BUG_ON(ram->base.next != &ram->base.xition);
+               ram->base.next = &ram->base.target;
+       }
+
+       return nve0_ram_calc_xits(pfb, ram->base.next);
+}
+
 static int
 nve0_ram_prog(struct nouveau_fb *pfb)
 {
@@ -1007,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
        ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
-       return 0;
+       return (ram->base.next == &ram->base.xition);
 }
 
 static void
@@ -1015,6 +1119,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
 {
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
+       ram->base.next = NULL;
        ram_exec(fuc, false);
 }
 
@@ -1055,7 +1160,7 @@ nve0_ram_init(struct nouveau_object *object)
         * binary driver skips the one that's already been setup by
         * the init tables.
         */
-       data = nvbios_rammap_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
+       data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
        if (!data || hdr < 0x15)
                return -EINVAL;
 
@@ -1073,6 +1178,7 @@ nve0_ram_init(struct nouveau_object *object)
                data += 4;
        }
        nv_wr32(pfb, 0x10f65c, save);
+       nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000);
 
        switch (ram->base.type) {
        case NV_MEM_TYPE_GDDR5:
@@ -1117,7 +1223,8 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nouveau_gpio *gpio = nouveau_gpio(pfb);
        struct dcb_gpio_func func;
        struct nve0_ram *ram;
-       int ret;
+       int ret, i;
+       u32 tmp;
 
        ret = nvc0_ram_create(parent, engine, oclass, &ram);
        *pobject = nv_object(ram);
@@ -1136,6 +1243,25 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                break;
        }
 
+       /* calculate a mask of differently configured memory partitions,
+        * because, of course reclocking wasn't complicated enough
+        * already without having to treat some of them differently to
+        * the others....
+        */
+       ram->parts = nv_rd32(pfb, 0x022438);
+       ram->pmask = nv_rd32(pfb, 0x022554);
+       ram->pnuts = 0;
+       for (i = 0, tmp = 0; i < ram->parts; i++) {
+               if (!(ram->pmask & (1 << i))) {
+                       u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000));
+                       if (tmp && tmp != cfg1) {
+                               ram->pnuts |= (1 << i);
+                               continue;
+                       }
+                       tmp = cfg1;
+               }
+       }
+
        // parse bios data for both pll's
        ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll);
        if (ret) {
@@ -1248,7 +1374,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c);
        ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc);
        ram->fuc.r_0x100710 = ramfuc_reg(0x100710);
-       ram->fuc.r_0x10f750 = ramfuc_reg(0x10f750);
+       ram->fuc.r_0x100750 = ramfuc_reg(0x100750);
        return 0;
 }
 
index 041fd5edaebf7de988206ec6440bdf1950edc938..c33c03d2f4af2f695e50e92078ea18c800d07eec 100644 (file)
@@ -197,7 +197,7 @@ static int
 nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                     struct nouveau_i2c_board_info *info,
                     bool (*match)(struct nouveau_i2c_port *,
-                                  struct i2c_board_info *))
+                                  struct i2c_board_info *, void *), void *data)
 {
        struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index);
        int i;
@@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                }
 
                if (nv_probe_i2c(port, info[i].dev.addr) &&
-                   (!match || match(port, &info[i].dev))) {
+                   (!match || match(port, &info[i].dev, data))) {
                        nv_info(i2c, "detected %s: %s\n", what,
                                info[i].dev.type);
                        return i;
index 6565f3dbbe04e7e04c0721ad49f3523688f8b729..14706d9842ca6d1428298982e247f1887f11cff6 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+/******************************************************************************
+ * instmem object base implementation
+ *****************************************************************************/
+
+void
+_nouveau_instobj_dtor(struct nouveau_object *object)
+{
+       struct nouveau_instmem *imem = (void *)object->engine;
+       struct nouveau_instobj *iobj = (void *)object;
+
+       mutex_lock(&nv_subdev(imem)->mutex);
+       list_del(&iobj->head);
+       mutex_unlock(&nv_subdev(imem)->mutex);
+
+       return nouveau_object_destroy(&iobj->base);
+}
 
 int
 nouveau_instobj_create_(struct nouveau_object *parent,
@@ -46,73 +63,26 @@ nouveau_instobj_create_(struct nouveau_object *parent,
        return 0;
 }
 
-void
-nouveau_instobj_destroy(struct nouveau_instobj *iobj)
-{
-       struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
+/******************************************************************************
+ * instmem subdev base implementation
+ *****************************************************************************/
 
-       mutex_lock(&subdev->mutex);
-       list_del(&iobj->head);
-       mutex_unlock(&subdev->mutex);
-
-       return nouveau_object_destroy(&iobj->base);
-}
-
-void
-_nouveau_instobj_dtor(struct nouveau_object *object)
+static int
+nouveau_instmem_alloc(struct nouveau_instmem *imem,
+                     struct nouveau_object *parent, u32 size, u32 align,
+                     struct nouveau_object **pobject)
 {
-       struct nouveau_instobj *iobj = (void *)object;
-       return nouveau_instobj_destroy(iobj);
+       struct nouveau_object *engine = nv_object(imem);
+       struct nouveau_instmem_impl *impl = (void *)engine->oclass;
+       struct nouveau_instobj_args args = { .size = size, .align = align };
+       return nouveau_object_ctor(parent, engine, impl->instobj, &args,
+                                  sizeof(args), pobject);
 }
 
 int
-nouveau_instmem_create_(struct nouveau_object *parent,
-                       struct nouveau_object *engine,
-                       struct nouveau_oclass *oclass,
-                       int length, void **pobject)
-{
-       struct nouveau_instmem *imem;
-       int ret;
-
-       ret = nouveau_subdev_create_(parent, engine, oclass, 0,
-                                    "INSTMEM", "instmem", length, pobject);
-       imem = *pobject;
-       if (ret)
-               return ret;
-
-       INIT_LIST_HEAD(&imem->list);
-       return 0;
-}
-
-int
-nouveau_instmem_init(struct nouveau_instmem *imem)
-{
-       struct nouveau_instobj *iobj;
-       int ret, i;
-
-       ret = nouveau_subdev_init(&imem->base);
-       if (ret)
-               return ret;
-
-       mutex_lock(&imem->base.mutex);
-
-       list_for_each_entry(iobj, &imem->list, head) {
-               if (iobj->suspend) {
-                       for (i = 0; i < iobj->size; i += 4)
-                               nv_wo32(iobj, i, iobj->suspend[i / 4]);
-                       vfree(iobj->suspend);
-                       iobj->suspend = NULL;
-               }
-       }
-
-       mutex_unlock(&imem->base.mutex);
-
-       return 0;
-}
-
-int
-nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
+_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
 {
+       struct nouveau_instmem *imem = (void *)object;
        struct nouveau_instobj *iobj;
        int i, ret = 0;
 
@@ -143,12 +113,45 @@ int
 _nouveau_instmem_init(struct nouveau_object *object)
 {
        struct nouveau_instmem *imem = (void *)object;
-       return nouveau_instmem_init(imem);
+       struct nouveau_instobj *iobj;
+       int ret, i;
+
+       ret = nouveau_subdev_init(&imem->base);
+       if (ret)
+               return ret;
+
+       mutex_lock(&imem->base.mutex);
+
+       list_for_each_entry(iobj, &imem->list, head) {
+               if (iobj->suspend) {
+                       for (i = 0; i < iobj->size; i += 4)
+                               nv_wo32(iobj, i, iobj->suspend[i / 4]);
+                       vfree(iobj->suspend);
+                       iobj->suspend = NULL;
+               }
+       }
+
+       mutex_unlock(&imem->base.mutex);
+
+       return 0;
 }
 
 int
-_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
+nouveau_instmem_create_(struct nouveau_object *parent,
+                       struct nouveau_object *engine,
+                       struct nouveau_oclass *oclass,
+                       int length, void **pobject)
 {
-       struct nouveau_instmem *imem = (void *)object;
-       return nouveau_instmem_fini(imem, suspend);
+       struct nouveau_instmem *imem;
+       int ret;
+
+       ret = nouveau_subdev_create_(parent, engine, oclass, 0,
+                                    "INSTMEM", "instmem", length, pobject);
+       imem = *pobject;
+       if (ret)
+               return ret;
+
+       INIT_LIST_HEAD(&imem->list);
+       imem->alloc = nouveau_instmem_alloc;
+       return 0;
 }
index 795393d7b2f56826c0be783c320867bd14d4336b..7b64befee48fbb5b30b306c980ae53bd077c3368 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/fb.h>
-
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
+
+static u32
+nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
+{
+       struct nv04_instobj_priv *node = (void *)object;
+       return nv_ro32(object->engine, node->mem->offset + addr);
+}
+
+static void
+nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       struct nv04_instobj_priv *node = (void *)object;
+       nv_wo32(object->engine, node->mem->offset + addr, data);
+}
+
+static void
+nv04_instobj_dtor(struct nouveau_object *object)
+{
+       struct nv04_instmem_priv *priv = (void *)object->engine;
+       struct nv04_instobj_priv *node = (void *)object;
+       nouveau_mm_free(&priv->heap, &node->mem);
+       nouveau_instobj_destroy(&node->base);
+}
+
 static int
 nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -33,18 +58,19 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
        struct nv04_instmem_priv *priv = (void *)engine;
        struct nv04_instobj_priv *node;
-       int ret, align;
+       struct nouveau_instobj_args *args = data;
+       int ret;
 
-       align = (unsigned long)data;
-       if (!align)
-               align = 1;
+       if (!args->align)
+               args->align = 1;
 
        ret = nouveau_instobj_create(parent, engine, oclass, &node);
        *pobject = nv_object(node);
        if (ret)
                return ret;
 
-       ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem);
+       ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size,
+                             args->align, &node->mem);
        if (ret)
                return ret;
 
@@ -53,32 +79,9 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-static void
-nv04_instobj_dtor(struct nouveau_object *object)
-{
-       struct nv04_instmem_priv *priv = (void *)object->engine;
-       struct nv04_instobj_priv *node = (void *)object;
-       nouveau_mm_free(&priv->heap, &node->mem);
-       nouveau_instobj_destroy(&node->base);
-}
-
-static u32
-nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
-{
-       struct nv04_instobj_priv *node = (void *)object;
-       return nv_ro32(object->engine, node->mem->offset + addr);
-}
-
-static void
-nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       struct nv04_instobj_priv *node = (void *)object;
-       nv_wo32(object->engine, node->mem->offset + addr, data);
-}
-
-static struct nouveau_oclass
+struct nouveau_instobj_impl
 nv04_instobj_oclass = {
-       .ofuncs = &(struct nouveau_ofuncs) {
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_instobj_ctor,
                .dtor = nv04_instobj_dtor,
                .init = _nouveau_instobj_init,
@@ -88,19 +91,34 @@ nv04_instobj_oclass = {
        },
 };
 
-int
-nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-                  u32 size, u32 align, struct nouveau_object **pobject)
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
 {
-       struct nouveau_object *engine = nv_object(imem);
-       int ret;
+       return nv_rd32(object, 0x700000 + addr);
+}
 
-       ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass,
-                                 (void *)(unsigned long)align, size, pobject);
-       if (ret)
-               return ret;
+static void
+nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       return nv_wr32(object, 0x700000 + addr, data);
+}
 
-       return 0;
+void
+nv04_instmem_dtor(struct nouveau_object *object)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       nouveau_gpuobj_ref(NULL, &priv->ramfc);
+       nouveau_gpuobj_ref(NULL, &priv->ramro);
+       nouveau_ramht_ref(NULL, &priv->ramht);
+       nouveau_gpuobj_ref(NULL, &priv->vbios);
+       nouveau_mm_fini(&priv->heap);
+       if (priv->iomem)
+               iounmap(priv->iomem);
+       nouveau_instmem_destroy(&priv->base);
 }
 
 static int
@@ -118,7 +136,6 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        /* PRAMIN aperture maps over the end of VRAM, reserve it */
        priv->base.reserved = 512 * 1024;
-       priv->base.alloc    = nv04_instmem_alloc;
 
        ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
        if (ret)
@@ -150,36 +167,10 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-void
-nv04_instmem_dtor(struct nouveau_object *object)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       nouveau_gpuobj_ref(NULL, &priv->ramfc);
-       nouveau_gpuobj_ref(NULL, &priv->ramro);
-       nouveau_ramht_ref(NULL, &priv->ramht);
-       nouveau_gpuobj_ref(NULL, &priv->vbios);
-       nouveau_mm_fini(&priv->heap);
-       if (priv->iomem)
-               iounmap(priv->iomem);
-       nouveau_instmem_destroy(&priv->base);
-}
-
-static u32
-nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-       return nv_rd32(object, 0x700000 + addr);
-}
-
-static void
-nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       return nv_wr32(object, 0x700000 + addr, data);
-}
-
-struct nouveau_oclass
-nv04_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x04),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_instmem_ctor,
                .dtor = nv04_instmem_dtor,
                .init = _nouveau_instmem_init,
@@ -187,4 +178,5 @@ nv04_instmem_oclass = {
                .rd32 = nv04_instmem_rd32,
                .wr32 = nv04_instmem_wr32,
        },
-};
+       .instobj = &nv04_instobj_oclass.base,
+}.base;
index b15b61310236608e88a1bc2b89f58b70f3705f48..095fbc6fc099a852bfee334dea9aba389448adcb 100644 (file)
@@ -5,7 +5,9 @@
 #include <core/ramht.h>
 #include <core/mm.h>
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+extern struct nouveau_instobj_impl nv04_instobj_oclass;
 
 struct nv04_instmem_priv {
        struct nouveau_instmem base;
index b10a143787a7af95af24475f78fa52de7c7a641f..ec0b9661d614ced3dec026e3460d3eeb07905f2e 100644 (file)
 
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       return ioread32_native(priv->iomem + addr);
+}
+
+static void
+nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       iowrite32_native(data, priv->iomem + addr);
+}
+
 static int
 nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -69,7 +87,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->base.reserved += 512 * 1024;      /* object storage */
 
        priv->base.reserved = round_up(priv->base.reserved, 4096);
-       priv->base.alloc    = nv04_instmem_alloc;
 
        ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
        if (ret)
@@ -106,24 +123,10 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-static u32
-nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       return ioread32_native(priv->iomem + addr);
-}
-
-static void
-nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       iowrite32_native(data, priv->iomem + addr);
-}
-
-struct nouveau_oclass
-nv40_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x40),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv40_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x40),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv40_instmem_ctor,
                .dtor = nv04_instmem_dtor,
                .init = _nouveau_instmem_init,
@@ -131,4 +134,5 @@ nv40_instmem_oclass = {
                .rd32 = nv40_instmem_rd32,
                .wr32 = nv40_instmem_wr32,
        },
-};
+       .instobj = &nv04_instobj_oclass.base,
+}.base;
index 97bc5dff93e7aa224643c0cb5422faa15adb9e36..7cb3b098a08d030d7d315a1642ebf6a167033ffe 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
 #include <subdev/fb.h>
-
 #include <core/mm.h>
 
+#include "priv.h"
+
 struct nv50_instmem_priv {
        struct nouveau_instmem base;
        spinlock_t lock;
@@ -38,42 +38,9 @@ struct nv50_instobj_priv {
        struct nouveau_mem *mem;
 };
 
-static int
-nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nouveau_fb *pfb = nouveau_fb(parent);
-       struct nv50_instobj_priv *node;
-       u32 align = (unsigned long)data;
-       int ret;
-
-       size  = max((size  + 4095) & ~4095, (u32)4096);
-       align = max((align + 4095) & ~4095, (u32)4096);
-
-       ret = nouveau_instobj_create(parent, engine, oclass, &node);
-       *pobject = nv_object(node);
-       if (ret)
-               return ret;
-
-       ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem);
-       if (ret)
-               return ret;
-
-       node->base.addr = node->mem->offset;
-       node->base.size = node->mem->size << 12;
-       node->mem->page_shift = 12;
-       return 0;
-}
-
-static void
-nv50_instobj_dtor(struct nouveau_object *object)
-{
-       struct nv50_instobj_priv *node = (void *)object;
-       struct nouveau_fb *pfb = nouveau_fb(object);
-       pfb->ram->put(pfb, &node->mem);
-       nouveau_instobj_destroy(&node->base);
-}
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
 
 static u32
 nv50_instobj_rd32(struct nouveau_object *object, u64 offset)
@@ -113,9 +80,46 @@ nv50_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static struct nouveau_oclass
+static void
+nv50_instobj_dtor(struct nouveau_object *object)
+{
+       struct nv50_instobj_priv *node = (void *)object;
+       struct nouveau_fb *pfb = nouveau_fb(object);
+       pfb->ram->put(pfb, &node->mem);
+       nouveau_instobj_destroy(&node->base);
+}
+
+static int
+nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                 struct nouveau_oclass *oclass, void *data, u32 size,
+                 struct nouveau_object **pobject)
+{
+       struct nouveau_fb *pfb = nouveau_fb(parent);
+       struct nouveau_instobj_args *args = data;
+       struct nv50_instobj_priv *node;
+       int ret;
+
+       args->size  = max((args->size  + 4095) & ~4095, (u32)4096);
+       args->align = max((args->align + 4095) & ~4095, (u32)4096);
+
+       ret = nouveau_instobj_create(parent, engine, oclass, &node);
+       *pobject = nv_object(node);
+       if (ret)
+               return ret;
+
+       ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem);
+       if (ret)
+               return ret;
+
+       node->base.addr = node->mem->offset;
+       node->base.size = node->mem->size << 12;
+       node->mem->page_shift = 12;
+       return 0;
+}
+
+static struct nouveau_instobj_impl
 nv50_instobj_oclass = {
-       .ofuncs = &(struct nouveau_ofuncs) {
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_instobj_ctor,
                .dtor = nv50_instobj_dtor,
                .init = _nouveau_instobj_init,
@@ -125,13 +129,16 @@ nv50_instobj_oclass = {
        },
 };
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
 static int
-nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-                  u32 size, u32 align, struct nouveau_object **pobject)
+nv50_instmem_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nouveau_object *engine = nv_object(imem);
-       return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass,
-                                  (void *)(unsigned long)align, size, pobject);
+       struct nv50_instmem_priv *priv = (void *)object;
+       priv->addr = ~0ULL;
+       return nouveau_instmem_fini(&priv->base, suspend);
 }
 
 static int
@@ -148,25 +155,17 @@ nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        spin_lock_init(&priv->lock);
-       priv->base.alloc = nv50_instmem_alloc;
        return 0;
 }
 
-static int
-nv50_instmem_fini(struct nouveau_object *object, bool suspend)
-{
-       struct nv50_instmem_priv *priv = (void *)object;
-       priv->addr = ~0ULL;
-       return nouveau_instmem_fini(&priv->base, suspend);
-}
-
-struct nouveau_oclass
-nv50_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x50),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_instmem_ctor,
                .dtor = _nouveau_instmem_dtor,
                .init = _nouveau_instmem_init,
                .fini = nv50_instmem_fini,
        },
-};
+       .instobj = &nv50_instobj_oclass.base,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h
new file mode 100644 (file)
index 0000000..8d67ded
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __NVKM_INSTMEM_PRIV_H__
+#define __NVKM_INSTMEM_PRIV_H__
+
+#include <subdev/instmem.h>
+
+struct nouveau_instobj_impl {
+       struct nouveau_oclass base;
+};
+
+struct nouveau_instobj_args {
+       u32 size;
+       u32 align;
+};
+
+#define nouveau_instobj_create(p,e,o,d)                                        \
+       nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instobj_destroy(p) ({                                          \
+       struct nouveau_instobj *iobj = (p);                                    \
+       _nouveau_instobj_dtor(nv_object(iobj));                                \
+})
+#define nouveau_instobj_init(p)                                                \
+       nouveau_object_init(&(p)->base)
+#define nouveau_instobj_fini(p,s)                                              \
+       nouveau_object_fini(&(p)->base, (s))
+
+int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
+                            struct nouveau_oclass *, int, void **);
+void _nouveau_instobj_dtor(struct nouveau_object *);
+#define _nouveau_instobj_init nouveau_object_init
+#define _nouveau_instobj_fini nouveau_object_fini
+
+struct nouveau_instmem_impl {
+       struct nouveau_oclass base;
+       struct nouveau_oclass *instobj;
+};
+
+#define nouveau_instmem_create(p,e,o,d)                                        \
+       nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instmem_destroy(p)                                             \
+       nouveau_subdev_destroy(&(p)->base)
+#define nouveau_instmem_init(p) ({                                             \
+       struct nouveau_instmem *imem = (p);                                    \
+       _nouveau_instmem_init(nv_object(imem));                                \
+})
+#define nouveau_instmem_fini(p,s) ({                                           \
+       struct nouveau_instmem *imem = (p);                                    \
+       _nouveau_instmem_fini(nv_object(imem), (s));                           \
+})
+
+int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
+                           struct nouveau_oclass *, int, void **);
+#define _nouveau_instmem_dtor _nouveau_subdev_dtor
+int _nouveau_instmem_init(struct nouveau_object *);
+int _nouveau_instmem_fini(struct nouveau_object *, bool);
+
+#endif
index c02b4763a2d50e40db65cf2a8a247f2e8374cd3f..34472d3170974ca8e6207afe0a347f332130d6bd 100644 (file)
@@ -32,6 +32,7 @@ nvc0_mc_intr[] = {
        { 0x00000080, NVDEV_ENGINE_COPY2 },
        { 0x00000100, NVDEV_ENGINE_FIFO },
        { 0x00001000, NVDEV_ENGINE_GR },
+       { 0x00002000, NVDEV_SUBDEV_FB },
        { 0x00008000, NVDEV_ENGINE_BSP },
        { 0x00040000, NVDEV_SUBDEV_THERM },
        { 0x00020000, NVDEV_ENGINE_VP },
@@ -40,6 +41,7 @@ nvc0_mc_intr[] = {
        { 0x01000000, NVDEV_SUBDEV_PWR },
        { 0x02000000, NVDEV_SUBDEV_LTCG },
        { 0x04000000, NVDEV_ENGINE_DISP },
+       { 0x08000000, NVDEV_SUBDEV_FB },
        { 0x10000000, NVDEV_SUBDEV_BUS },
        { 0x40000000, NVDEV_SUBDEV_IBUS },
        { 0x80000000, NVDEV_ENGINE_SW },
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc
new file mode 100644 (file)
index 0000000..757dda7
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#define T_TIMEOUT  2200000
+#define T_RISEFALL 1000
+#define T_HOLD     5000
+
+#ifdef INCLUDE_PROC
+process(PROC_I2C_, #i2c_init, #i2c_recv)
+#endif
+
+/******************************************************************************
+ * I2C_ data segment
+ *****************************************************************************/
+#ifdef INCLUDE_DATA
+i2c_scl_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SCL
+.b32 NV_PPWR_OUTPUT_I2C_1_SCL
+.b32 NV_PPWR_OUTPUT_I2C_2_SCL
+.b32 NV_PPWR_OUTPUT_I2C_3_SCL
+.b32 NV_PPWR_OUTPUT_I2C_4_SCL
+.b32 NV_PPWR_OUTPUT_I2C_5_SCL
+.b32 NV_PPWR_OUTPUT_I2C_6_SCL
+.b32 NV_PPWR_OUTPUT_I2C_7_SCL
+.b32 NV_PPWR_OUTPUT_I2C_8_SCL
+.b32 NV_PPWR_OUTPUT_I2C_9_SCL
+i2c_sda_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SDA
+.b32 NV_PPWR_OUTPUT_I2C_1_SDA
+.b32 NV_PPWR_OUTPUT_I2C_2_SDA
+.b32 NV_PPWR_OUTPUT_I2C_3_SDA
+.b32 NV_PPWR_OUTPUT_I2C_4_SDA
+.b32 NV_PPWR_OUTPUT_I2C_5_SDA
+.b32 NV_PPWR_OUTPUT_I2C_6_SDA
+.b32 NV_PPWR_OUTPUT_I2C_7_SDA
+.b32 NV_PPWR_OUTPUT_I2C_8_SDA
+.b32 NV_PPWR_OUTPUT_I2C_9_SDA
+#if NVKM_PPWR_CHIPSET < GF119
+i2c_ctrl:
+.b32 0x00e138
+.b32 0x00e150
+.b32 0x00e168
+.b32 0x00e180
+.b32 0x00e254
+.b32 0x00e274
+.b32 0x00e764
+.b32 0x00e780
+.b32 0x00e79c
+.b32 0x00e7b8
+#endif
+#endif
+
+/******************************************************************************
+ * I2C_ code segment
+ *****************************************************************************/
+#ifdef INCLUDE_CODE
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_drive_scl:
+       cmp b32 $r3 0
+       bra e #i2c_drive_scl_lo
+       nv_iowr(NV_PPWR_OUTPUT_SET, $r1)
+       ret
+       i2c_drive_scl_lo:
+       nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)
+       ret
+
+i2c_drive_sda:
+       cmp b32 $r3 0
+       bra e #i2c_drive_sda_lo
+       nv_iowr(NV_PPWR_OUTPUT_SET, $r2)
+       ret
+       i2c_drive_sda_lo:
+       nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)
+       ret
+
+i2c_sense_scl:
+       bclr $flags $p1
+       nv_iord($r3, NV_PPWR_INPUT)
+       and $r3 $r1
+       bra z #i2c_sense_scl_done
+               bset $flags $p1
+       i2c_sense_scl_done:
+       ret
+
+i2c_sense_sda:
+       bclr $flags $p1
+       nv_iord($r3, NV_PPWR_INPUT)
+       and $r3 $r2
+       bra z #i2c_sense_sda_done
+               bset $flags $p1
+       i2c_sense_sda_done:
+       ret
+
+#define i2c_drive_scl(v) /*
+*/     mov $r3 (v) /*
+*/     call(i2c_drive_scl)
+#define i2c_drive_sda(v) /*
+*/     mov $r3 (v) /*
+*/     call(i2c_drive_sda)
+#define i2c_sense_scl() /*
+*/     call(i2c_sense_scl)
+#define i2c_sense_sda() /*
+*/     call(i2c_sense_sda)
+#define i2c_delay(v) /*
+*/     mov $r14 (v) /*
+*/     call(nsec)
+
+#define i2c_trace_init() /*
+*/     imm32($r6, 0x10000000) /*
+*/     sub b32 $r7 $r6 1 /*
+*/
+#define i2c_trace_down() /*
+*/     shr b32 $r6 4 /*
+*/     push $r5 /*
+*/     shl b32 $r5 $r6 4 /*
+*/     sub b32 $r5 $r6 /*
+*/     not b32 $r5 /*
+*/     and $r7 $r5 /*
+*/     pop $r5 /*
+*/
+#define i2c_trace_exit() /*
+*/     shl b32 $r6 4 /*
+*/
+#define i2c_trace_next() /*
+*/     add b32 $r7 $r6 /*
+*/
+#define i2c_trace_call(func) /*
+*/     i2c_trace_next() /*
+*/     i2c_trace_down() /*
+*/     call(func) /*
+*/     i2c_trace_exit() /*
+*/
+
+i2c_raise_scl:
+       push $r4
+       mov $r4 (T_TIMEOUT / T_RISEFALL)
+       i2c_drive_scl(1)
+       i2c_raise_scl_wait:
+               i2c_delay(T_RISEFALL)
+               i2c_sense_scl()
+               bra $p1 #i2c_raise_scl_done
+               sub b32 $r4 1
+               bra nz #i2c_raise_scl_wait
+       i2c_raise_scl_done:
+       pop $r4
+       ret
+
+i2c_start:
+       i2c_sense_scl()
+       bra not $p1 #i2c_start_rep
+       i2c_sense_sda()
+       bra not $p1 #i2c_start_rep
+       bra #i2c_start_send
+       i2c_start_rep:
+               i2c_drive_scl(0)
+               i2c_drive_sda(1)
+               i2c_trace_call(i2c_raise_scl)
+               bra not $p1 #i2c_start_out
+       i2c_start_send:
+       i2c_drive_sda(0)
+       i2c_delay(T_HOLD)
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       i2c_start_out:
+       ret
+
+i2c_stop:
+       i2c_drive_scl(0)
+       i2c_drive_sda(0)
+       i2c_delay(T_RISEFALL)
+       i2c_drive_scl(1)
+       i2c_delay(T_HOLD)
+       i2c_drive_sda(1)
+       i2c_delay(T_HOLD)
+       ret
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitw:
+       call(i2c_drive_sda)
+       i2c_delay(T_RISEFALL)
+       i2c_trace_call(i2c_raise_scl)
+       bra not $p1 #i2c_bitw_out
+       i2c_delay(T_HOLD)
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       i2c_bitw_out:
+       ret
+
+// $r3  - value (out)
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitr:
+       i2c_drive_sda(1)
+       i2c_delay(T_RISEFALL)
+       i2c_trace_call(i2c_raise_scl)
+       bra not $p1 #i2c_bitr_done
+       i2c_sense_sda()
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       xbit $r3 $flags $p1
+       bset $flags $p1
+       i2c_bitr_done:
+       ret
+
+i2c_get_byte:
+       mov $r5 0
+       mov $r4 8
+       i2c_get_byte_next:
+               shl b32 $r5 1
+               i2c_trace_call(i2c_bitr)
+               bra not $p1 #i2c_get_byte_done
+               or $r5 $r3
+               sub b32 $r4 1
+               bra nz #i2c_get_byte_next
+       mov $r3 1
+       i2c_trace_call(i2c_bitw)
+       i2c_get_byte_done:
+       ret
+
+i2c_put_byte:
+       mov $r4 8
+       i2c_put_byte_next:
+               sub b32 $r4 1
+               xbit $r3 $r5 $r4
+               i2c_trace_call(i2c_bitw)
+               bra not $p1 #i2c_put_byte_done
+               cmp b32 $r4 0
+               bra ne #i2c_put_byte_next
+       i2c_trace_call(i2c_bitr)
+       bra not $p1 #i2c_put_byte_done
+       i2c_trace_next()
+       cmp b32 $r3 1
+       bra ne #i2c_put_byte_done
+       bclr $flags $p1 // nack
+       i2c_put_byte_done:
+       ret
+
+i2c_addr:
+       i2c_trace_call(i2c_start)
+       bra not $p1 #i2c_addr_done
+       extr $r3 $r12 I2C__MSG_DATA0_ADDR
+       shl b32 $r3 1
+       or $r5 $r3
+       i2c_trace_call(i2c_put_byte)
+       i2c_addr_done:
+       ret
+
+i2c_acquire_addr:
+       extr $r14 $r12 I2C__MSG_DATA0_PORT
+#if NVKM_PPWR_CHIPSET < GF119
+       shl b32 $r14 2
+       add b32 $r14 #i2c_ctrl
+       ld b32 $r14 D[$r14]
+#else
+       shl b32 $r14 5
+       add b32 $r14 0x00d014
+#endif
+       ret
+
+i2c_acquire:
+       call(i2c_acquire_addr)
+       call(rd32)
+       bset $r13 3
+       call(wr32)
+       ret
+
+i2c_release:
+       call(i2c_acquire_addr)
+       call(rd32)
+       bclr $r13 3
+       call(wr32)
+       ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r14 - sender process name
+// $r13 - message
+// $r12 - data0
+// $r11 - data1
+// $r0  - zero
+i2c_recv:
+       bclr $flags $p1
+       extr $r1 $r12 I2C__MSG_DATA0_PORT
+       shl b32 $r1 2
+       cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)
+       bra ge #i2c_recv_done
+       add b32 $r3 $r1 #i2c_sda_map
+       ld b32 $r2 D[$r3]
+       add b32 $r3 $r1 #i2c_scl_map
+       ld b32 $r1 D[$r3]
+
+       bset $flags $p2
+       push $r13
+       push $r14
+
+       push $r13
+       i2c_trace_init()
+       i2c_trace_call(i2c_acquire)
+       pop $r13
+
+       cmp b32 $r13 I2C__MSG_RD08
+       bra ne #i2c_recv_not_rd08
+               mov $r5 0
+               i2c_trace_call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r12 I2C__MSG_DATA0_RD08_REG
+               i2c_trace_call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               mov $r5 1
+               i2c_trace_call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               i2c_trace_call(i2c_get_byte)
+               bra not $p1 #i2c_recv_done
+               ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL
+               i2c_trace_call(i2c_stop)
+               mov b32 $r11 $r5
+               clear b32 $r7
+               bra #i2c_recv_done
+
+       i2c_recv_not_rd08:
+       cmp b32 $r13 I2C__MSG_WR08
+       bra ne #i2c_recv_not_wr08
+               mov $r5 0
+               call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r12 I2C__MSG_DATA0_WR08_REG
+               call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               mov $r5 0
+               call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL
+               call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               call(i2c_stop)
+               clear b32 $r7
+               extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC
+               bra nz #i2c_recv_done
+               bclr $flags $p2
+               bra #i2c_recv_done
+
+       i2c_recv_not_wr08:
+
+       i2c_recv_done:
+       extr $r14 $r12 I2C__MSG_DATA0_PORT
+       call(i2c_release)
+
+       pop $r14
+       pop $r13
+       bra not $p2 #i2c_recv_exit
+       mov b32 $r12 $r7
+       call(send)
+
+       i2c_recv_exit:
+       ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r0  - zero
+i2c_init:
+       ret
+#endif
index 0a7b05fa5c1112ab4f172ca39a5d66fd1de7ead2..8f29badd785f16f9cd37cff7adf19d03f1aafc44 100644 (file)
@@ -51,12 +51,12 @@ time_next: .b32 0
 // $r0  - zero
 rd32:
        nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
-       mov $r14 NV_PPWR_MMIO_CTRL_OP_RD
-       sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
-       nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+       mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
+       sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
+       nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
        rd32_wait:
-               nv_iord($r14, NV_PPWR_MMIO_CTRL)
-               and $r14 NV_PPWR_MMIO_CTRL_STATUS
+               nv_iord($r13, NV_PPWR_MMIO_CTRL)
+               and $r13 NV_PPWR_MMIO_CTRL_STATUS
                bra nz #rd32_wait
        nv_iord($r13, NV_PPWR_MMIO_DATA)
        ret
@@ -70,23 +70,25 @@ rd32:
 wr32:
        nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
        nv_iowr(NV_PPWR_MMIO_DATA, $r13)
-       mov $r14 NV_PPWR_MMIO_CTRL_OP_WR
-       or $r14 NV_PPWR_MMIO_CTRL_MASK_B32_0
-       sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
+       mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
+       or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
+       sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
 
 #ifdef NVKM_FALCON_MMIO_TRAP
-       mov $r8 NV_PPWR_INTR_TRIGGER_USER1
-       nv_iowr(NV_PPWR_INTR_TRIGGER, $r8)
+       push $r13
+       mov $r13 NV_PPWR_INTR_TRIGGER_USER1
+       nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
        wr32_host:
-               nv_iord($r8, NV_PPWR_INTR)
-               and $r8 NV_PPWR_INTR_USER1
+               nv_iord($r13, NV_PPWR_INTR)
+               and $r13 NV_PPWR_INTR_USER1
                bra nz #wr32_host
+       pop $r13
 #endif
 
-       nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+       nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
        wr32_wait:
-               nv_iord($r14, NV_PPWR_MMIO_CTRL)
-               and $r14 NV_PPWR_MMIO_CTRL_STATUS
+               nv_iord($r13, NV_PPWR_MMIO_CTRL)
+               and $r13 NV_PPWR_MMIO_CTRL_STATUS
                bra nz #wr32_wait
        ret
 
index 2a74ea90760430624d6bb369b02e5a575ad75c5d..e2a63ac5422b8180e4e21cd77e622f688900e4ad 100644 (file)
 #define NV_PPWR_MMIO_CTRL_OP_WR                                      0x00000002
 #define NV_PPWR_OUTPUT                                                   0x07c0
 #define NV_PPWR_OUTPUT_FB_PAUSE                                      0x00000004
+#if NVKM_PPWR_CHIPSET < GF119
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00000100
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00000200
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#else
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00000400
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00000800
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#endif
+#define NV_PPWR_INPUT                                                    0x07c4
 #define NV_PPWR_OUTPUT_SET                                               0x07e0
 #define NV_PPWR_OUTPUT_SET_FB_PAUSE                                  0x00000004
 #define NV_PPWR_OUTPUT_CLR                                               0x07e4
 */     .b32 0 /*
 */     .skip 64
 
+#if NV_PPWR_CHIPSET < GK208
+#define imm32(reg,val) /*
+*/     movw reg  ((val) & 0x0000ffff) /*
+*/     sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/     mov reg (val)
+#endif
+
 #ifndef NVKM_FALCON_UNSHIFTED_IO
 #define nv_iord(reg,ior) /*
 */     mov reg ior /*
index 947be536daefcb6031723f3d5e8eb2638c29eb47..17a8a383d91a91929c2eebad9ef1f531861c6800 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 9342e2d7d3b7909b94f5cc02ead4c80d1e9e3e9b..4bd43a99fdccbe3d2cde12233644f18bda7561c0 100644 (file)
@@ -89,16 +89,9 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x54534554,
-       0x00000494,
-       0x00000475,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x5f433249,
+       0x00000877,
+       0x0000071e,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -111,16 +104,6 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x454c4449,
-       0x0000049f,
-       0x0000049d,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -128,17 +111,16 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x54534554,
+       0x00000898,
+       0x00000879,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
        0x00000000,
-/* 0x0214: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -151,6 +133,9 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x454c4449,
+       0x000008a3,
+       0x000008a1,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -170,9 +155,12 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x026c: time_next */
        0x00000000,
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,31 +192,8 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
-       0x00010000,
-       0x00000000,
-       0x000003a9,
-/* 0x0324: memx_func_next */
-       0x00000001,
-       0x00000000,
-       0x000003c7,
-       0x00000002,
-       0x00000002,
-       0x000003df,
-       0x00040003,
-       0x00000000,
-       0x00000407,
-       0x00010004,
-       0x00000000,
-       0x00000421,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
        0x00000000,
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -261,10 +226,25 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0370: memx_func_head */
+       0x00010000,
        0x00000000,
+       0x000003a9,
+/* 0x037c: memx_func_next */
+       0x00000001,
        0x00000000,
+       0x000003c7,
+       0x00000002,
+       0x00000002,
+       0x000003df,
+       0x00040003,
        0x00000000,
+       0x00000407,
+       0x00010004,
        0x00000000,
+       0x00000421,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +715,6 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -778,6 +757,29 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00000400,
+       0x00000800,
+       0x00001000,
+       0x00002000,
+       0x00004000,
+       0x00008000,
+       0x00010000,
+       0x00020000,
+       0x00040000,
+       0x00080000,
+/* 0x0bd4: i2c_sda_map */
+       0x00100000,
+       0x00200000,
+       0x00400000,
+       0x00800000,
+       0x01000000,
+       0x02000000,
+       0x04000000,
+       0x08000000,
+       0x10000000,
+       0x20000000,
        0x00000000,
 };
 
@@ -786,13 +788,13 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0004: rd32 */
        0xf607a040,
        0x04bd000e,
-       0xe3f0010e,
+       0xd3f0010d,
        0x07ac4001,
-       0xbd000ef6,
+       0xbd000df6,
 /* 0x0019: rd32_wait */
-       0x07ac4e04,
-       0xf100eecf,
-       0xf47000e4,
+       0x07ac4d04,
+       0xf100ddcf,
+       0xf47000d4,
        0xa44df61b,
        0x00ddcf07,
 /* 0x002e: wr32 */
@@ -800,14 +802,14 @@ uint32_t nv108_pwr_code[] = {
        0x000ef607,
        0xa44004bd,
        0x000df607,
-       0x020e04bd,
-       0xf0f0e5f0,
-       0xac4001e3,
-       0x000ef607,
+       0x020d04bd,
+       0xf0f0d5f0,
+       0xac4001d3,
+       0x000df607,
 /* 0x004e: wr32_wait */
-       0xac4e04bd,
-       0x00eecf07,
-       0x7000e4f1,
+       0xac4d04bd,
+       0x00ddcf07,
+       0x7000d4f1,
        0xf8f61bf4,
 /* 0x005d: nsec */
        0xcf2c0800,
@@ -832,20 +834,20 @@ uint32_t nv108_pwr_code[] = {
        0x03e99800,
        0xf40096b0,
        0x0a98280b,
-       0x029abb84,
+       0x029abb9a,
        0x0d0e1cf4,
        0x01de7e01,
        0xf494bd00,
 /* 0x00b2: intr_watchdog_next_time */
        0x0a98140e,
-       0x00a6b085,
+       0x00a6b09b,
        0xa6080bf4,
        0x061cf49a,
 /* 0x00c0: intr_watchdog_next_time_set */
 /* 0x00c3: intr_watchdog_next_proc */
-       0xb58509b5,
+       0xb59b09b5,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc81bf402,
 /* 0x00d2: intr */
        0x00f900f8,
@@ -862,15 +864,15 @@ uint32_t nv108_pwr_code[] = {
        0x080804bd,
        0xc40088cf,
        0x0bf40289,
-       0x8500b51f,
+       0x9b00b51f,
        0x957e580e,
        0x09980000,
-       0x0096b085,
+       0x0096b09b,
        0x000d0bf4,
        0x0009f634,
        0x09b504bd,
 /* 0x0125: intr_skip_watchdog */
-       0x0089e484,
+       0x0089e49a,
        0x360bf408,
        0xcf068849,
        0x9ac40099,
@@ -918,7 +920,7 @@ uint32_t nv108_pwr_code[] = {
 /* 0x01c6: timer_reset */
        0x3400161e,
        0xbd000ef6,
-       0x840eb504,
+       0x9a0eb504,
 /* 0x01d0: timer_enable */
        0x38000108,
        0xbd0008f6,
@@ -949,7 +951,7 @@ uint32_t nv108_pwr_code[] = {
        0xa6008a98,
        0x100bf4ae,
        0xb15880b6,
-       0xf4021086,
+       0xf4026886,
        0x32f4f11b,
 /* 0x0239: find_done */
        0xfc8eb201,
@@ -1009,7 +1011,7 @@ uint32_t nv108_pwr_code[] = {
        0x0bf412a6,
        0x071ec42e,
        0xb704ee94,
-       0x980218e0,
+       0x980270e0,
        0xec9803eb,
        0x01ed9802,
        0x7e00ee98,
@@ -1031,7 +1033,7 @@ uint32_t nv108_pwr_code[] = {
        0xf412a608,
        0x23c4ef0b,
        0x0434b607,
-       0x029830b7,
+       0x02f030b7,
        0xb5033bb5,
        0x3db5023c,
        0x003eb501,
@@ -1044,11 +1046,11 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0379: host_init */
        0x00804100,
        0xf11014b6,
-       0x40021815,
+       0x40027015,
        0x01f604d0,
        0x4104bd00,
        0x14b60080,
-       0x9815f110,
+       0xf015f110,
        0x04dc4002,
        0xbd0001f6,
        0x40010104,
@@ -1101,13 +1103,13 @@ uint32_t nv108_pwr_code[] = {
        0x001398b2,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12a655f9,
        0xfced1ef4,
        0x7ee0fcd0,
        0xf800023f,
 /* 0x0455: memx_info */
-       0x03544c00,
+       0x03ac4c00,
        0x7e08004b,
        0xf800023f,
 /* 0x0461: memx_recv */
@@ -1119,7 +1121,301 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0471: perf_recv */
 /* 0x0473: perf_init */
        0xf800f800,
-/* 0x0475: test_recv */
+/* 0x0475: i2c_drive_scl */
+       0x0036b000,
+       0x400d0bf4,
+       0x01f607e0,
+       0xf804bd00,
+/* 0x0485: i2c_drive_scl_lo */
+       0x07e44000,
+       0xbd0001f6,
+/* 0x048f: i2c_drive_sda */
+       0xb000f804,
+       0x0bf40036,
+       0x07e0400d,
+       0xbd0002f6,
+/* 0x049f: i2c_drive_sda_lo */
+       0x4000f804,
+       0x02f607e4,
+       0xf804bd00,
+/* 0x04a9: i2c_sense_scl */
+       0x0132f400,
+       0xcf07c443,
+       0x31fd0033,
+       0x060bf404,
+/* 0x04bb: i2c_sense_scl_done */
+       0xf80131f4,
+/* 0x04bd: i2c_sense_sda */
+       0x0132f400,
+       0xcf07c443,
+       0x32fd0033,
+       0x060bf404,
+/* 0x04cf: i2c_sense_sda_done */
+       0xf80131f4,
+/* 0x04d1: i2c_raise_scl */
+       0x4440f900,
+       0x01030898,
+       0x0004757e,
+/* 0x04dc: i2c_raise_scl_wait */
+       0x7e03e84e,
+       0x7e00005d,
+       0xf40004a9,
+       0x42b60901,
+       0xef1bf401,
+/* 0x04f0: i2c_raise_scl_done */
+       0x00f840fc,
+/* 0x04f4: i2c_start */
+       0x0004a97e,
+       0x7e0d11f4,
+       0xf40004bd,
+       0x0ef40611,
+/* 0x0505: i2c_start_rep */
+       0x7e00032e,
+       0x03000475,
+       0x048f7e01,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xd17e50fc,
+       0x64b60004,
+       0x1d11f404,
+/* 0x0530: i2c_start_send */
+       0x8f7e0003,
+       0x884e0004,
+       0x005d7e13,
+       0x7e000300,
+       0x4e000475,
+       0x5d7e1388,
+/* 0x054a: i2c_start_out */
+       0x00f80000,
+/* 0x054c: i2c_stop */
+       0x757e0003,
+       0x00030004,
+       0x00048f7e,
+       0x7e03e84e,
+       0x0300005d,
+       0x04757e01,
+       0x13884e00,
+       0x00005d7e,
+       0x8f7e0103,
+       0x884e0004,
+       0x005d7e13,
+/* 0x057b: i2c_bitw */
+       0x7e00f800,
+       0x4e00048f,
+       0x5d7e03e8,
+       0x76bb0000,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60004d1,
+       0x11f40464,
+       0x13884e17,
+       0x00005d7e,
+       0x757e0003,
+       0x884e0004,
+       0x005d7e13,
+/* 0x05b9: i2c_bitw_out */
+/* 0x05bb: i2c_bitr */
+       0x0300f800,
+       0x048f7e01,
+       0x03e84e00,
+       0x00005d7e,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x04d17e50,
+       0x0464b600,
+       0x7e1a11f4,
+       0x030004bd,
+       0x04757e00,
+       0x13884e00,
+       0x00005d7e,
+       0xf4013cf0,
+/* 0x05fe: i2c_bitr_done */
+       0x00f80131,
+/* 0x0600: i2c_get_byte */
+       0x08040005,
+/* 0x0604: i2c_get_byte_next */
+       0xbb0154b6,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x0005bb7e,
+       0xf40464b6,
+       0x53fd2a11,
+       0x0142b605,
+       0x03d81bf4,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x7b7e50fc,
+       0x64b60005,
+/* 0x064d: i2c_get_byte_done */
+/* 0x064f: i2c_put_byte */
+       0x0400f804,
+/* 0x0651: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x00057b7e,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x05bb7e50,
+       0x0464b600,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x06a7: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x06a9: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xf47e50fc,
+       0x64b60004,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb600064f,
+/* 0x06ee: i2c_addr_done */
+       0x00f80464,
+/* 0x06f0: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b705e4,
+       0x00f8d014,
+/* 0x06fc: i2c_acquire */
+       0x0006f07e,
+       0x0000047e,
+       0x7e03d9f0,
+       0xf800002e,
+/* 0x070d: i2c_release */
+       0x06f07e00,
+       0x00047e00,
+       0x03daf000,
+       0x00002e7e,
+/* 0x071e: i2c_recv */
+       0x32f400f8,
+       0xf8c1c701,
+       0xb00214b6,
+       0x1ff52816,
+       0x13b80137,
+       0x98000bd4,
+       0x13b80032,
+       0x98000bac,
+       0x31f40031,
+       0xf9d0f902,
+       0xf1d0f9e0,
+       0xf1000067,
+       0x92100063,
+       0x76bb0167,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60006fc,
+       0xd0fc0464,
+       0xf500d6b0,
+       0x0500b01b,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xa97e50fc,
+       0x64b60006,
+       0xcc11f504,
+       0xe0c5c700,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x064f7e50,
+       0x0464b600,
+       0x00a911f5,
+       0x76bb0105,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60006a9,
+       0x11f50464,
+       0x76bb0087,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb6000600,
+       0x11f40464,
+       0xe05bcb67,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x054c7e50,
+       0x0464b600,
+       0x74bd5bb2,
+/* 0x0823: i2c_recv_not_rd08 */
+       0xb0410ef4,
+       0x1bf401d6,
+       0x7e00053b,
+       0xf40006a9,
+       0xc5c73211,
+       0x064f7ee0,
+       0x2811f400,
+       0xa97e0005,
+       0x11f40006,
+       0xe0b5c71f,
+       0x00064f7e,
+       0x7e1511f4,
+       0xbd00054c,
+       0x08c5c774,
+       0xf4091bf4,
+       0x0ef40232,
+/* 0x0861: i2c_recv_not_wr08 */
+/* 0x0861: i2c_recv_done */
+       0xf8cec703,
+       0x00070d7e,
+       0xd0fce0fc,
+       0xb20912f4,
+       0x023f7e7c,
+/* 0x0875: i2c_recv_exit */
+/* 0x0877: i2c_init */
+       0xf800f800,
+/* 0x0879: test_recv */
        0x04584100,
        0xb60011cf,
        0x58400110,
@@ -1128,26 +1424,26 @@ uint32_t nv108_pwr_code[] = {
        0xe3f1d900,
        0x967e134f,
        0x00f80001,
-/* 0x0494: test_init */
+/* 0x0898: test_init */
        0x7e08004e,
        0xf8000196,
-/* 0x049d: idle_recv */
-/* 0x049f: idle */
+/* 0x08a1: idle_recv */
+/* 0x08a3: idle */
        0xf400f800,
        0x54410031,
        0x0011cf04,
        0x400110b6,
        0x01f60454,
-/* 0x04b3: idle_loop */
+/* 0x08b7: idle_loop */
        0x0104bd00,
        0x0232f458,
-/* 0x04b8: idle_proc */
-/* 0x04b8: idle_proc_exec */
+/* 0x08bc: idle_proc */
+/* 0x08bc: idle_proc_exec */
        0x1eb210f9,
        0x0002487e,
        0x11f410fc,
        0x0231f409,
-/* 0x04cb: idle_proc_next */
+/* 0x08cf: idle_proc_next */
        0xb6f00ef4,
        0x1fa65810,
        0xf4e81bf4,
@@ -1161,5 +1457,4 @@ uint32_t nv108_pwr_code[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x00000000,
 };
index 6fde0b89e5aa641de3add5489a98dea4e25c61bc..6744fcc0615160e657227285a70fc2c201bb7cb9 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 0fa4d7dcd407bb5bdb7802dcd4a6382c6bb84803..5a73fa620978aa0b300f87f80e6a1c049a2aa094 100644 (file)
@@ -89,9 +89,31 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x5f433249,
+       0x00000982,
+       0x00000825,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x54534554,
-       0x0000057b,
-       0x00000554,
+       0x000009ab,
+       0x00000984,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -112,8 +134,8 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x454c4449,
-       0x00000587,
-       0x00000585,
+       0x000009b7,
+       0x000009b5,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -133,12 +155,12 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,7 +193,7 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,11 +226,11 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
        0x00010000,
        0x00000000,
        0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
        0x00000001,
        0x00000000,
        0x00000496,
@@ -221,8 +243,18 @@ uint32_t nva3_pwr_data[] = {
        0x00010004,
        0x00000000,
        0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -725,6 +757,42 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00001000,
+       0x00004000,
+       0x00010000,
+       0x00000100,
+       0x00040000,
+       0x00100000,
+       0x00400000,
+       0x01000000,
+       0x04000000,
+       0x10000000,
+/* 0x0bd4: i2c_sda_map */
+       0x00002000,
+       0x00008000,
+       0x00020000,
+       0x00000200,
+       0x00080000,
+       0x00200000,
+       0x00800000,
+       0x02000000,
+       0x08000000,
+       0x20000000,
+/* 0x0bfc: i2c_ctrl */
+       0x0000e138,
+       0x0000e150,
+       0x0000e168,
+       0x0000e180,
+       0x0000e254,
+       0x0000e274,
+       0x0000e764,
+       0x0000e780,
+       0x0000e79c,
+       0x0000e7b8,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +803,6 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -787,15 +854,15 @@ uint32_t nva3_pwr_code[] = {
        0x07a007f1,
        0xd00604b6,
        0x04bd000e,
-       0xf001e7f0,
-       0x07f101e3,
+       0xf001d7f0,
+       0x07f101d3,
        0x04b607ac,
-       0x000ed006,
+       0x000dd006,
 /* 0x0022: rd32_wait */
-       0xe7f104bd,
-       0xe4b607ac,
-       0x00eecf06,
-       0x7000e4f1,
+       0xd7f104bd,
+       0xd4b607ac,
+       0x00ddcf06,
+       0x7000d4f1,
        0xf1f21bf4,
        0xb607a4d7,
        0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nva3_pwr_code[] = {
        0xb607a407,
        0x0dd00604,
        0xf004bd00,
-       0xe5f002e7,
-       0x01e3f0f0,
+       0xd5f002d7,
+       0x01d3f0f0,
        0x07ac07f1,
        0xd00604b6,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x006c: wr32_wait */
-       0x07ace7f1,
-       0xcf06e4b6,
-       0xe4f100ee,
+       0x07acd7f1,
+       0xcf06d4b6,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x007f: nsec */
        0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nva3_pwr_code[] = {
        0x9800f8df,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x025421f5,
        0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x010a: intr */
        0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nva3_pwr_code[] = {
        0x0088cf06,
        0xf40289c4,
        0x0080230b,
-       0x58e7f085,
+       0x58e7f09b,
        0x98cb21f4,
-       0x96b08509,
+       0x96b09b09,
        0x110bf400,
        0xb63407f0,
        0x09d00604,
        0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f148,
        0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nva3_pwr_code[] = {
        0x000ed006,
        0x0e8004bd,
 /* 0x0241: timer_enable */
-       0x0187f084,
+       0x0187f09a,
        0xb63807f0,
        0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nva3_pwr_code[] = {
        0xb8008a98,
        0x0bf406ae,
        0x5880b610,
-       0x021086b1,
+       0x026886b1,
        0xf4f01bf4,
 /* 0x02b2: find_done */
        0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nva3_pwr_code[] = {
        0x320bf406,
        0x94071ec4,
        0xe0b704ee,
-       0xeb980218,
+       0xeb980270,
        0x02ec9803,
        0x9801ed98,
        0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nva3_pwr_code[] = {
        0xe60bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0430: host_init */
        0x008017f1,
        0xf11014b6,
-       0xf1021815,
+       0xf1027015,
        0xb604d007,
        0x01d00604,
        0xf104bd00,
        0xb6008017,
        0x15f11014,
-       0x07f10298,
+       0x07f102f0,
        0x04b604dc,
        0x0001d006,
        0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nva3_pwr_code[] = {
        0x00139802,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12b855f9,
        0xec1ef406,
        0xe0fcd0fc,
        0x02b921f5,
 /* 0x0532: memx_info */
        0xc7f100f8,
-       0xb7f10354,
+       0xb7f103ac,
        0x21f50800,
        0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
        0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+       0xf40036b0,
+       0x07f1110b,
+       0x04b607e0,
+       0x0001d006,
+       0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+       0x07e407f1,
+       0xd00604b6,
+       0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+       0x36b000f8,
+       0x110bf400,
+       0x07e007f1,
+       0xd00604b6,
+       0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+       0x07f100f8,
+       0x04b607e4,
+       0x0002d006,
+       0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0431fd00,
+       0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+       0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+       0xe8e7f105,
+       0x7f21f403,
+       0x059821f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x05ed: i2c_start */
+       0x9821f500,
+       0x0d11f405,
+       0x05b021f5,
+       0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+       0x37f0300e,
+       0x5421f500,
+       0x0137f005,
+       0x057621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xc821f550,
+       0x0464b605,
+/* 0x062b: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f10576,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x0647: i2c_start_out */
+       0xf87f21f4,
+/* 0x0649: i2c_stop */
+       0x0037f000,
+       0x055421f5,
+       0xf50037f0,
+       0xf1057621,
+       0xf403e8e7,
+       0x37f07f21,
+       0x5421f501,
+       0x88e7f105,
+       0x7f21f413,
+       0xf50137f0,
+       0xf1057621,
+       0xf41388e7,
+       0x00f87f21,
+/* 0x067c: i2c_bitw */
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+       0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+       0x0137f000,
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f005b0,
+       0x5421f500,
+       0x88e7f105,
+       0x7f21f413,
+       0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+       0x00f80131,
+/* 0x0704: i2c_get_byte */
+       0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b606bd,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x7c21f550,
+       0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+       0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x067c21f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xbd21f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x07b1: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b605ed,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+/* 0x07f6: i2c_addr_done */
+       0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b702e4,
+       0xee980bfc,
+/* 0x0807: i2c_acquire */
+       0xf500f800,
+       0xf407f821,
+       0xd9f00421,
+       0x3f21f403,
+/* 0x0816: i2c_release */
+       0x21f500f8,
+       0x21f407f8,
+       0x03daf004,
+       0xf83f21f4,
+/* 0x0825: i2c_recv */
+       0x0132f400,
+       0xb6f8c1c7,
+       0x16b00214,
+       0x3a1ff528,
+       0xd413a001,
+       0x0032980b,
+       0x0bac13a0,
+       0xf4003198,
+       0xd0f90231,
+       0xd0f9e0f9,
+       0x000067f1,
+       0x100063f1,
+       0xbb016792,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x080721f5,
+       0xfc0464b6,
+       0x00d6b0d0,
+       0x00b31bf5,
+       0xbb0057f0,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x07b121f5,
+       0xf50464b6,
+       0xc700d011,
+       0x76bbe0c5,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+       0x11f50464,
+       0x57f000ad,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b607b1,
+       0x8a11f504,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60704,
+       0x6a11f404,
+       0xbbe05bcb,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x064921f5,
+       0xb90464b6,
+       0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+       0xb0430ef4,
+       0x1bf401d6,
+       0x0057f03d,
+       0x07b121f5,
+       0xc73311f4,
+       0x21f5e0c5,
+       0x11f40756,
+       0x0057f029,
+       0x07b121f5,
+       0xc71f11f4,
+       0x21f5e0b5,
+       0x11f40756,
+       0x4921f515,
+       0xc774bd06,
+       0x1bf408c5,
+       0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+       0xc7030ef4,
+       0x21f5f8ce,
+       0xe0fc0816,
+       0x12f4d0fc,
+       0x027cb90a,
+       0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+       0x00f800f8,
+/* 0x0984: test_recv */
        0x05d817f1,
        0xcf0614b6,
        0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nva3_pwr_code[] = {
        0x00e7f104,
        0x4fe3f1d9,
        0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
        0xf100f801,
        0xf50800e7,
        0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
        0xf400f800,
        0x17f10031,
        0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nva3_pwr_code[] = {
        0xf10110b6,
        0xb605d407,
        0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
        0xf004bd00,
        0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
        0xb910f902,
        0x21f5021e,
        0x10fc02c2,
        0xf40911f4,
        0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
        0x5810b6ef,
        0xf4061fb8,
        0x02f4e61b,
        0x0028f4dd,
        0x00bb0ef4,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
 };
index eaa64da68e3604b1537753cc314388311dd48514..48f79434a4491f30c61f95755d43c37097f73249 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 82c8e8b889178dd34e0eef6cf6a39fdd0d7a800d..4dba00d2dd1a6f579d19c4571964440ccbf077b5 100644 (file)
@@ -89,9 +89,31 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x5f433249,
+       0x00000982,
+       0x00000825,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x54534554,
-       0x0000057b,
-       0x00000554,
+       0x000009ab,
+       0x00000984,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -112,8 +134,8 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x454c4449,
-       0x00000587,
-       0x00000585,
+       0x000009b7,
+       0x000009b5,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -133,12 +155,12 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,7 +193,7 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,11 +226,11 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
        0x00010000,
        0x00000000,
        0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
        0x00000001,
        0x00000000,
        0x00000496,
@@ -221,8 +243,18 @@ uint32_t nvc0_pwr_data[] = {
        0x00010004,
        0x00000000,
        0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -725,6 +757,42 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00001000,
+       0x00004000,
+       0x00010000,
+       0x00000100,
+       0x00040000,
+       0x00100000,
+       0x00400000,
+       0x01000000,
+       0x04000000,
+       0x10000000,
+/* 0x0bd4: i2c_sda_map */
+       0x00002000,
+       0x00008000,
+       0x00020000,
+       0x00000200,
+       0x00080000,
+       0x00200000,
+       0x00800000,
+       0x02000000,
+       0x08000000,
+       0x20000000,
+/* 0x0bfc: i2c_ctrl */
+       0x0000e138,
+       0x0000e150,
+       0x0000e168,
+       0x0000e180,
+       0x0000e254,
+       0x0000e274,
+       0x0000e764,
+       0x0000e780,
+       0x0000e79c,
+       0x0000e7b8,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +803,6 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -787,15 +854,15 @@ uint32_t nvc0_pwr_code[] = {
        0x07a007f1,
        0xd00604b6,
        0x04bd000e,
-       0xf001e7f0,
-       0x07f101e3,
+       0xf001d7f0,
+       0x07f101d3,
        0x04b607ac,
-       0x000ed006,
+       0x000dd006,
 /* 0x0022: rd32_wait */
-       0xe7f104bd,
-       0xe4b607ac,
-       0x00eecf06,
-       0x7000e4f1,
+       0xd7f104bd,
+       0xd4b607ac,
+       0x00ddcf06,
+       0x7000d4f1,
        0xf1f21bf4,
        0xb607a4d7,
        0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nvc0_pwr_code[] = {
        0xb607a407,
        0x0dd00604,
        0xf004bd00,
-       0xe5f002e7,
-       0x01e3f0f0,
+       0xd5f002d7,
+       0x01d3f0f0,
        0x07ac07f1,
        0xd00604b6,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x006c: wr32_wait */
-       0x07ace7f1,
-       0xcf06e4b6,
-       0xe4f100ee,
+       0x07acd7f1,
+       0xcf06d4b6,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x007f: nsec */
        0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nvc0_pwr_code[] = {
        0x9800f8df,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x025421f5,
        0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x010a: intr */
        0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nvc0_pwr_code[] = {
        0x0088cf06,
        0xf40289c4,
        0x0080230b,
-       0x58e7f085,
+       0x58e7f09b,
        0x98cb21f4,
-       0x96b08509,
+       0x96b09b09,
        0x110bf400,
        0xb63407f0,
        0x09d00604,
        0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f148,
        0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nvc0_pwr_code[] = {
        0x000ed006,
        0x0e8004bd,
 /* 0x0241: timer_enable */
-       0x0187f084,
+       0x0187f09a,
        0xb63807f0,
        0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nvc0_pwr_code[] = {
        0xb8008a98,
        0x0bf406ae,
        0x5880b610,
-       0x021086b1,
+       0x026886b1,
        0xf4f01bf4,
 /* 0x02b2: find_done */
        0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nvc0_pwr_code[] = {
        0x320bf406,
        0x94071ec4,
        0xe0b704ee,
-       0xeb980218,
+       0xeb980270,
        0x02ec9803,
        0x9801ed98,
        0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nvc0_pwr_code[] = {
        0xe60bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0430: host_init */
        0x008017f1,
        0xf11014b6,
-       0xf1021815,
+       0xf1027015,
        0xb604d007,
        0x01d00604,
        0xf104bd00,
        0xb6008017,
        0x15f11014,
-       0x07f10298,
+       0x07f102f0,
        0x04b604dc,
        0x0001d006,
        0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nvc0_pwr_code[] = {
        0x00139802,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12b855f9,
        0xec1ef406,
        0xe0fcd0fc,
        0x02b921f5,
 /* 0x0532: memx_info */
        0xc7f100f8,
-       0xb7f10354,
+       0xb7f103ac,
        0x21f50800,
        0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
        0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+       0xf40036b0,
+       0x07f1110b,
+       0x04b607e0,
+       0x0001d006,
+       0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+       0x07e407f1,
+       0xd00604b6,
+       0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+       0x36b000f8,
+       0x110bf400,
+       0x07e007f1,
+       0xd00604b6,
+       0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+       0x07f100f8,
+       0x04b607e4,
+       0x0002d006,
+       0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0431fd00,
+       0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+       0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+       0xe8e7f105,
+       0x7f21f403,
+       0x059821f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x05ed: i2c_start */
+       0x9821f500,
+       0x0d11f405,
+       0x05b021f5,
+       0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+       0x37f0300e,
+       0x5421f500,
+       0x0137f005,
+       0x057621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xc821f550,
+       0x0464b605,
+/* 0x062b: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f10576,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x0647: i2c_start_out */
+       0xf87f21f4,
+/* 0x0649: i2c_stop */
+       0x0037f000,
+       0x055421f5,
+       0xf50037f0,
+       0xf1057621,
+       0xf403e8e7,
+       0x37f07f21,
+       0x5421f501,
+       0x88e7f105,
+       0x7f21f413,
+       0xf50137f0,
+       0xf1057621,
+       0xf41388e7,
+       0x00f87f21,
+/* 0x067c: i2c_bitw */
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+       0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+       0x0137f000,
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f005b0,
+       0x5421f500,
+       0x88e7f105,
+       0x7f21f413,
+       0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+       0x00f80131,
+/* 0x0704: i2c_get_byte */
+       0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b606bd,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x7c21f550,
+       0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+       0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x067c21f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xbd21f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x07b1: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b605ed,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+/* 0x07f6: i2c_addr_done */
+       0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b702e4,
+       0xee980bfc,
+/* 0x0807: i2c_acquire */
+       0xf500f800,
+       0xf407f821,
+       0xd9f00421,
+       0x3f21f403,
+/* 0x0816: i2c_release */
+       0x21f500f8,
+       0x21f407f8,
+       0x03daf004,
+       0xf83f21f4,
+/* 0x0825: i2c_recv */
+       0x0132f400,
+       0xb6f8c1c7,
+       0x16b00214,
+       0x3a1ff528,
+       0xd413a001,
+       0x0032980b,
+       0x0bac13a0,
+       0xf4003198,
+       0xd0f90231,
+       0xd0f9e0f9,
+       0x000067f1,
+       0x100063f1,
+       0xbb016792,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x080721f5,
+       0xfc0464b6,
+       0x00d6b0d0,
+       0x00b31bf5,
+       0xbb0057f0,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x07b121f5,
+       0xf50464b6,
+       0xc700d011,
+       0x76bbe0c5,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+       0x11f50464,
+       0x57f000ad,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b607b1,
+       0x8a11f504,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60704,
+       0x6a11f404,
+       0xbbe05bcb,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x064921f5,
+       0xb90464b6,
+       0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+       0xb0430ef4,
+       0x1bf401d6,
+       0x0057f03d,
+       0x07b121f5,
+       0xc73311f4,
+       0x21f5e0c5,
+       0x11f40756,
+       0x0057f029,
+       0x07b121f5,
+       0xc71f11f4,
+       0x21f5e0b5,
+       0x11f40756,
+       0x4921f515,
+       0xc774bd06,
+       0x1bf408c5,
+       0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+       0xc7030ef4,
+       0x21f5f8ce,
+       0xe0fc0816,
+       0x12f4d0fc,
+       0x027cb90a,
+       0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+       0x00f800f8,
+/* 0x0984: test_recv */
        0x05d817f1,
        0xcf0614b6,
        0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nvc0_pwr_code[] = {
        0x00e7f104,
        0x4fe3f1d9,
        0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
        0xf100f801,
        0xf50800e7,
        0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
        0xf400f800,
        0x17f10031,
        0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nvc0_pwr_code[] = {
        0xf10110b6,
        0xb605d407,
        0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
        0xf004bd00,
        0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
        0xb910f902,
        0x21f5021e,
        0x10fc02c2,
        0xf40911f4,
        0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
        0x5810b6ef,
        0xf4061fb8,
        0x02f4e61b,
        0x0028f4dd,
        0x00bb0ef4,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
 };
index 32d65ea254dd85c9b89677855d527c63d2b85654..8a89dfe41ce1ba8ddf7b808ef5534e5eefd418a9 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index ce65e2a4b789b4cfef72c9ee196bc0a69c20b906..5e24c6bc041d6aefbe8de51933ed4c30e0af3fcc 100644 (file)
@@ -89,33 +89,13 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x54534554,
-       0x000004eb,
-       0x000004ca,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x5f433249,
+       0x000008e3,
+       0x00000786,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
-       0x454c4449,
-       0x000004f7,
-       0x000004f5,
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -131,14 +111,13 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x54534554,
+       0x00000906,
+       0x000008e5,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
        0x00000000,
-/* 0x0214: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -154,6 +133,9 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x454c4449,
+       0x00000912,
+       0x00000910,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,11 +153,14 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
        0x00000000,
        0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
+/* 0x026c: time_next */
        0x00000000,
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,31 +189,11 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
-       0x00010000,
-       0x00000000,
-       0x000003f4,
-/* 0x0324: memx_func_next */
-       0x00000001,
-       0x00000000,
-       0x00000415,
-       0x00000002,
-       0x00000002,
-       0x00000430,
-       0x00040003,
-       0x00000000,
-       0x00000458,
-       0x00010004,
-       0x00000000,
-       0x00000472,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -261,10 +226,25 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0370: memx_func_head */
+       0x00010000,
        0x00000000,
+       0x000003f4,
+/* 0x037c: memx_func_next */
+       0x00000001,
        0x00000000,
+       0x00000415,
+       0x00000002,
+       0x00000002,
+       0x00000430,
+       0x00040003,
        0x00000000,
+       0x00000458,
+       0x00010004,
        0x00000000,
+       0x00000472,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +715,6 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -778,6 +757,29 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00000400,
+       0x00000800,
+       0x00001000,
+       0x00002000,
+       0x00004000,
+       0x00008000,
+       0x00010000,
+       0x00020000,
+       0x00040000,
+       0x00080000,
+/* 0x0bd4: i2c_sda_map */
+       0x00100000,
+       0x00200000,
+       0x00400000,
+       0x00800000,
+       0x01000000,
+       0x02000000,
+       0x04000000,
+       0x08000000,
+       0x10000000,
+       0x20000000,
        0x00000000,
 };
 
@@ -786,14 +788,14 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x0004: rd32 */
        0x07a007f1,
        0xbd000ed0,
-       0x01e7f004,
-       0xf101e3f0,
+       0x01d7f004,
+       0xf101d3f0,
        0xd007ac07,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x001c: rd32_wait */
-       0x07ace7f1,
-       0xf100eecf,
-       0xf47000e4,
+       0x07acd7f1,
+       0xf100ddcf,
+       0xf47000d4,
        0xd7f1f51b,
        0xddcf07a4,
 /* 0x0033: wr32 */
@@ -802,14 +804,14 @@ uint32_t nvd0_pwr_code[] = {
        0x04bd000e,
        0x07a407f1,
        0xbd000dd0,
-       0x02e7f004,
-       0xf0f0e5f0,
-       0x07f101e3,
-       0x0ed007ac,
+       0x02d7f004,
+       0xf0f0d5f0,
+       0x07f101d3,
+       0x0dd007ac,
 /* 0x0057: wr32_wait */
        0xf104bd00,
-       0xcf07ace7,
-       0xe4f100ee,
+       0xcf07acd7,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x0067: nsec */
        0xf000f8f5,
@@ -836,21 +838,21 @@ uint32_t nvd0_pwr_code[] = {
        0x9800f8e2,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x020621f5,
        0x0ef494bd,
 /* 0x00c5: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00d4: intr_watchdog_next_time_set */
 /* 0x00d7: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x00e6: intr */
        0x00f900f8,
@@ -868,15 +870,15 @@ uint32_t nvd0_pwr_code[] = {
        0x0887f004,
        0xc40088cf,
        0x0bf40289,
-       0x85008020,
+       0x9b008020,
        0xf458e7f0,
        0x0998a721,
-       0x0096b085,
+       0x0096b09b,
        0xf00e0bf4,
        0x09d03407,
        0x8004bd00,
 /* 0x013e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f13c,
        0x0099cf06,
@@ -929,7 +931,7 @@ uint32_t nvd0_pwr_code[] = {
        0x0ed03407,
        0x8004bd00,
 /* 0x01f6: timer_enable */
-       0x87f0840e,
+       0x87f09a0e,
        0x3807f001,
        0xbd0008d0,
 /* 0x0201: timer_done */
@@ -960,7 +962,7 @@ uint32_t nvd0_pwr_code[] = {
        0x06aeb800,
        0xb6100bf4,
        0x86b15880,
-       0x1bf40210,
+       0x1bf40268,
        0x0132f4f0,
 /* 0x0264: find_done */
        0xfc028eb9,
@@ -1024,7 +1026,7 @@ uint32_t nvd0_pwr_code[] = {
        0x0bf40612,
        0x071ec42f,
        0xb704ee94,
-       0x980218e0,
+       0x980270e0,
        0xec9803eb,
        0x01ed9802,
        0xf500ee98,
@@ -1048,7 +1050,7 @@ uint32_t nvd0_pwr_code[] = {
        0xec0bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1061,12 +1063,12 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x03be: host_init */
        0x17f100f8,
        0x14b60080,
-       0x1815f110,
+       0x7015f110,
        0xd007f102,
        0x0001d004,
        0x17f104bd,
        0x14b60080,
-       0x9815f110,
+       0xf015f110,
        0xdc07f102,
        0x0001d004,
        0x17f004bd,
@@ -1122,13 +1124,13 @@ uint32_t nvd0_pwr_code[] = {
        0x10b60013,
        0x10349504,
        0x980c30f0,
-       0x55f9c835,
+       0x55f9de35,
        0xf40612b8,
        0xd0fcec1e,
        0x21f5e0fc,
        0x00f8026b,
 /* 0x04a8: memx_info */
-       0x0354c7f1,
+       0x03acc7f1,
        0x0800b7f1,
        0x026b21f5,
 /* 0x04b6: memx_recv */
@@ -1140,49 +1142,342 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x04c6: perf_recv */
        0x00f800f8,
 /* 0x04c8: perf_init */
-/* 0x04ca: test_recv */
-       0x17f100f8,
-       0x11cf05d8,
-       0x0110b600,
-       0x05d807f1,
+/* 0x04ca: i2c_drive_scl */
+       0x36b000f8,
+       0x0e0bf400,
+       0x07e007f1,
        0xbd0001d0,
-       0x00e7f104,
-       0x4fe3f1d9,
-       0xb621f513,
-/* 0x04eb: test_init */
-       0xf100f801,
-       0xf50800e7,
-       0xf801b621,
-/* 0x04f5: idle_recv */
-/* 0x04f7: idle */
-       0xf400f800,
-       0x17f10031,
-       0x11cf05d4,
-       0x0110b600,
-       0x05d407f1,
-       0xbd0001d0,
-/* 0x050d: idle_loop */
-       0x5817f004,
-/* 0x0513: idle_proc */
-/* 0x0513: idle_proc_exec */
-       0xf90232f4,
-       0x021eb910,
-       0x027421f5,
-       0x11f410fc,
-       0x0231f409,
-/* 0x0527: idle_proc_next */
-       0xb6ef0ef4,
-       0x1fb85810,
-       0xe61bf406,
-       0xf4dd02f4,
-       0x0ef40028,
-       0x000000c1,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+/* 0x04db: i2c_drive_scl_lo */
+       0xf100f804,
+       0xd007e407,
+       0x04bd0001,
+/* 0x04e6: i2c_drive_sda */
+       0x36b000f8,
+       0x0e0bf400,
+       0x07e007f1,
+       0xbd0002d0,
+/* 0x04f7: i2c_drive_sda_lo */
+       0xf100f804,
+       0xd007e407,
+       0x04bd0002,
+/* 0x0502: i2c_sense_scl */
+       0x32f400f8,
+       0xc437f101,
+       0x0033cf07,
+       0xf40431fd,
+       0x31f4060b,
+/* 0x0515: i2c_sense_scl_done */
+/* 0x0517: i2c_sense_sda */
+       0xf400f801,
+       0x37f10132,
+       0x33cf07c4,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x052a: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x052c: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0xca21f501,
+/* 0x0539: i2c_raise_scl_wait */
+       0xe8e7f104,
+       0x6721f403,
+       0x050221f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x054d: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x0551: i2c_start */
+       0x0221f500,
+       0x0d11f405,
+       0x051721f5,
+       0xf40611f4,
+/* 0x0562: i2c_start_rep */
+       0x37f0300e,
+       0xca21f500,
+       0x0137f004,
+       0x04e621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x2c21f550,
+       0x0464b605,
+/* 0x058f: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f104e6,
+       0x21f41388,
+       0x0037f067,
+       0x04ca21f5,
+       0x1388e7f1,
+/* 0x05ab: i2c_start_out */
+       0xf86721f4,
+/* 0x05ad: i2c_stop */
+       0x0037f000,
+       0x04ca21f5,
+       0xf50037f0,
+       0xf104e621,
+       0xf403e8e7,
+       0x37f06721,
+       0xca21f501,
+       0x88e7f104,
+       0x6721f413,
+       0xf50137f0,
+       0xf104e621,
+       0xf41388e7,
+       0x00f86721,
+/* 0x05e0: i2c_bitw */
+       0x04e621f5,
+       0x03e8e7f1,
+       0xbb6721f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x052c21f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f067,
+       0x04ca21f5,
+       0x1388e7f1,
+/* 0x061f: i2c_bitw_out */
+       0xf86721f4,
+/* 0x0621: i2c_bitr */
+       0x0137f000,
+       0x04e621f5,
+       0x03e8e7f1,
+       0xbb6721f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x052c21f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f00517,
+       0xca21f500,
+       0x88e7f104,
+       0x6721f413,
+       0xf4013cf0,
+/* 0x0666: i2c_bitr_done */
+       0x00f80131,
+/* 0x0668: i2c_get_byte */
+       0xf00057f0,
+/* 0x066e: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60621,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xe021f550,
+       0x0464b605,
+/* 0x06b8: i2c_get_byte_done */
+/* 0x06ba: i2c_put_byte */
+       0x47f000f8,
+/* 0x06bd: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05e021f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x2121f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x0713: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x0715: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60551,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb606ba21,
+/* 0x075a: i2c_addr_done */
+       0x00f80464,
+/* 0x075c: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b705e4,
+       0x00f8d014,
+/* 0x0768: i2c_acquire */
+       0x075c21f5,
+       0xf00421f4,
+       0x21f403d9,
+/* 0x0777: i2c_release */
+       0xf500f833,
+       0xf4075c21,
+       0xdaf00421,
+       0x3321f403,
+/* 0x0786: i2c_recv */
+       0x32f400f8,
+       0xf8c1c701,
+       0xb00214b6,
+       0x1ff52816,
+       0x13a0013a,
+       0x32980bd4,
+       0xac13a000,
+       0x0031980b,
+       0xf90231f4,
+       0xf9e0f9d0,
+       0x0067f1d0,
+       0x0063f100,
+       0x01679210,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x6821f550,
+       0x0464b607,
+       0xd6b0d0fc,
+       0xb31bf500,
+       0x0057f000,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x1521f550,
+       0x0464b607,
+       0x00d011f5,
+       0xbbe0c5c7,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x06ba21f5,
+       0xf50464b6,
+       0xf000ad11,
+       0x76bb0157,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6071521,
+       0x11f50464,
+       0x76bb008a,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6066821,
+       0x11f40464,
+       0xe05bcb6a,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xad21f550,
+       0x0464b605,
+       0xbd025bb9,
+       0x430ef474,
+/* 0x088c: i2c_recv_not_rd08 */
+       0xf401d6b0,
+       0x57f03d1b,
+       0x1521f500,
+       0x3311f407,
+       0xf5e0c5c7,
+       0xf406ba21,
+       0x57f02911,
+       0x1521f500,
+       0x1f11f407,
+       0xf5e0b5c7,
+       0xf406ba21,
+       0x21f51511,
+       0x74bd05ad,
+       0xf408c5c7,
+       0x32f4091b,
+       0x030ef402,
+/* 0x08cc: i2c_recv_not_wr08 */
+/* 0x08cc: i2c_recv_done */
+       0xf5f8cec7,
+       0xfc077721,
+       0xf4d0fce0,
+       0x7cb90a12,
+       0x6b21f502,
+/* 0x08e1: i2c_recv_exit */
+/* 0x08e3: i2c_init */
+       0xf800f802,
+/* 0x08e5: test_recv */
+       0xd817f100,
+       0x0011cf05,
+       0xf10110b6,
+       0xd005d807,
+       0x04bd0001,
+       0xd900e7f1,
+       0x134fe3f1,
+       0x01b621f5,
+/* 0x0906: test_init */
+       0xe7f100f8,
+       0x21f50800,
+       0x00f801b6,
+/* 0x0910: idle_recv */
+/* 0x0912: idle */
+       0x31f400f8,
+       0xd417f100,
+       0x0011cf05,
+       0xf10110b6,
+       0xd005d407,
+       0x04bd0001,
+/* 0x0928: idle_loop */
+       0xf45817f0,
+/* 0x092e: idle_proc */
+/* 0x092e: idle_proc_exec */
+       0x10f90232,
+       0xf5021eb9,
+       0xfc027421,
+       0x0911f410,
+       0xf40231f4,
+/* 0x0942: idle_proc_next */
+       0x10b6ef0e,
+       0x061fb858,
+       0xf4e61bf4,
+       0x28f4dd02,
+       0xc10ef400,
        0x00000000,
        0x00000000,
        0x00000000,
index 5fb0cccc6c64b593dbe1d2728a4011e793744f21..574acfa44c8c78f327dcd9d59cc7e1b6e9b2bc1f 100644 (file)
@@ -7,6 +7,7 @@
 #define PROC_HOST 0x54534f48
 #define PROC_MEMX 0x584d454d
 #define PROC_PERF 0x46524550
+#define PROC_I2C_ 0x5f433249
 #define PROC_TEST 0x54534554
 
 /* KERN: message identifiers */
 #define MEMX_WAIT   3
 #define MEMX_DELAY  4
 
+/* I2C_: message identifiers */
+#define I2C__MSG_RD08 0
+#define I2C__MSG_WR08 1
+
+#define I2C__MSG_DATA0_PORT 24:31
+#define I2C__MSG_DATA0_ADDR 14:23
+
+#define I2C__MSG_DATA0_RD08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_RD08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_RD08_REG 0:7
+#define I2C__MSG_DATA1_RD08_VAL 0:7
+
+#define I2C__MSG_DATA0_WR08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_WR08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_WR08_SYNC 8:8
+#define I2C__MSG_DATA0_WR08_REG 0:7
+#define I2C__MSG_DATA1_WR08_VAL 0:7
+
 #endif
index e44ed7b93c6d88db3826a6c6dcb13efd5429385a..7610fc5f8fa256de8038e3770ca227a3d0150c64 100644 (file)
@@ -29,9 +29,9 @@
 
 static bool
 probe_monitoring_device(struct nouveau_i2c_port *i2c,
-                       struct i2c_board_info *info)
+                       struct i2c_board_info *info, void *data)
 {
-       struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
+       struct nouveau_therm_priv *priv = data;
        struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
        struct i2c_client *client;
 
@@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
           device. Let's try our static list.
         */
        i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                     nv_board_infos, probe_monitoring_device);
+                     nv_board_infos, probe_monitoring_device, therm);
 }
index ef3133e7575c8eaf937520cf750bd51effcd7505..7dd680ff2f6f63683f34e39a1d7821f3c73c140c 100644 (file)
@@ -72,13 +72,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
        vmm->flush(vm);
 }
 
-void
-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
-{
-       nouveau_vm_map_at(vma, 0, node);
-}
-
-void
+static void
 nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
                        struct nouveau_mem *mem)
 {
@@ -136,7 +130,7 @@ finish:
        vmm->flush(vm);
 }
 
-void
+static void
 nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
                  struct nouveau_mem *mem)
 {
@@ -174,6 +168,18 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
        vmm->flush(vm);
 }
 
+void
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
+{
+       if (node->sg)
+               nouveau_vm_map_sg_table(vma, 0, node->size << 12, node);
+       else
+       if (node->pages)
+               nouveau_vm_map_sg(vma, 0, node->size << 12, node);
+       else
+               nouveau_vm_map_at(vma, 0, node);
+}
+
 void
 nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
 {
index 936a71c5908076814a4aa8ffc5c2a3757e745ea5..7fdc51e2a571bee85b6fcf707890c8e4138ca8d9 100644 (file)
@@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
            get_tmds_slave(encoder))
                return;
 
-       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL);
+       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL);
        if (type < 0)
                return;
 
index b13ff0fc42de4b2dcaf175e4a1ec3a126f04732c..2f1ed61f7c8c9e39d44c1528410eb4aaeb83fe17 100644 (file)
@@ -77,11 +77,6 @@ nv04_display_create(struct drm_device *dev)
 
        nouveau_hw_save_vga_fonts(dev, 1);
 
-       ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000,
-                                NV04_DISP_CLASS, NULL, 0, &disp->core);
-       if (ret)
-               return ret;
-
        nv04_crtc_create(dev, 0);
        if (nv_two_heads(dev))
                nv04_crtc_create(dev, 1);
index 56a28db040004fe6ecfebb6b3b69c8feda6a85f5..4245fc3dab70e5ce06964cc70296ef4e6929a9b8 100644 (file)
@@ -80,7 +80,6 @@ struct nv04_display {
        struct nv04_mode_state saved_reg;
        uint32_t saved_vga_font[4][16384];
        uint32_t dac_users[4];
-       struct nouveau_object *core;
        struct nouveau_bo *image[2];
 };
 
index 32e7064b819b6df4f9e5847beba7a826eaaed726..ab03f7719d2d3af06687ea0b1e840290094ad8dd 100644 (file)
@@ -55,9 +55,12 @@ struct nouveau_plane {
        int hue;
        int saturation;
        int iturbt_709;
+
+       void (*set_params)(struct nouveau_plane *);
 };
 
 static uint32_t formats[] = {
+       DRM_FORMAT_YUYV,
        DRM_FORMAT_UYVY,
        DRM_FORMAT_NV12,
 };
@@ -140,10 +143,10 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
        nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
 
-       if (fb->pixel_format == DRM_FORMAT_NV12) {
+       if (fb->pixel_format != DRM_FORMAT_UYVY)
                format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
+       if (fb->pixel_format == DRM_FORMAT_NV12)
                format |= NV_PVIDEO_FORMAT_PLANAR;
-       }
        if (nv_plane->iturbt_709)
                format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
        if (nv_plane->colorkey & (1 << 24))
@@ -182,9 +185,9 @@ nv10_disable_plane(struct drm_plane *plane)
 }
 
 static void
-nv10_destroy_plane(struct drm_plane *plane)
+nv_destroy_plane(struct drm_plane *plane)
 {
-       nv10_disable_plane(plane);
+       plane->funcs->disable_plane(plane);
        drm_plane_cleanup(plane);
        kfree(plane);
 }
@@ -217,9 +220,9 @@ nv10_set_params(struct nouveau_plane *plane)
 }
 
 static int
-nv10_set_property(struct drm_plane *plane,
-                 struct drm_property *property,
-                 uint64_t value)
+nv_set_property(struct drm_plane *plane,
+               struct drm_property *property,
+               uint64_t value)
 {
        struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 
@@ -238,15 +241,16 @@ nv10_set_property(struct drm_plane *plane,
        else
                return -EINVAL;
 
-       nv10_set_params(nv_plane);
+       if (nv_plane->set_params)
+               nv_plane->set_params(nv_plane);
        return 0;
 }
 
 static const struct drm_plane_funcs nv10_plane_funcs = {
        .update_plane = nv10_update_plane,
        .disable_plane = nv10_disable_plane,
-       .set_property = nv10_set_property,
-       .destroy = nv10_destroy_plane,
+       .set_property = nv_set_property,
+       .destroy = nv_destroy_plane,
 };
 
 static void
@@ -266,7 +270,7 @@ nv10_overlay_init(struct drm_device *device)
        case 0x15:
        case 0x1a:
        case 0x20:
-               num_formats = 1;
+               num_formats = 2;
                break;
        }
 
@@ -321,8 +325,159 @@ nv10_overlay_init(struct drm_device *device)
        drm_object_attach_property(&plane->base.base,
                                   plane->props.iturbt_709, plane->iturbt_709);
 
+       plane->set_params = nv10_set_params;
        nv10_set_params(plane);
-       nv_wr32(dev, NV_PVIDEO_STOP, 1);
+       nv10_disable_plane(&plane->base);
+       return;
+cleanup:
+       drm_plane_cleanup(&plane->base);
+err:
+       kfree(plane);
+       nv_error(dev, "Failed to create plane\n");
+}
+
+static int
+nv04_update_plane(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 nouveau_device *dev = nouveau_dev(plane->dev);
+       struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+       struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+       struct nouveau_bo *cur = nv_plane->cur;
+       uint32_t overlay = 1;
+       int brightness = (nv_plane->brightness - 512) * 62 / 512;
+       int pitch, ret, i;
+
+       /* Source parameters given in 16.16 fixed point, ignore fractional. */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       pitch = ALIGN(src_w * 4, 0x100);
+
+       if (pitch > 0xffff)
+               return -ERANGE;
+
+       /* TODO: Compute an offset? Not sure how to do this for YUYV. */
+       if (src_x != 0 || src_y != 0)
+               return -ERANGE;
+
+       if (crtc_w < src_w || crtc_h < src_h)
+               return -ERANGE;
+
+       ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret)
+               return ret;
+
+       nv_plane->cur = nv_fb->nvbo;
+
+       nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+
+       for (i = 0; i < 2; i++) {
+               nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+                       nv_fb->nvbo->bo.offset);
+               nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
+               nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+       }
+       nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
+       nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
+       nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
+               (uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
+
+       /* It should be possible to convert hue/contrast to this */
+       nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
+       nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
+       nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
+       nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
+
+       nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
+       nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
+
+       nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
+       nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
+
+       nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
+
+       if (nv_plane->colorkey & (1 << 24))
+               overlay |= 0x10;
+       if (fb->pixel_format == DRM_FORMAT_YUYV)
+               overlay |= 0x100;
+
+       nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
+
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
+
+       if (cur)
+               nouveau_bo_unpin(cur);
+
+       return 0;
+}
+
+static int
+nv04_disable_plane(struct drm_plane *plane)
+{
+       struct nouveau_device *dev = nouveau_dev(plane->dev);
+       struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+
+       nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
+       nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+       if (nv_plane->cur) {
+               nouveau_bo_unpin(nv_plane->cur);
+               nv_plane->cur = NULL;
+       }
+
+       return 0;
+}
+
+static const struct drm_plane_funcs nv04_plane_funcs = {
+       .update_plane = nv04_update_plane,
+       .disable_plane = nv04_disable_plane,
+       .set_property = nv_set_property,
+       .destroy = nv_destroy_plane,
+};
+
+static void
+nv04_overlay_init(struct drm_device *device)
+{
+       struct nouveau_device *dev = nouveau_dev(device);
+       struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+       int ret;
+
+       if (!plane)
+               return;
+
+       ret = drm_plane_init(device, &plane->base, 1 /* single crtc */,
+                            &nv04_plane_funcs,
+                            formats, 2, false);
+       if (ret)
+               goto err;
+
+       /* Set up the plane properties */
+       plane->props.colorkey = drm_property_create_range(
+                       device, 0, "colorkey", 0, 0x01ffffff);
+       plane->props.brightness = drm_property_create_range(
+                       device, 0, "brightness", 0, 1024);
+       if (!plane->props.colorkey ||
+           !plane->props.brightness)
+               goto cleanup;
+
+       plane->colorkey = 0;
+       drm_object_attach_property(&plane->base.base,
+                                  plane->props.colorkey, plane->colorkey);
+
+       plane->brightness = 512;
+       drm_object_attach_property(&plane->base.base,
+                                  plane->props.brightness, plane->brightness);
+
+       nv04_disable_plane(&plane->base);
        return;
 cleanup:
        drm_plane_cleanup(&plane->base);
@@ -335,6 +490,8 @@ void
 nouveau_overlay_init(struct drm_device *device)
 {
        struct nouveau_device *dev = nouveau_dev(device);
-       if (dev->chipset >= 0x10 && dev->chipset <= 0x40)
+       if (dev->chipset < 0x10)
+               nv04_overlay_init(device);
+       else if (dev->chipset <= 0x40)
                nv10_overlay_init(device);
 }
index cc4b208ce546d50aad1813810981099fe6d81935..244822df8ffc73d1e9f15075c7ee6faa54368a84 100644 (file)
@@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index)
        struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
 
        return i2c->identify(i2c, i2c_index, "TV encoder",
-                            nv04_tv_encoder_info, NULL);
+                            nv04_tv_encoder_info, NULL, NULL);
 }
 
 
index 6828d81ed7b99daea875ffd06c4dd399d4aa05dd..900fae01793e7884ee8033a11d6c247cbeb36678 100644 (file)
@@ -447,6 +447,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (ret)
                goto done;
 
+       info->offset = ntfy->node->offset;
+
 done:
        if (ret)
                nouveau_abi16_ntfy_fini(chan, ntfy);
index 95c740454049ad1b4a4cf23c2bc63d7038c7a362..d9f6120e972e649ccc77be83abb9a53f9660ec9a 100644 (file)
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
        bool dsm_detected;
        bool optimus_detected;
        acpi_handle dhandle;
+       acpi_handle other_handle;
        acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
@@ -65,6 +66,7 @@ bool nouveau_is_v1_dsm(void) {
 #define NOUVEAU_DSM_HAS_MUX 0x1
 #define NOUVEAU_DSM_HAS_OPT 0x2
 
+#ifdef CONFIG_VGA_SWITCHEROO
 static const char nouveau_dsm_muid[] = {
        0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
        0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -260,9 +262,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
        if (!dhandle)
                return false;
 
-       if (!acpi_has_method(dhandle, "_DSM"))
+       if (!acpi_has_method(dhandle, "_DSM")) {
+               nouveau_dsm_priv.other_handle = dhandle;
                return false;
-
+       }
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
@@ -338,6 +341,16 @@ static bool nouveau_dsm_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                        acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when _DSM is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
+               acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
                ret = true;
        }
 
@@ -376,6 +389,11 @@ void nouveau_unregister_dsm_handler(void)
        if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
                vga_switcheroo_unregister_handler();
 }
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+void nouveau_switcheroo_optimus_dsm(void) {}
+#endif
 
 /* retrieve the ROM in 4k blocks */
 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
index c0fde6b9393cb24fa602e838fdf145657d059d05..488686d490c0c7a96ba016e0f55a4beffcda6e4f 100644 (file)
@@ -560,28 +560,6 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 }
 
 
-/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
- * TTM_PL_{VRAM,TT} directly.
- */
-
-static int
-nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
-                             struct nouveau_bo *nvbo, bool evict,
-                             bool no_wait_gpu, struct ttm_mem_reg *new_mem)
-{
-       struct nouveau_fence *fence = NULL;
-       int ret;
-
-       ret = nouveau_fence_new(chan, false, &fence);
-       if (ret)
-               return ret;
-
-       ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, evict,
-                                       no_wait_gpu, new_mem);
-       nouveau_fence_unref(&fence);
-       return ret;
-}
-
 static int
 nve0_bo_move_init(struct nouveau_channel *chan, u32 handle)
 {
@@ -798,25 +776,25 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
        struct nouveau_mem *node = old_mem->mm_node;
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
        u64 length = (new_mem->num_pages << PAGE_SHIFT);
        u64 src_offset = node->vma[0].offset;
        u64 dst_offset = node->vma[1].offset;
+       int src_tiled = !!node->memtype;
+       int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype;
        int ret;
 
        while (length) {
                u32 amount, stride, height;
 
+               ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled));
+               if (ret)
+                       return ret;
+
                amount  = min(length, (u64)(4 * 1024 * 1024));
                stride  = 16 * 4;
                height  = amount / stride;
 
-               if (old_mem->mem_type == TTM_PL_VRAM &&
-                   nouveau_bo_tile_layout(nvbo)) {
-                       ret = RING_SPACE(chan, 8);
-                       if (ret)
-                               return ret;
-
+               if (src_tiled) {
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
@@ -826,19 +804,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
                } else {
-                       ret = RING_SPACE(chan, 2);
-                       if (ret)
-                               return ret;
-
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
                        OUT_RING  (chan, 1);
                }
-               if (new_mem->mem_type == TTM_PL_VRAM &&
-                   nouveau_bo_tile_layout(nvbo)) {
-                       ret = RING_SPACE(chan, 8);
-                       if (ret)
-                               return ret;
-
+               if (dst_tiled) {
                        BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
@@ -848,18 +817,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
                } else {
-                       ret = RING_SPACE(chan, 2);
-                       if (ret)
-                               return ret;
-
                        BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);
                        OUT_RING  (chan, 1);
                }
 
-               ret = RING_SPACE(chan, 14);
-               if (ret)
-                       return ret;
-
                BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);
                OUT_RING  (chan, upper_32_bits(src_offset));
                OUT_RING  (chan, upper_32_bits(dst_offset));
@@ -953,23 +914,28 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 }
 
 static int
-nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
-                  struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
+                    struct ttm_mem_reg *mem)
 {
-       struct nouveau_mem *node = mem->mm_node;
+       struct nouveau_mem *old_node = bo->mem.mm_node;
+       struct nouveau_mem *new_node = mem->mm_node;
+       u64 size = (u64)mem->num_pages << PAGE_SHIFT;
        int ret;
 
-       ret = nouveau_vm_get(nv_client(chan->cli)->vm, mem->num_pages <<
-                            PAGE_SHIFT, node->page_shift,
-                            NV_MEM_ACCESS_RW, vma);
+       ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift,
+                            NV_MEM_ACCESS_RW, &old_node->vma[0]);
        if (ret)
                return ret;
 
-       if (mem->mem_type == TTM_PL_VRAM)
-               nouveau_vm_map(vma, node);
-       else
-               nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node);
+       ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift,
+                            NV_MEM_ACCESS_RW, &old_node->vma[1]);
+       if (ret) {
+               nouveau_vm_put(&old_node->vma[0]);
+               return ret;
+       }
 
+       nouveau_vm_map(&old_node->vma[0], old_node);
+       nouveau_vm_map(&old_node->vma[1], new_node);
        return 0;
 }
 
@@ -979,35 +945,34 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 {
        struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_channel *chan = drm->ttm.chan;
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct ttm_mem_reg *old_mem = &bo->mem;
+       struct nouveau_fence *fence;
        int ret;
 
-       mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
-
        /* create temporary vmas for the transfer and attach them to the
         * old nouveau_mem node, these will get cleaned up after ttm has
         * destroyed the ttm_mem_reg
         */
        if (nv_device(drm->device)->card_type >= NV_50) {
-               struct nouveau_mem *node = old_mem->mm_node;
-
-               ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
-               if (ret)
-                       goto out;
-
-               ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+               ret = nouveau_bo_move_prep(drm, bo, new_mem);
                if (ret)
-                       goto out;
+                       return ret;
        }
 
-       ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+       mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
+       ret = nouveau_fence_sync(bo->sync_obj, chan);
        if (ret == 0) {
-               ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
-                                                   no_wait_gpu, new_mem);
+               ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+               if (ret == 0) {
+                       ret = nouveau_fence_new(chan, false, &fence);
+                       if (ret == 0) {
+                               ret = ttm_bo_move_accel_cleanup(bo, fence,
+                                                               evict,
+                                                               no_wait_gpu,
+                                                               new_mem);
+                               nouveau_fence_unref(&fence);
+                       }
+               }
        }
-
-out:
        mutex_unlock(&chan->cli->mutex);
        return ret;
 }
@@ -1147,19 +1112,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
                return;
 
        list_for_each_entry(vma, &nvbo->vma_list, head) {
-               if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
+               if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM &&
+                             (new_mem->mem_type == TTM_PL_VRAM ||
+                              nvbo->page_shift != vma->vm->vmm->lpg_shift)) {
                        nouveau_vm_map(vma, new_mem->mm_node);
-               } else
-               if (new_mem && new_mem->mem_type == TTM_PL_TT &&
-                   nvbo->page_shift == vma->vm->vmm->spg_shift) {
-                       if (((struct nouveau_mem *)new_mem->mm_node)->sg)
-                               nouveau_vm_map_sg_table(vma, 0, new_mem->
-                                                 num_pages << PAGE_SHIFT,
-                                                 new_mem->mm_node);
-                       else
-                               nouveau_vm_map_sg(vma, 0, new_mem->
-                                                 num_pages << PAGE_SHIFT,
-                                                 new_mem->mm_node);
                } else {
                        nouveau_vm_unmap(vma);
                }
@@ -1224,28 +1180,27 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
                goto out;
        }
 
-       /* CPU copy if we have no accelerated method available */
-       if (!drm->ttm.move) {
-               ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
-               goto out;
-       }
-
        /* Hardware assisted copy. */
-       if (new_mem->mem_type == TTM_PL_SYSTEM)
-               ret = nouveau_bo_move_flipd(bo, evict, intr,
-                                           no_wait_gpu, new_mem);
-       else if (old_mem->mem_type == TTM_PL_SYSTEM)
-               ret = nouveau_bo_move_flips(bo, evict, intr,
-                                           no_wait_gpu, new_mem);
-       else
-               ret = nouveau_bo_move_m2mf(bo, evict, intr,
-                                          no_wait_gpu, new_mem);
-
-       if (!ret)
-               goto out;
+       if (drm->ttm.move) {
+               if (new_mem->mem_type == TTM_PL_SYSTEM)
+                       ret = nouveau_bo_move_flipd(bo, evict, intr,
+                                                   no_wait_gpu, new_mem);
+               else if (old_mem->mem_type == TTM_PL_SYSTEM)
+                       ret = nouveau_bo_move_flips(bo, evict, intr,
+                                                   no_wait_gpu, new_mem);
+               else
+                       ret = nouveau_bo_move_m2mf(bo, evict, intr,
+                                                  no_wait_gpu, new_mem);
+               if (!ret)
+                       goto out;
+       }
 
        /* Fallback to software copy. */
-       ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+       spin_lock(&bo->bdev->fence_lock);
+       ret = ttm_bo_wait(bo, true, intr, no_wait_gpu);
+       spin_unlock(&bo->bdev->fence_lock);
+       if (ret == 0)
+               ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
 
 out:
        if (nv_device(drm->device)->card_type < NV_50) {
@@ -1271,6 +1226,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
        struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
        struct nouveau_drm *drm = nouveau_bdev(bdev);
+       struct nouveau_mem *node = mem->mm_node;
        struct drm_device *dev = drm->dev;
        int ret;
 
@@ -1293,14 +1249,16 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                        mem->bus.is_iomem = !dev->agp->cant_use_aperture;
                }
 #endif
-               break;
+               if (!node->memtype)
+                       /* untiled */
+                       break;
+               /* fallthrough, tiled memory */
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
                mem->bus.base = pci_resource_start(dev->pdev, 1);
                mem->bus.is_iomem = true;
                if (nv_device(drm->device)->card_type >= NV_50) {
                        struct nouveau_bar *bar = nouveau_bar(drm->device);
-                       struct nouveau_mem *node = mem->mm_node;
 
                        ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,
                                        &node->bar_vma);
@@ -1336,6 +1294,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct nouveau_device *device = nv_device(drm->device);
        u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT;
+       int ret;
 
        /* as long as the bo isn't in vram, and isn't tiled, we've got
         * nothing to do here.
@@ -1344,10 +1303,20 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
                if (nv_device(drm->device)->card_type < NV_50 ||
                    !nouveau_bo_tile_layout(nvbo))
                        return 0;
+
+               if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+                       nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0);
+
+                       ret = nouveau_bo_validate(nvbo, false, false);
+                       if (ret)
+                               return ret;
+               }
+               return 0;
        }
 
        /* make sure bo is in mappable vram */
-       if (bo->mem.start + bo->mem.num_pages < mappable)
+       if (nv_device(drm->device)->card_type >= NV_50 ||
+           bo->mem.start + bo->mem.num_pages < mappable)
                return 0;
 
 
@@ -1535,7 +1504,6 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
                   struct nouveau_vma *vma)
 {
        const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
-       struct nouveau_mem *node = nvbo->bo.mem.mm_node;
        int ret;
 
        ret = nouveau_vm_get(vm, size, nvbo->page_shift,
@@ -1543,15 +1511,10 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
        if (ret)
                return ret;
 
-       if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+       if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
+           (nvbo->bo.mem.mem_type == TTM_PL_VRAM ||
+            nvbo->page_shift != vma->vm->vmm->lpg_shift))
                nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
-       else if (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-                nvbo->page_shift == vma->vm->vmm->spg_shift) {
-               if (node->sg)
-                       nouveau_vm_map_sg_table(vma, 0, size, node);
-               else
-                       nouveau_vm_map_sg(vma, 0, size, node);
-       }
 
        list_add_tail(&vma->head, &nvbo->vma_list);
        vma->refcount = 1;
index 29c3efdfc7dd714e00ae03525d0b9528fce841cd..b4262ad66b182de48af73965fb3c0ce4af250e4a 100644 (file)
@@ -74,14 +74,14 @@ nouveau_display_vblank_fini(struct drm_device *dev)
        struct nouveau_display *disp = nouveau_display(dev);
        int i;
 
+       drm_vblank_cleanup(dev);
+
        if (disp->vblank) {
                for (i = 0; i < dev->mode_config.num_crtc; i++)
                        nouveau_event_ref(NULL, &disp->vblank[i]);
                kfree(disp->vblank);
                disp->vblank = NULL;
        }
-
-       drm_vblank_cleanup(dev);
 }
 
 static int
@@ -407,10 +407,31 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_disable(dev);
 
        if (drm->vbios.dcb.entries) {
-               if (nv_device(drm->device)->card_type < NV_50)
-                       ret = nv04_display_create(dev);
-               else
-                       ret = nv50_display_create(dev);
+               static const u16 oclass[] = {
+                       NVF0_DISP_CLASS,
+                       NVE0_DISP_CLASS,
+                       NVD0_DISP_CLASS,
+                       NVA3_DISP_CLASS,
+                       NV94_DISP_CLASS,
+                       NVA0_DISP_CLASS,
+                       NV84_DISP_CLASS,
+                       NV50_DISP_CLASS,
+                       NV04_DISP_CLASS,
+               };
+               int i;
+
+               for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
+                       ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
+                                                NVDRM_DISPLAY, oclass[i],
+                                                NULL, 0, &disp->core);
+               }
+
+               if (ret == 0) {
+                       if (nv_mclass(disp->core) < NV50_DISP_CLASS)
+                               ret = nv04_display_create(dev);
+                       else
+                               ret = nv50_display_create(dev);
+               }
        } else {
                ret = 0;
        }
@@ -439,6 +460,7 @@ void
 nouveau_display_destroy(struct drm_device *dev)
 {
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_drm *drm = nouveau_drm(dev);
 
        nouveau_backlight_exit(dev);
        nouveau_display_vblank_fini(dev);
@@ -449,6 +471,8 @@ nouveau_display_destroy(struct drm_device *dev)
        if (disp->dtor)
                disp->dtor(dev);
 
+       nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY);
+
        nouveau_drm(dev)->display = NULL;
        kfree(disp);
 }
@@ -603,6 +627,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        if (!s)
                return -ENOMEM;
 
+       if (new_bo != old_bo) {
+               ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
+               if (ret)
+                       goto fail_free;
+       }
+
+       mutex_lock(&chan->cli->mutex);
+
        /* synchronise rendering channel with the kernel's channel */
        spin_lock(&new_bo->bo.bdev->fence_lock);
        fence = nouveau_fence_ref(new_bo->bo.sync_obj);
@@ -610,15 +642,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        ret = nouveau_fence_sync(fence, chan);
        nouveau_fence_unref(&fence);
        if (ret)
-               return ret;
+               goto fail_free;
 
-       if (new_bo != old_bo) {
-               ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       goto fail_free;
-       }
-
-       mutex_lock(&chan->cli->mutex);
        ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
        if (ret)
                goto fail_unpin;
index 8bc8bab90e8d34462f0b484a90710a9094247216..73aa231130b8ddbb8e610881367f6daa81de070f 100644 (file)
@@ -36,6 +36,7 @@ struct nouveau_display {
        int  (*init)(struct drm_device *);
        void (*fini)(struct drm_device *);
 
+       struct nouveau_object *core;
        struct nouveau_eventh **vblank;
 
        struct drm_property *dithering_mode;
index 40f91e1e58422f0cdd7db3f607cde397966a7e8d..c177272152e24b7fb525891b8308668abfbeb460 100644 (file)
@@ -100,7 +100,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
 
        chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
 
-       DRM_MEMORYBARRIER();
+       mb();
        /* Flush writes. */
        nouveau_bo_rd32(pb, 0);
 
index 984004d66a6d313d1934230bc654c091a77b5f8f..dc0e0c5cadb48753d0c814f4b24586620053fb10 100644 (file)
@@ -155,7 +155,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data)
 }
 
 #define WRITE_PUT(val) do {                                                    \
-       DRM_MEMORYBARRIER();                                                   \
+       mb();                                                   \
        nouveau_bo_rd32(chan->push.buffer, 0);                                 \
        nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset);  \
 } while (0)
index 4b0fb6c66be918857bc6529b3a7c5a7c7a49a498..23ca7a517246feda3e7dfae782683c88c2bc64a5 100644 (file)
@@ -54,6 +54,7 @@ enum nouveau_drm_handle {
        NVDRM_CLIENT  = 0xffffffff,
        NVDRM_DEVICE  = 0xdddddddd,
        NVDRM_CONTROL = 0xdddddddc,
+       NVDRM_DISPLAY = 0xd1500000,
        NVDRM_PUSH    = 0xbbbb0000, /* |= client chid */
        NVDRM_CHAN    = 0xcccc0000, /* |= client chid */
        NVDRM_NVSW    = 0x55550000,
index 40cf52e6d6d21ffb818f70b2b01be3b5f5e02b95..90074d620e31265bdcc70d4b7285fc9be077fee8 100644 (file)
@@ -143,7 +143,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
        int ret;
 
        fence->channel  = chan;
-       fence->timeout  = jiffies + (15 * DRM_HZ);
+       fence->timeout  = jiffies + (15 * HZ);
        fence->sequence = ++fctx->sequence;
 
        ret = fctx->emit(fence);
index 78a27f8ad7d97be653a63506bb60bd9c7b518252..27c3fd89e8ceb657595d188a8a3ff16cadde0edc 100644 (file)
@@ -463,12 +463,6 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-               ret = validate_sync(chan, nvbo);
-               if (unlikely(ret)) {
-                       NV_ERROR(cli, "fail pre-validate sync\n");
-                       return ret;
-               }
-
                ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
                                             b->write_domains,
                                             b->valid_domains);
@@ -506,7 +500,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
                        b->presumed.valid = 0;
                        relocs++;
 
-                       if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+                       if (copy_to_user(&upbbo[nvbo->pbbo_index].presumed,
                                             &b->presumed, sizeof(b->presumed)))
                                return -EFAULT;
                }
@@ -593,7 +587,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
        if (!mem)
                return ERR_PTR(-ENOMEM);
 
-       if (DRM_COPY_FROM_USER(mem, userptr, size)) {
+       if (copy_from_user(mem, userptr, size)) {
                u_free(mem);
                return ERR_PTR(-EFAULT);
        }
index 0843ebc910d4d6062ce94023f70dde1f1cc00ea0..a4d22e5eb176ef342023fdf0e581c564139139ed 100644 (file)
@@ -31,16 +31,17 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 {
        struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
        struct nouveau_mem *node = mem->mm_node;
-       u64 size = mem->num_pages << 12;
 
        if (ttm->sg) {
-               node->sg = ttm->sg;
-               nouveau_vm_map_sg_table(&node->vma[0], 0, size, node);
+               node->sg    = ttm->sg;
+               node->pages = NULL;
        } else {
+               node->sg    = NULL;
                node->pages = nvbe->ttm.dma_address;
-               nouveau_vm_map_sg(&node->vma[0], 0, size, node);
        }
+       node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
 
+       nouveau_vm_map(&node->vma[0], node);
        nvbe->node = node;
        return 0;
 }
@@ -67,9 +68,13 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 
        /* noop: bound in move_notify() */
        if (ttm->sg) {
-               node->sg = ttm->sg;
-       } else
+               node->sg    = ttm->sg;
+               node->pages = NULL;
+       } else {
+               node->sg    = NULL;
                node->pages = nvbe->ttm.dma_address;
+       }
+       node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
        return 0;
 }
 
index 19e3757291fba09434de033622fd4f5f6b35ea8c..d45d50da978f07870fb2bfc703ef509b4a2482f9 100644 (file)
@@ -171,6 +171,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
+
        node->page_shift = 12;
 
        switch (nv_device(drm->device)->card_type) {
index 4e384a2f99c3627ea0fc6e31f5f0e34ac95e71e8..6ae7a697866e1ccca6e3fc4aa481def0e1e82992 100644 (file)
@@ -2199,16 +2199,6 @@ nv50_display_destroy(struct drm_device *dev)
 int
 nv50_display_create(struct drm_device *dev)
 {
-       static const u16 oclass[] = {
-               NVF0_DISP_CLASS,
-               NVE0_DISP_CLASS,
-               NVD0_DISP_CLASS,
-               NVA3_DISP_CLASS,
-               NV94_DISP_CLASS,
-               NVA0_DISP_CLASS,
-               NV84_DISP_CLASS,
-               NV50_DISP_CLASS,
-       };
        struct nouveau_device *device = nouveau_dev(dev);
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct dcb_table *dcb = &drm->vbios.dcb;
@@ -2225,6 +2215,7 @@ nv50_display_create(struct drm_device *dev)
        nouveau_display(dev)->dtor = nv50_display_destroy;
        nouveau_display(dev)->init = nv50_display_init;
        nouveau_display(dev)->fini = nv50_display_fini;
+       disp->core = nouveau_display(dev)->core;
 
        /* small shared memory area we use for notifiers and semaphores */
        ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2240,17 +2231,6 @@ nv50_display_create(struct drm_device *dev)
                        nouveau_bo_ref(NULL, &disp->sync);
        }
 
-       if (ret)
-               goto out;
-
-       /* attempt to allocate a supported evo display class */
-       ret = -ENODEV;
-       for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) {
-               ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
-                                        0xd1500000, oclass[i], NULL, 0,
-                                        &disp->core);
-       }
-
        if (ret)
                goto out;
 
index c27f59da7f2935f0fe3a1908b9a73c9a4c6b7529..d4c04d69fc4df62a62352db72cd035ae6e5e53d1 100644 (file)
@@ -48,7 +48,7 @@ static int mm_show(struct seq_file *m, void *arg)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static int fb_show(struct seq_file *m, void *arg)
index c57e99cc3caa4c5a1abdec613b658d084cbf5213..bf39fcc49e0f181ddcbf340632fa4f77c8b1bb10 100644 (file)
@@ -695,12 +695,11 @@ static int pdev_probe(struct platform_device *device)
 static int pdev_remove(struct platform_device *device)
 {
        DBG("");
-       drm_platform_exit(&omap_drm_driver, device);
 
        omap_disconnect_dssdevs();
        omap_crtc_pre_uninit();
 
-       platform_driver_unregister(&omap_dmm_driver);
+       drm_put_dev(platform_get_drvdata(device));
        return 0;
 }
 
index 26dfd2129943a0060571ac51ca588eac066c707a..428b2981fd685f3e42b3ec4d0a63021a94fdaf15 100644 (file)
@@ -141,7 +141,7 @@ int omap_gem_resume(struct device *dev);
 
 int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id);
 void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t omap_irq_handler(int irq, void *arg);
 void omap_irq_preinstall(struct drm_device *dev);
 int omap_irq_postinstall(struct drm_device *dev);
 void omap_irq_uninstall(struct drm_device *dev);
index f2b8f0668c0c1701887e8b6c4a8ccb3b3bf1952b..f466c4aaee9464c7ca4c16d684a4e7d4bfec5584 100644 (file)
@@ -123,12 +123,16 @@ static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
 {
        int i;
 
+       drm_modeset_lock_all(fb->dev);
+
        for (i = 0; i < num_clips; i++) {
                omap_framebuffer_flush(fb, clips[i].x1, clips[i].y1,
                                        clips[i].x2 - clips[i].x1,
                                        clips[i].y2 - clips[i].y1);
        }
 
+       drm_modeset_unlock_all(fb->dev);
+
        return 0;
 }
 
index da690d0e0f0318b6bc46e8cb12b161096d16d384..f035d2bceae7db358427c689b3a1fdd6cde28334 100644 (file)
@@ -187,7 +187,7 @@ void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)
        dispc_runtime_put();
 }
 
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t omap_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct omap_drm_private *priv = dev->dev_private;
@@ -322,7 +322,7 @@ int omap_drm_irq_uninstall(struct drm_device *dev)
        if (dev->num_crtcs) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                for (i = 0; i < dev->num_crtcs; i++) {
-                       DRM_WAKEUP(&dev->vblank[i].queue);
+                       wake_up(&dev->vblank[i].queue);
                        dev->vblank[i].enabled = false;
                        dev->vblank[i].last =
                                dev->driver->get_vblank_counter(dev, i);
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
new file mode 100644 (file)
index 0000000..3e0f13d
--- /dev/null
@@ -0,0 +1,19 @@
+config DRM_PANEL
+       bool
+       depends on DRM
+       help
+         Panel registration and lookup framework.
+
+menu "Display Panels"
+       depends on DRM_PANEL
+
+config DRM_PANEL_SIMPLE
+       tristate "support for simple panels"
+       depends on OF
+       help
+         DRM panel driver for dumb panels that need at most a regulator and
+         a GPIO to be powered up. Optionally a backlight can be attached so
+         that it can be automatically turned off when the panel goes into a
+         low power state.
+
+endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
new file mode 100644 (file)
index 0000000..af9dfa2
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
new file mode 100644 (file)
index 0000000..3e611af
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2013, NVIDIA 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, sub license,
+ * 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 NON-INFRINGEMENT. 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.
+ */
+
+#include <linux/backlight.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+struct panel_desc {
+       const struct drm_display_mode *modes;
+       unsigned int num_modes;
+
+       struct {
+               unsigned int width;
+               unsigned int height;
+       } size;
+};
+
+/* TODO: convert to gpiod_*() API once it's been merged */
+#define GPIO_ACTIVE_LOW        (1 << 0)
+
+struct panel_simple {
+       struct drm_panel base;
+       bool enabled;
+
+       const struct panel_desc *desc;
+
+       struct backlight_device *backlight;
+       struct regulator *supply;
+       struct i2c_adapter *ddc;
+
+       unsigned long enable_gpio_flags;
+       int enable_gpio;
+};
+
+static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
+{
+       return container_of(panel, struct panel_simple, base);
+}
+
+static int panel_simple_get_fixed_modes(struct panel_simple *panel)
+{
+       struct drm_connector *connector = panel->base.connector;
+       struct drm_device *drm = panel->base.drm;
+       struct drm_display_mode *mode;
+       unsigned int i, num = 0;
+
+       if (!panel->desc)
+               return 0;
+
+       for (i = 0; i < panel->desc->num_modes; i++) {
+               const struct drm_display_mode *m = &panel->desc->modes[i];
+
+               mode = drm_mode_duplicate(drm, m);
+               if (!mode) {
+                       dev_err(drm->dev, "failed to add mode %ux%u@%u\n",
+                               m->hdisplay, m->vdisplay, m->vrefresh);
+                       continue;
+               }
+
+               drm_mode_set_name(mode);
+
+               drm_mode_probed_add(connector, mode);
+               num++;
+       }
+
+       connector->display_info.width_mm = panel->desc->size.width;
+       connector->display_info.height_mm = panel->desc->size.height;
+
+       return num;
+}
+
+static int panel_simple_disable(struct drm_panel *panel)
+{
+       struct panel_simple *p = to_panel_simple(panel);
+
+       if (!p->enabled)
+               return 0;
+
+       if (p->backlight) {
+               p->backlight->props.power = FB_BLANK_POWERDOWN;
+               backlight_update_status(p->backlight);
+       }
+
+       if (gpio_is_valid(p->enable_gpio)) {
+               if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
+                       gpio_set_value(p->enable_gpio, 1);
+               else
+                       gpio_set_value(p->enable_gpio, 0);
+       }
+
+       regulator_disable(p->supply);
+       p->enabled = false;
+
+       return 0;
+}
+
+static int panel_simple_enable(struct drm_panel *panel)
+{
+       struct panel_simple *p = to_panel_simple(panel);
+       int err;
+
+       if (p->enabled)
+               return 0;
+
+       err = regulator_enable(p->supply);
+       if (err < 0) {
+               dev_err(panel->dev, "failed to enable supply: %d\n", err);
+               return err;
+       }
+
+       if (gpio_is_valid(p->enable_gpio)) {
+               if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
+                       gpio_set_value(p->enable_gpio, 0);
+               else
+                       gpio_set_value(p->enable_gpio, 1);
+       }
+
+       if (p->backlight) {
+               p->backlight->props.power = FB_BLANK_UNBLANK;
+               backlight_update_status(p->backlight);
+       }
+
+       p->enabled = true;
+
+       return 0;
+}
+
+static int panel_simple_get_modes(struct drm_panel *panel)
+{
+       struct panel_simple *p = to_panel_simple(panel);
+       int num = 0;
+
+       /* probe EDID if a DDC bus is available */
+       if (p->ddc) {
+               struct edid *edid = drm_get_edid(panel->connector, p->ddc);
+               if (edid) {
+                       num += drm_add_edid_modes(panel->connector, edid);
+                       kfree(edid);
+               }
+       }
+
+       /* add hard-coded panel modes */
+       num += panel_simple_get_fixed_modes(p);
+
+       return num;
+}
+
+static const struct drm_panel_funcs panel_simple_funcs = {
+       .disable = panel_simple_disable,
+       .enable = panel_simple_enable,
+       .get_modes = panel_simple_get_modes,
+};
+
+static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
+{
+       struct device_node *backlight, *ddc;
+       struct panel_simple *panel;
+       enum of_gpio_flags flags;
+       int err;
+
+       panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
+       if (!panel)
+               return -ENOMEM;
+
+       panel->enabled = false;
+       panel->desc = desc;
+
+       panel->supply = devm_regulator_get(dev, "power");
+       if (IS_ERR(panel->supply))
+               return PTR_ERR(panel->supply);
+
+       panel->enable_gpio = of_get_named_gpio_flags(dev->of_node,
+                                                    "enable-gpios", 0,
+                                                    &flags);
+       if (gpio_is_valid(panel->enable_gpio)) {
+               unsigned int value;
+
+               if (flags & OF_GPIO_ACTIVE_LOW)
+                       panel->enable_gpio_flags |= GPIO_ACTIVE_LOW;
+
+               err = gpio_request(panel->enable_gpio, "enable");
+               if (err < 0) {
+                       dev_err(dev, "failed to request GPIO#%u: %d\n",
+                               panel->enable_gpio, err);
+                       return err;
+               }
+
+               value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0;
+
+               err = gpio_direction_output(panel->enable_gpio, value);
+               if (err < 0) {
+                       dev_err(dev, "failed to setup GPIO%u: %d\n",
+                               panel->enable_gpio, err);
+                       goto free_gpio;
+               }
+       }
+
+       backlight = of_parse_phandle(dev->of_node, "backlight", 0);
+       if (backlight) {
+               panel->backlight = of_find_backlight_by_node(backlight);
+               of_node_put(backlight);
+
+               if (!panel->backlight) {
+                       err = -EPROBE_DEFER;
+                       goto free_gpio;
+               }
+       }
+
+       ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
+       if (ddc) {
+               panel->ddc = of_find_i2c_adapter_by_node(ddc);
+               of_node_put(ddc);
+
+               if (!panel->ddc) {
+                       err = -EPROBE_DEFER;
+                       goto free_backlight;
+               }
+       }
+
+       drm_panel_init(&panel->base);
+       panel->base.dev = dev;
+       panel->base.funcs = &panel_simple_funcs;
+
+       err = drm_panel_add(&panel->base);
+       if (err < 0)
+               goto free_ddc;
+
+       dev_set_drvdata(dev, panel);
+
+       return 0;
+
+free_ddc:
+       if (panel->ddc)
+               put_device(&panel->ddc->dev);
+free_backlight:
+       if (panel->backlight)
+               put_device(&panel->backlight->dev);
+free_gpio:
+       if (gpio_is_valid(panel->enable_gpio))
+               gpio_free(panel->enable_gpio);
+
+       return err;
+}
+
+static int panel_simple_remove(struct device *dev)
+{
+       struct panel_simple *panel = dev_get_drvdata(dev);
+
+       drm_panel_detach(&panel->base);
+       drm_panel_remove(&panel->base);
+
+       panel_simple_disable(&panel->base);
+
+       if (panel->ddc)
+               put_device(&panel->ddc->dev);
+
+       if (panel->backlight)
+               put_device(&panel->backlight->dev);
+
+       if (gpio_is_valid(panel->enable_gpio))
+               gpio_free(panel->enable_gpio);
+
+       regulator_disable(panel->supply);
+
+       return 0;
+}
+
+static const struct drm_display_mode auo_b101aw03_mode = {
+       .clock = 51450,
+       .hdisplay = 1024,
+       .hsync_start = 1024 + 156,
+       .hsync_end = 1024 + 156 + 8,
+       .htotal = 1024 + 156 + 8 + 156,
+       .vdisplay = 600,
+       .vsync_start = 600 + 16,
+       .vsync_end = 600 + 16 + 6,
+       .vtotal = 600 + 16 + 6 + 16,
+       .vrefresh = 60,
+};
+
+static const struct panel_desc auo_b101aw03 = {
+       .modes = &auo_b101aw03_mode,
+       .num_modes = 1,
+       .size = {
+               .width = 223,
+               .height = 125,
+       },
+};
+
+static const struct drm_display_mode chunghwa_claa101wb01_mode = {
+       .clock = 69300,
+       .hdisplay = 1366,
+       .hsync_start = 1366 + 48,
+       .hsync_end = 1366 + 48 + 32,
+       .htotal = 1366 + 48 + 32 + 20,
+       .vdisplay = 768,
+       .vsync_start = 768 + 16,
+       .vsync_end = 768 + 16 + 8,
+       .vtotal = 768 + 16 + 8 + 16,
+       .vrefresh = 60,
+};
+
+static const struct panel_desc chunghwa_claa101wb01 = {
+       .modes = &chunghwa_claa101wb01_mode,
+       .num_modes = 1,
+       .size = {
+               .width = 223,
+               .height = 125,
+       },
+};
+
+static const struct of_device_id platform_of_match[] = {
+       {
+               .compatible = "auo,b101aw03",
+               .data = &auo_b101aw03,
+       }, {
+               .compatible = "chunghwa,claa101wb01",
+               .data = &chunghwa_claa101wb01
+       }, {
+               .compatible = "simple-panel",
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, platform_of_match);
+
+static int panel_simple_platform_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *id;
+
+       id = of_match_node(platform_of_match, pdev->dev.of_node);
+       if (!id)
+               return -ENODEV;
+
+       return panel_simple_probe(&pdev->dev, id->data);
+}
+
+static int panel_simple_platform_remove(struct platform_device *pdev)
+{
+       return panel_simple_remove(&pdev->dev);
+}
+
+static struct platform_driver panel_simple_platform_driver = {
+       .driver = {
+               .name = "panel-simple",
+               .owner = THIS_MODULE,
+               .of_match_table = platform_of_match,
+       },
+       .probe = panel_simple_platform_probe,
+       .remove = panel_simple_platform_remove,
+};
+
+struct panel_desc_dsi {
+       struct panel_desc desc;
+
+       enum mipi_dsi_pixel_format format;
+       unsigned int lanes;
+};
+
+static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
+       .clock = 157200,
+       .hdisplay = 1920,
+       .hsync_start = 1920 + 154,
+       .hsync_end = 1920 + 154 + 16,
+       .htotal = 1920 + 154 + 16 + 32,
+       .vdisplay = 1200,
+       .vsync_start = 1200 + 17,
+       .vsync_end = 1200 + 17 + 2,
+       .vtotal = 1200 + 17 + 2 + 16,
+       .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
+       .desc = {
+               .modes = &panasonic_vvx10f004b00_mode,
+               .num_modes = 1,
+               .size = {
+                       .width = 217,
+                       .height = 136,
+               },
+       },
+       .format = MIPI_DSI_FMT_RGB888,
+       .lanes = 4,
+};
+
+static const struct of_device_id dsi_of_match[] = {
+       {
+               .compatible = "panasonic,vvx10f004b00",
+               .data = &panasonic_vvx10f004b00
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, dsi_of_match);
+
+static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
+{
+       const struct panel_desc_dsi *desc;
+       const struct of_device_id *id;
+       int err;
+
+       id = of_match_node(dsi_of_match, dsi->dev.of_node);
+       if (!id)
+               return -ENODEV;
+
+       desc = id->data;
+
+       err = panel_simple_probe(&dsi->dev, &desc->desc);
+       if (err < 0)
+               return err;
+
+       dsi->format = desc->format;
+       dsi->lanes = desc->lanes;
+
+       return mipi_dsi_attach(dsi);
+}
+
+static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
+{
+       int err;
+
+       err = mipi_dsi_detach(dsi);
+       if (err < 0)
+               dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
+
+       return panel_simple_remove(&dsi->dev);
+}
+
+static struct mipi_dsi_driver panel_simple_dsi_driver = {
+       .driver = {
+               .name = "panel-simple-dsi",
+               .owner = THIS_MODULE,
+               .of_match_table = dsi_of_match,
+       },
+       .probe = panel_simple_dsi_probe,
+       .remove = panel_simple_dsi_remove,
+};
+
+static int __init panel_simple_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&panel_simple_platform_driver);
+       if (err < 0)
+               return err;
+
+       if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
+               err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+module_init(panel_simple_init);
+
+static void __exit panel_simple_exit(void)
+{
+       if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+               mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
+
+       platform_driver_unregister(&panel_simple_platform_driver);
+}
+module_exit(panel_simple_exit);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("DRM Driver for Simple Panels");
+MODULE_LICENSE("GPL and additional rights");
index d70aafb83307d2a085afdbba6a2d4762309667ea..798bde2e5881db484fd3797013aa11a04f11c902 100644 (file)
@@ -399,10 +399,14 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
        struct qxl_bo *qobj;
        int inc = 1;
 
+       drm_modeset_lock_all(fb->dev);
+
        qobj = gem_to_qxl_bo(qxl_fb->obj);
        /* if we aren't primary surface ignore this */
-       if (!qobj->is_primary)
+       if (!qobj->is_primary) {
+               drm_modeset_unlock_all(fb->dev);
                return 0;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -417,6 +421,9 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
 
        qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color,
                          clips, num_clips, inc);
+
+       drm_modeset_unlock_all(fb->dev);
+
        return 0;
 }
 
index 7bda32f68d3b50e528c21c3bba29a3b2018d1df1..36ed40ba773f8149d88eacef4c0633614e09eb83 100644 (file)
@@ -534,7 +534,7 @@ void qxl_debugfs_takedown(struct drm_minor *minor);
 
 /* qxl_irq.c */
 int qxl_irq_init(struct qxl_device *qdev);
-irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t qxl_irq_handler(int irq, void *arg);
 
 /* qxl_fb.c */
 int qxl_fb_init(struct qxl_device *qdev);
index 7b95c75e9626ae1324dea48b310d3052f0c00d2d..0bb86e6d41b44cc4c1641e72da6e67e754994798 100644 (file)
@@ -200,7 +200,7 @@ static int qxl_process_single_command(struct qxl_device *qdev,
        for (i = 0; i < cmd->relocs_num; ++i) {
                struct drm_qxl_reloc reloc;
 
-               if (DRM_COPY_FROM_USER(&reloc,
+               if (copy_from_user(&reloc,
                                       &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i],
                                       sizeof(reloc))) {
                        ret = -EFAULT;
@@ -297,7 +297,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
                struct drm_qxl_command *commands =
                        (struct drm_qxl_command *)(uintptr_t)execbuffer->commands;
 
-               if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num],
+               if (copy_from_user(&user_cmd, &commands[cmd_num],
                                       sizeof(user_cmd)))
                        return -EFAULT;
 
index 21393dc4700a09697b7551d274b18a96ff5938ab..28f84b4fce32fab576d4bd71d324bceaf93c0682 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "qxl_drv.h"
 
-irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t qxl_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct qxl_device *qdev = (struct qxl_device *)dev->dev_private;
index e5ca498be920a86be9507c94858637aeb0b3c4c6..fd88eb4a3f79d1be5b5478ef04a3c77dde2dbb71 100644 (file)
@@ -115,7 +115,7 @@ static void qxl_gc_work(struct work_struct *work)
        qxl_garbage_collect(qdev);
 }
 
-int qxl_device_init(struct qxl_device *qdev,
+static int qxl_device_init(struct qxl_device *qdev,
                    struct drm_device *ddev,
                    struct pci_dev *pdev,
                    unsigned long flags)
index c451257f08fb51ea4b2c5346339237032705f955..59459fe4e8c57b9c367887daa945324ac7f4eb34 100644 (file)
@@ -892,10 +892,10 @@ static int r128_cce_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+               if (copy_to_user(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+               if (copy_to_user(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
                        return -EFAULT;
 
index 56eb5e3f54399ae9197e62cd5cfadcf094b7fb1b..5bf3f5ff805d941b74e05ab26f5119b8f154c057 100644 (file)
@@ -154,7 +154,7 @@ extern int r128_do_cleanup_cce(struct drm_device *dev);
 extern int r128_enable_vblank(struct drm_device *dev, int crtc);
 extern void r128_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
-extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t r128_driver_irq_handler(int irq, void *arg);
 extern void r128_driver_irq_preinstall(struct drm_device *dev);
 extern int r128_driver_irq_postinstall(struct drm_device *dev);
 extern void r128_driver_irq_uninstall(struct drm_device *dev);
@@ -514,7 +514,7 @@ do {                                                                        \
        if (R128_VERBOSE)                                               \
                DRM_INFO("COMMIT_RING() tail=0x%06x\n",                 \
                         dev_priv->ring.tail);                          \
-       DRM_MEMORYBARRIER();                                            \
+       mb();                                           \
        R128_WRITE(R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail);       \
        R128_READ(R128_PM4_BUFFER_DL_WPTR);                             \
 } while (0)
index a954c548201ece8f733a933885c3830e32de1788..b0d0fd3e437676cb306a55df7fa82cba49bcdda1 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <drm/drmP.h>
 #include <drm/r128_drm.h>
+#include "r128_drv.h"
 
 typedef struct drm_r128_init32 {
        int func;
index 2ea4f09d2691d7f69f0a084677c9821f1e0afd69..c2ae496babb7374da8381c688f15883ebc533bc0 100644 (file)
@@ -44,7 +44,7 @@ u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
        return atomic_read(&dev_priv->vbl_received);
 }
 
-irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t r128_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
index 01dd9aef9f0e9046116d570d52de96b3bf4a121b..e806dacd452f7b9cc8c93d20308db93ea0ef0da6 100644 (file)
@@ -895,31 +895,22 @@ static int r128_cce_dispatch_write_span(struct drm_device *dev,
        if (count > 4096 || count <= 0)
                return -EMSGSIZE;
 
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))
+       if (copy_from_user(&x, depth->x, sizeof(x)))
                return -EFAULT;
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))
+       if (copy_from_user(&y, depth->y, sizeof(y)))
                return -EFAULT;
 
        buffer_size = depth->n * sizeof(u32);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (buffer == NULL)
-               return -ENOMEM;
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-               kfree(buffer);
-               return -EFAULT;
-       }
+       buffer = memdup_user(depth->buffer, buffer_size);
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
 
        mask_size = depth->n * sizeof(u8);
        if (depth->mask) {
-               mask = kmalloc(mask_size, GFP_KERNEL);
-               if (mask == NULL) {
+               mask = memdup_user(depth->mask, mask_size);
+               if (IS_ERR(mask)) {
                        kfree(buffer);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-                       kfree(buffer);
-                       kfree(mask);
-                       return -EFAULT;
+                       return PTR_ERR(mask);
                }
 
                for (i = 0; i < count; i++, x++) {
@@ -999,46 +990,33 @@ static int r128_cce_dispatch_write_pixels(struct drm_device *dev,
                kfree(x);
                return -ENOMEM;
        }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+       if (copy_from_user(x, depth->x, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
-       if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
+       if (copy_from_user(y, depth->y, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
 
        buffer_size = depth->n * sizeof(u32);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (buffer == NULL) {
-               kfree(x);
-               kfree(y);
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+       buffer = memdup_user(depth->buffer, buffer_size);
+       if (IS_ERR(buffer)) {
                kfree(x);
                kfree(y);
-               kfree(buffer);
-               return -EFAULT;
+               return PTR_ERR(buffer);
        }
 
        if (depth->mask) {
                mask_size = depth->n * sizeof(u8);
-               mask = kmalloc(mask_size, GFP_KERNEL);
-               if (mask == NULL) {
-                       kfree(x);
-                       kfree(y);
-                       kfree(buffer);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+               mask = memdup_user(depth->mask, mask_size);
+               if (IS_ERR(mask)) {
                        kfree(x);
                        kfree(y);
                        kfree(buffer);
-                       kfree(mask);
-                       return -EFAULT;
+                       return PTR_ERR(mask);
                }
 
                for (i = 0; i < count; i++) {
@@ -1107,9 +1085,9 @@ static int r128_cce_dispatch_read_span(struct drm_device *dev,
        if (count > 4096 || count <= 0)
                return -EMSGSIZE;
 
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))
+       if (copy_from_user(&x, depth->x, sizeof(x)))
                return -EFAULT;
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))
+       if (copy_from_user(&y, depth->y, sizeof(y)))
                return -EFAULT;
 
        BEGIN_RING(7);
@@ -1162,12 +1140,12 @@ static int r128_cce_dispatch_read_pixels(struct drm_device *dev,
                kfree(x);
                return -ENOMEM;
        }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+       if (copy_from_user(x, depth->x, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
-       if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
+       if (copy_from_user(y, depth->y, ybuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
@@ -1524,7 +1502,7 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file
 
        DEV_INIT_TEST_WITH_RETURN(dev_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+       if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
                return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
@@ -1622,7 +1600,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index b1970596a782a437547a1fe32475253a69557f97..4cf678306c9c19b05aa51324160fdf943e15a826 100644 (file)
@@ -423,7 +423,17 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
        union atom_enable_ss args;
 
-       if (!enable) {
+       if (enable) {
+               /* Don't mess with SS if percentage is 0 or external ss.
+                * SS is already disabled previously, and disabling it
+                * again can cause display problems if the pll is already
+                * programmed.
+                */
+               if (ss->percentage == 0)
+                       return;
+               if (ss->type & ATOM_EXTERNAL_SS_MASK)
+                       return;
+       } else {
                for (i = 0; i < rdev->num_crtc; i++) {
                        if (rdev->mode_info.crtcs[i] &&
                            rdev->mode_info.crtcs[i]->enabled &&
@@ -459,8 +469,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v3.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev))
-                       args.v3.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE4(rdev)) {
                args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -480,8 +488,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v2.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev))
-                       args.v2.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE3(rdev)) {
                args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -503,8 +509,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.lvds_ss_2.ucSpreadSpectrumRange = ss->range;
                args.lvds_ss_2.ucEnable = enable;
        } else {
-               if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
-                   (ss->type & ATOM_EXTERNAL_SS_MASK)) {
+               if (enable == ATOM_DISABLE) {
                        atombios_disable_ss(rdev, pll_id);
                        return;
                }
@@ -938,11 +943,14 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
                                                        radeon_atombios_get_ppll_ss_info(rdev,
                                                                                         &radeon_crtc->ss,
                                                                                         ATOM_DP_SS_ID1);
-                               } else
+                               } else {
                                        radeon_crtc->ss_enabled =
                                                radeon_atombios_get_ppll_ss_info(rdev,
                                                                                 &radeon_crtc->ss,
                                                                                 ATOM_DP_SS_ID1);
+                               }
+                               /* disable spread spectrum on DCE3 DP */
+                               radeon_crtc->ss_enabled = false;
                        }
                        break;
                case ATOM_ENCODER_MODE_LVDS:
@@ -1039,15 +1047,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                /* calculate ss amount and step size */
                if (ASIC_IS_DCE4(rdev)) {
                        u32 step_size;
-                       u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000;
+                       u32 amount = (((fb_div * 10) + frac_fb_div) *
+                                     (u32)radeon_crtc->ss.percentage) /
+                               (100 * (u32)radeon_crtc->ss.percentage_divider);
                        radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
                        radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
                        if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
-                               step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        else
-                               step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        radeon_crtc->ss.step = step_size;
                }
@@ -1143,31 +1153,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        }
 
        if (tiling_flags & RADEON_TILING_MACRO) {
-               if (rdev->family >= CHIP_BONAIRE)
-                       tmp = rdev->config.cik.tile_config;
-               else if (rdev->family >= CHIP_TAHITI)
-                       tmp = rdev->config.si.tile_config;
-               else if (rdev->family >= CHIP_CAYMAN)
-                       tmp = rdev->config.cayman.tile_config;
-               else
-                       tmp = rdev->config.evergreen.tile_config;
+               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
-               switch ((tmp & 0xf0) >> 4) {
-               case 0: /* 4 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
-                       break;
-               case 1: /* 8 banks */
-               default:
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
-                       break;
-               case 2: /* 16 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
-                       break;
+               /* Set NUM_BANKS. */
+               if (rdev->family >= CHIP_BONAIRE) {
+                       unsigned tileb, index, num_banks, tile_split_bytes;
+
+                       /* Calculate the macrotile mode index. */
+                       tile_split_bytes = 64 << tile_split;
+                       tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                       tileb = min(tile_split_bytes, tileb);
+
+                       for (index = 0; tileb > 64; index++) {
+                               tileb >>= 1;
+                       }
+
+                       if (index >= 16) {
+                               DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                         target_fb->bits_per_pixel, tile_split);
+                               return -EINVAL;
+                       }
+
+                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
+               } else {
+                       /* SI and older. */
+                       if (rdev->family >= CHIP_TAHITI)
+                               tmp = rdev->config.si.tile_config;
+                       else if (rdev->family >= CHIP_CAYMAN)
+                               tmp = rdev->config.cayman.tile_config;
+                       else
+                               tmp = rdev->config.evergreen.tile_config;
+
+                       switch ((tmp & 0xf0) >> 4) {
+                       case 0: /* 4 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                               break;
+                       case 1: /* 8 banks */
+                       default:
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                               break;
+                       case 2: /* 16 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                               break;
+                       }
                }
 
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-
-               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
                fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
                fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
                fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
@@ -1180,19 +1212,12 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
        if (rdev->family >= CHIP_BONAIRE) {
-               u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
-               u32 num_rb = rdev->config.cik.max_backends_per_se;
-               if (num_pipe_configs > 8)
-                       num_pipe_configs = 8;
-               if (num_pipe_configs == 8)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
-               else if (num_pipe_configs == 4) {
-                       if (num_rb == 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
-                       else if (num_rb < 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
-               } else if (num_pipe_configs == 2)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+               /* Read the pipe config from the 2D TILED SCANOUT mode.
+                * It should be the same for the other modes too, but not all
+                * modes set the pipe config field. */
+               u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+               fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
        } else if ((rdev->family == CHIP_TAHITI) ||
                   (rdev->family == CHIP_PITCAIRN))
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
index fb3ae07a14692601a912b1cbea37ae7ff13bcc62..4ad7643fce5fe9bdb8a479727400ae173475bb37 100644 (file)
@@ -157,21 +157,22 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
 
        msg[0] = address;
        msg[1] = address >> 8;
-       msg[2] = AUX_NATIVE_WRITE << 4;
+       msg[2] = DP_AUX_NATIVE_WRITE << 4;
        msg[3] = (msg_bytes << 4) | (send_bytes - 1);
        memcpy(&msg[4], send, send_bytes);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, NULL, 0, delay, &ack);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return send_bytes;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
@@ -191,20 +192,21 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
 
        msg[0] = address;
        msg[1] = address >> 8;
-       msg[2] = AUX_NATIVE_READ << 4;
+       msg[2] = DP_AUX_NATIVE_READ << 4;
        msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, recv, recv_bytes, delay, &ack);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return ret;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
+                       usleep_range(400, 500);
                else if (ret == 0)
                        return -EPROTO;
                else
@@ -246,12 +248,12 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[2] = AUX_I2C_READ << 4;
+               msg[2] = DP_AUX_I2C_READ << 4;
        else
-               msg[2] = AUX_I2C_WRITE << 4;
+               msg[2] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[2] |= AUX_I2C_MOT << 4;
+               msg[2] |= DP_AUX_I2C_MOT << 4;
 
        msg[0] = address;
        msg[1] = address >> 8;
@@ -272,7 +274,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                break;
        }
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(auxch,
                                            msg, msg_bytes, reply, reply_bytes, 0, &ack);
                if (ret == -EBUSY)
@@ -282,35 +284,35 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return ret;
                }
 
-               switch (ack & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        return -EREMOTEIO;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_ch native defer\n");
-                       udelay(400);
+                       usleep_range(500, 600);
                        continue;
                default:
                        DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack);
                        return -EREMOTEIO;
                }
 
-               switch (ack & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ)
                                *read_byte = reply[0];
                        return ret;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        return -EREMOTEIO;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
-                       udelay(400);
+                       usleep_range(400, 500);
                        break;
                default:
                        DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack);
@@ -671,9 +673,11 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
        u8 tmp;
 
        /* power up the sink */
-       if (dp_info->dpcd[0] >= 0x11)
+       if (dp_info->dpcd[0] >= 0x11) {
                radeon_write_dpcd_reg(dp_info->radeon_connector,
                                      DP_SET_POWER, DP_SET_POWER_D0);
+               usleep_range(1000, 2000);
+       }
 
        /* possibly enable downspread on the sink */
        if (dp_info->dpcd[3] & 0x1)
index f685035dbe39a7d7ad48e63a9b4ca2ea717701fe..b5162c3b6111a1845834fe1b63d3e1f17642d501 100644 (file)
@@ -27,8 +27,6 @@
 #include "radeon.h"
 #include "atom.h"
 
-extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
-
 #define TARGET_HW_I2C_CLOCK 50
 
 /* these are a limitation of ProcessI2cChannelTransaction not the hw */
index 9b6950d9b3c09cc193010a50bdd521939464d539..0fbd36f3d4e9da34b65bc5f8ed302dc143b2d3c7 100644 (file)
@@ -49,6 +49,7 @@ struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
 
 //********* BARTS **************//
 static const u32 barts_cgcg_cgls_default[] =
@@ -2510,21 +2511,6 @@ int btc_dpm_enable(struct radeon_device *rdev)
        if (eg_pi->ls_clock_gating)
                btc_ls_clock_gating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        btc_init_stutter_mode(rdev);
@@ -2576,7 +2562,11 @@ void btc_dpm_disable(struct radeon_device *rdev)
 void btc_dpm_setup_asic(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       int r;
 
+       r = ni_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        rv770_get_memory_type(rdev);
        rv740_read_clock_registers(rdev);
        btc_read_arb_registers(rdev);
index 1ed47997635803d9e69bba8b3bd0202ecbc04b0e..8d49104ca6c254efa86f4287059323be28ba3f29 100644 (file)
@@ -171,8 +171,7 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
                                                     struct atom_voltage_table *voltage_table);
 extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev);
 extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev);
-extern void cik_update_cg(struct radeon_device *rdev,
-                         u32 block, bool enable);
+extern int ci_mc_load_microcode(struct radeon_device *rdev);
 
 static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev,
                                         struct atom_voltage_table_entry *voltage_table,
@@ -4503,8 +4502,8 @@ static void ci_get_memory_type(struct radeon_device *rdev)
 
 }
 
-void ci_update_current_ps(struct radeon_device *rdev,
-                         struct radeon_ps *rps)
+static void ci_update_current_ps(struct radeon_device *rdev,
+                                struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4514,8 +4513,8 @@ void ci_update_current_ps(struct radeon_device *rdev,
        pi->current_rps.ps_priv = &pi->current_ps;
 }
 
-void ci_update_requested_ps(struct radeon_device *rdev,
-                           struct radeon_ps *rps)
+static void ci_update_requested_ps(struct radeon_device *rdev,
+                                  struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4549,6 +4548,11 @@ void ci_dpm_post_set_power_state(struct radeon_device *rdev)
 
 void ci_dpm_setup_asic(struct radeon_device *rdev)
 {
+       int r;
+
+       r = ci_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        ci_read_clock_registers(rdev);
        ci_get_memory_type(rdev);
        ci_enable_acpi_power_management(rdev);
@@ -4561,13 +4565,6 @@ int ci_dpm_enable(struct radeon_device *rdev)
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        if (ci_is_smc_running(rdev))
                return -EINVAL;
        if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
@@ -4665,6 +4662,18 @@ int ci_dpm_enable(struct radeon_device *rdev)
                DRM_ERROR("ci_enable_power_containment failed\n");
                return ret;
        }
+
+       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       ci_update_current_ps(rdev, boot_ps);
+
+       return 0;
+}
+
+int ci_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
 #if 0
@@ -4685,19 +4694,8 @@ int ci_dpm_enable(struct radeon_device *rdev)
 #endif
        }
 
-       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
        ci_dpm_powergate_uvd(rdev, true);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
-       ci_update_current_ps(rdev, boot_ps);
-
        return 0;
 }
 
@@ -4706,12 +4704,6 @@ void ci_dpm_disable(struct radeon_device *rdev)
        struct ci_power_info *pi = ci_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_dpm_powergate_uvd(rdev, false);
 
        if (!ci_is_smc_running(rdev))
@@ -4742,13 +4734,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = &pi->current_rps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_find_dpm_states_clocks_in_dpm_table(rdev, new_ps);
        if (pi->pcie_performance_request)
                ci_request_link_speed_change_before_state_change(rdev, new_ps, old_ps);
@@ -4804,13 +4789,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        if (pi->pcie_performance_request)
                ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
@@ -5023,8 +5001,8 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        return 0;
 }
 
-int ci_get_vbios_boot_values(struct radeon_device *rdev,
-                            struct ci_vbios_boot_state *boot_state)
+static int ci_get_vbios_boot_values(struct radeon_device *rdev,
+                                   struct ci_vbios_boot_state *boot_state)
 {
        struct radeon_mode_info *mode_info = &rdev->mode_info;
        int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
index 9c745dd22438953106715feceb974cb620c7db02..8debc9d473625d642243b5a1923b6725eb534387 100644 (file)
@@ -28,6 +28,7 @@
 #include "cikd.h"
 #include "ppsmc.h"
 #include "radeon_ucode.h"
+#include "ci_dpm.h"
 
 static int ci_set_smc_sram_address(struct radeon_device *rdev,
                                   u32 smc_address, u32 limit)
index b43a3a3c90671911a4eaa0a7c5a260c42118df41..6ffe824624fb5a014f2bb74434b09257f00e0959 100644 (file)
@@ -1697,7 +1697,7 @@ static void cik_srbm_select(struct radeon_device *rdev,
  * Load the GDDR MC ucode into the hw (CIK).
  * Returns 0 on success, error on failure.
  */
-static int ci_mc_load_microcode(struct radeon_device *rdev)
+int ci_mc_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
        u32 running, blackout = 0;
@@ -3057,7 +3057,7 @@ static u32 cik_create_bitmask(u32 bit_width)
  * Returns the disabled RB bitmask.
  */
 static u32 cik_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -3071,7 +3071,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
@@ -3088,7 +3088,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
  */
 static void cik_setup_rb(struct radeon_device *rdev,
                         u32 se_num, u32 sh_per_se,
-                        u32 max_rb_num)
+                        u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -3098,7 +3098,7 @@ static void cik_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        cik_select_se_sh(rdev, i, j);
-                       data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        if (rdev->family == CHIP_HAWAII)
                                disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH);
                        else
@@ -3108,12 +3108,14 @@ static void cik_setup_rb(struct radeon_device *rdev,
        cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.cik.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                cik_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3484,6 +3486,51 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
        return r;
 }
 
+/**
+ * cik_hdp_flush_cp_ring_emit - emit an hdp flush on the cp
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emits an hdp flush on the cp.
+ */
+static void cik_hdp_flush_cp_ring_emit(struct radeon_device *rdev,
+                                      int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 ref_and_mask;
+
+       switch (ring->idx) {
+       case CAYMAN_RING_TYPE_CP1_INDEX:
+       case CAYMAN_RING_TYPE_CP2_INDEX:
+       default:
+               switch (ring->me) {
+               case 0:
+                       ref_and_mask = CP2 << ring->pipe;
+                       break;
+               case 1:
+                       ref_and_mask = CP6 << ring->pipe;
+                       break;
+               default:
+                       return;
+               }
+               break;
+       case RADEON_RING_TYPE_GFX_INDEX:
+               ref_and_mask = CP0;
+               break;
+       }
+
+       radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+       radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(1) | /* write, wait, write */
+                                WAIT_REG_MEM_FUNCTION(3) |  /* == */
+                                WAIT_REG_MEM_ENGINE(1)));   /* pfp */
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ >> 2);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE >> 2);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, 0x20); /* poll interval */
+}
+
 /**
  * cik_fence_gfx_ring_emit - emit a fence on the gfx ring
  *
@@ -3510,15 +3557,7 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
        /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -3548,15 +3587,7 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
        /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
 bool cik_semaphore_ring_emit(struct radeon_device *rdev,
@@ -3564,8 +3595,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev,
                             struct radeon_semaphore *semaphore,
                             bool emit_wait)
 {
-/* TODO: figure out why semaphore cause lockups */
-#if 0
        uint64_t addr = semaphore->gpu_addr;
        unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL;
 
@@ -3574,9 +3603,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel);
 
        return true;
-#else
-       return false;
-#endif
 }
 
 /**
@@ -4015,15 +4041,43 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
        return 0;
 }
 
-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring)
+u32 cik_gfx_get_rptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
 {
        u32 rptr;
 
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(CP_RB0_RPTR);
+
+       return rptr;
+}
+
+u32 cik_gfx_get_wptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(CP_RB0_WPTR);
 
+       return wptr;
+}
+
+void cik_gfx_set_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       WREG32(CP_RB0_WPTR, ring->wptr);
+       (void)RREG32(CP_RB0_WPTR);
+}
+
+u32 cik_compute_get_rptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       u32 rptr;
 
        if (rdev->wb.enabled) {
-               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
        } else {
                mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
@@ -4035,13 +4089,14 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
        return rptr;
 }
 
-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring)
+u32 cik_compute_get_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
 {
        u32 wptr;
 
        if (rdev->wb.enabled) {
-               wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]);
+               /* XXX check if swapping is necessary on BE */
+               wptr = rdev->wb.wb[ring->wptr_offs/4];
        } else {
                mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
@@ -4053,10 +4108,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
        return wptr;
 }
 
-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
-                              struct radeon_ring *ring)
+void cik_compute_set_wptr(struct radeon_device *rdev,
+                         struct radeon_ring *ring)
 {
-       rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr);
+       /* XXX check if swapping is necessary on BE */
+       rdev->wb.wb[ring->wptr_offs/4] = ring->wptr;
        WDOORBELL32(ring->doorbell_index, ring->wptr);
 }
 
@@ -4850,6 +4906,160 @@ static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        cik_print_gpu_status_regs(rdev);
 }
 
+struct kv_reset_save_regs {
+       u32 gmcon_reng_execute;
+       u32 gmcon_misc;
+       u32 gmcon_misc3;
+};
+
+static void kv_save_regs_for_reset(struct radeon_device *rdev,
+                                  struct kv_reset_save_regs *save)
+{
+       save->gmcon_reng_execute = RREG32(GMCON_RENG_EXECUTE);
+       save->gmcon_misc = RREG32(GMCON_MISC);
+       save->gmcon_misc3 = RREG32(GMCON_MISC3);
+
+       WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute & ~RENG_EXECUTE_ON_PWR_UP);
+       WREG32(GMCON_MISC, save->gmcon_misc & ~(RENG_EXECUTE_ON_REG_UPDATE |
+                                               STCTRL_STUTTER_EN));
+}
+
+static void kv_restore_regs_for_reset(struct radeon_device *rdev,
+                                     struct kv_reset_save_regs *save)
+{
+       int i;
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0x200010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0x300010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x210000);
+       WREG32(GMCON_PGFSM_CONFIG, 0xa00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x21003);
+       WREG32(GMCON_PGFSM_CONFIG, 0xb00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x2b00);
+       WREG32(GMCON_PGFSM_CONFIG, 0xc00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0xd00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x420000);
+       WREG32(GMCON_PGFSM_CONFIG, 0x100010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x120202);
+       WREG32(GMCON_PGFSM_CONFIG, 0x500010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x3e3e36);
+       WREG32(GMCON_PGFSM_CONFIG, 0x600010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x373f3e);
+       WREG32(GMCON_PGFSM_CONFIG, 0x700010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x3e1332);
+       WREG32(GMCON_PGFSM_CONFIG, 0xe00010ff);
+
+       WREG32(GMCON_MISC3, save->gmcon_misc3);
+       WREG32(GMCON_MISC, save->gmcon_misc);
+       WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute);
+}
+
+static void cik_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       struct kv_reset_save_regs kv_save = { 0 };
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* disable cg/pg */
+       cik_fini_pg(rdev);
+       cik_fini_cg(rdev);
+
+       /* Disable GFX parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
+
+       /* Disable MEC parsing/prefetching */
+       WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT);
+
+       /* sdma0 */
+       tmp = RREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET);
+       tmp |= SDMA_HALT;
+       WREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET, tmp);
+       /* sdma1 */
+       tmp = RREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET);
+       tmp |= SDMA_HALT;
+       WREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc, disable cp internal ints */
+       cik_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+
+       if (rdev->flags & RADEON_IS_IGP)
+               kv_save_regs_for_reset(rdev, &kv_save);
+
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* reset */
+       radeon_pci_config_reset(rdev);
+
+       udelay(100);
+
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+
+       /* does asic init need to be run first??? */
+       if (rdev->flags & RADEON_IS_IGP)
+               kv_restore_regs_for_reset(rdev, &kv_save);
+}
+
 /**
  * cik_asic_reset - soft reset GPU
  *
@@ -4868,10 +5078,17 @@ int cik_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        cik_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = cik_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               cik_gpu_pci_config_reset(rdev);
+
+       reset_mask = cik_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5136,20 +5353,6 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
                                WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
                                WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
 
-       /* TC cache setup ??? */
-       WREG32(TC_CFG_L1_LOAD_POLICY0, 0);
-       WREG32(TC_CFG_L1_LOAD_POLICY1, 0);
-       WREG32(TC_CFG_L1_STORE_POLICY, 0);
-
-       WREG32(TC_CFG_L2_LOAD_POLICY0, 0);
-       WREG32(TC_CFG_L2_LOAD_POLICY1, 0);
-       WREG32(TC_CFG_L2_STORE_POLICY0, 0);
-       WREG32(TC_CFG_L2_STORE_POLICY1, 0);
-       WREG32(TC_CFG_L2_ATOMIC_POLICY, 0);
-
-       WREG32(TC_CFG_L1_VOLATILE, 0);
-       WREG32(TC_CFG_L2_VOLATILE, 0);
-
        if (rdev->family == CHIP_KAVERI) {
                u32 tmp = RREG32(CHUB_CONTROL);
                tmp &= ~BYPASS_VM;
@@ -5365,16 +5568,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VMID(0));
 
        /* HDP flush */
-       /* We should be using the WAIT_REG_MEM packet here like in
-        * cik_fence_ring_emit(), but it causes the CP to hang in this
-        * context...
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, ridx);
 
        /* bits 0-15 are the VM contexts0-15 */
        radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -7501,26 +7695,7 @@ static int cik_startup(struct radeon_device *rdev)
 
        cik_mc_program(rdev);
 
-       if (rdev->flags & RADEON_IS_IGP) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
-                       r = cik_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
-                   !rdev->mc_fw) {
-                       r = cik_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-
+       if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) {
                r = ci_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
@@ -7625,7 +7800,6 @@ static int cik_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7634,7 +7808,6 @@ static int cik_startup(struct radeon_device *rdev)
        /* type-2 packets are deprecated on MEC, use type-3 instead */
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
-                            CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7646,7 +7819,6 @@ static int cik_startup(struct radeon_device *rdev)
        /* type-2 packets are deprecated on MEC, use type-3 instead */
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
-                            CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7658,16 +7830,12 @@ static int cik_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET,
-                            SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET,
                             SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET,
-                            SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET,
                             SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
        if (r)
                return r;
@@ -7683,7 +7851,6 @@ static int cik_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -7729,6 +7896,8 @@ int cik_resume(struct radeon_device *rdev)
        /* init golden registers */
        cik_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = cik_startup(rdev);
        if (r) {
@@ -7752,6 +7921,7 @@ int cik_resume(struct radeon_device *rdev)
  */
 int cik_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        dce6_audio_fini(rdev);
        radeon_vm_manager_fini(rdev);
        cik_cp_enable(rdev, false);
@@ -7833,6 +8003,30 @@ int cik_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (rdev->flags & RADEON_IS_IGP) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
+                       r = cik_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
+                   !rdev->mc_fw) {
+                       r = cik_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
@@ -7913,6 +8107,7 @@ int cik_init(struct radeon_device *rdev)
  */
 void cik_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        cik_cp_fini(rdev);
        cik_sdma_fini(rdev);
        cik_fini_pg(rdev);
index d08b83c6267b4cde4ff5ce0ad71754c1e5e446a1..9abea87a92133b7073ba64500d4083f711b82a63 100644 (file)
@@ -51,6 +51,75 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev);
  * buffers.
  */
 
+/**
+ * cik_sdma_get_rptr - get the current read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current rptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_rptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 rptr, reg;
+
+       if (rdev->wb.enabled) {
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       } else {
+               if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+                       reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET;
+               else
+                       reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET;
+
+               rptr = RREG32(reg);
+       }
+
+       return (rptr & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_get_wptr - get the current write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current wptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       return (RREG32(reg) & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_set_wptr - commit the write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Write the wptr back to the hardware (CIK+).
+ */
+void cik_sdma_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+}
+
 /**
  * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine
  *
@@ -87,6 +156,35 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev,
 
 }
 
+/**
+ * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emit an hdp flush packet on the requested DMA ring.
+ */
+static void cik_sdma_hdp_flush_ring_emit(struct radeon_device *rdev,
+                                        int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) |
+                         SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
+       u32 ref_and_mask;
+
+       if (ridx == R600_RING_TYPE_DMA_INDEX)
+               ref_and_mask = SDMA0;
+       else
+               ref_and_mask = SDMA1;
+
+       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits));
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ);
+       radeon_ring_write(ring, ref_and_mask); /* reference */
+       radeon_ring_write(ring, ref_and_mask); /* mask */
+       radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */
+}
+
 /**
  * cik_sdma_fence_ring_emit - emit a fence on the DMA ring
  *
@@ -111,12 +209,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
        /* generate an interrupt */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0));
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -747,12 +840,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm
        radeon_ring_write(ring, VMID(0));
 
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, ridx);
 
        /* flush TLB */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
index 5964af5e5b2d8823c4626cad40bfd2abf385fb40..98bae9d7b74d1b3fe82ab41bc5f631d7e4acfc86 100644 (file)
 
 #define ATC_MISC_CG                                    0x3350
 
+#define GMCON_RENG_EXECUTE                             0x3508
+#define        RENG_EXECUTE_ON_PWR_UP                  (1 << 0)
+#define GMCON_MISC                                     0x350c
+#define        RENG_EXECUTE_ON_REG_UPDATE              (1 << 11)
+#define        STCTRL_STUTTER_EN                       (1 << 16)
+
+#define GMCON_PGFSM_CONFIG                             0x3538
+#define GMCON_PGFSM_WRITE                              0x353c
+#define GMCON_PGFSM_READ                               0x3540
+#define GMCON_MISC3                                    0x3544
+
 #define MC_SEQ_CNTL_3                                     0x3600
 #       define CAC_EN                                     (1 << 31)
 #define MC_SEQ_G5PDX_CTRL                                 0x3604
index 920e1e4a52c52c1edefd84e727a0fc13c2dde39b..cf783fc0ef21920f7d0e50156bddbd9c24299150 100644 (file)
@@ -1905,21 +1905,6 @@ int cypress_dpm_enable(struct radeon_device *rdev)
        if (pi->mg_clock_gating)
                cypress_mg_clock_gating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        return 0;
index 9702e55e924e8327740869eb34ed455dcd908db3..4116d0279596605d0447d9687c6d9f5698ea27de 100644 (file)
@@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev);
 extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
 extern u32 cik_get_csb_size(struct radeon_device *rdev);
 extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 static const u32 evergreen_golden_registers[] =
 {
@@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        evergreen_print_gpu_status_regs(rdev);
 }
 
+void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+       udelay(50);
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc */
+       r600_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* set mclk/sclk to bypass */
+       rv770_set_clk_bypass_mode(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int evergreen_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        evergreen_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = evergreen_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5109,27 +5159,12 @@ static int evergreen_startup(struct radeon_device *rdev)
 
        evergreen_mc_program(rdev);
 
-       if (ASIC_IS_DCE5(rdev)) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
+       if (ASIC_IS_DCE5(rdev) && !rdev->pm.dpm_enabled) {
                r = ni_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
                        return r;
                }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-                       r = r600_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
        }
 
        if (rdev->flags & RADEON_IS_AGP) {
@@ -5199,14 +5234,12 @@ static int evergreen_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0));
        if (r)
                return r;
@@ -5224,7 +5257,6 @@ static int evergreen_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -5267,6 +5299,8 @@ int evergreen_resume(struct radeon_device *rdev)
        /* init golden registers */
        evergreen_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = evergreen_startup(rdev);
        if (r) {
@@ -5281,6 +5315,7 @@ int evergreen_resume(struct radeon_device *rdev)
 
 int evergreen_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_suspend(rdev);
@@ -5357,6 +5392,27 @@ int evergreen_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (ASIC_IS_DCE5(rdev)) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+                       r = r600_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -5409,6 +5465,7 @@ int evergreen_init(struct radeon_device *rdev)
 
 void evergreen_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r700_cp_fini(rdev);
        r600_dma_fini(rdev);
index eb8ac315f92faa3cbd58468b6bf9ba360a8c0986..c7cac07f139b2106041208179d124d8ff5ba20b0 100644 (file)
@@ -967,7 +967,10 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
        if (track->cb_dirty) {
                tmp = track->cb_target_mask;
                for (i = 0; i < 8; i++) {
-                       if ((tmp >> (i * 4)) & 0xF) {
+                       u32 format = G_028C70_FORMAT(track->cb_color_info[i]);
+
+                       if (format != V_028C70_COLOR_INVALID &&
+                           (tmp >> (i * 4)) & 0xF) {
                                /* at least one component is enabled */
                                if (track->cb_color_bo[i] == NULL) {
                                        dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
index 8a4e641f0e3c3712cfbcb543372fde5707e6cce5..a0f63ff5a5e97cb47100abce14bc249083c61479 100644 (file)
@@ -33,6 +33,7 @@
 #define EVERGREEN_PIF_PHY0_DATA                         0xc
 #define EVERGREEN_PIF_PHY1_INDEX                        0x10
 #define EVERGREEN_PIF_PHY1_DATA                         0x14
+#define EVERGREEN_MM_INDEX_HI                           0x18
 
 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS               0x310
 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH          0x324
index 17f990798992dae5d6335726a8f3b4c259659f89..f9c7963b3ee6b38730cdf6d422c2b612f0d1c904 100644 (file)
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
+#define        CG_SPLL_STATUS                                  0x60c
+#define                SPLL_CHG_STATUS                         (1 << 1)
 
 #define MPLL_CNTL_MODE                                  0x61c
+#       define MPLL_MCLK_SEL                            (1 << 11)
 #       define SS_SSEN                                  (1 << 24)
 #       define SS_DSMODE_EN                             (1 << 25)
 
index b41905573cd2a431862b3684f4d43ad445ecd15d..b6e01d5d2cced24edc67e773c84cba33a6d5fef8 100644 (file)
@@ -1126,11 +1126,6 @@ int kv_dpm_enable(struct radeon_device *rdev)
        struct kv_power_info *pi = kv_get_pi(rdev);
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ret = kv_process_firmware_header(rdev);
        if (ret) {
                DRM_ERROR("kv_process_firmware_header failed\n");
@@ -1215,6 +1210,21 @@ int kv_dpm_enable(struct radeon_device *rdev)
 
        kv_reset_acp_boot_level(rdev);
 
+       ret = kv_smc_bapm_enable(rdev, false);
+       if (ret) {
+               DRM_ERROR("kv_smc_bapm_enable failed\n");
+               return ret;
+       }
+
+       kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return ret;
+}
+
+int kv_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1226,35 +1236,17 @@ int kv_dpm_enable(struct radeon_device *rdev)
                radeon_irq_set(rdev);
        }
 
-       ret = kv_smc_bapm_enable(rdev, false);
-       if (ret) {
-               DRM_ERROR("kv_smc_bapm_enable failed\n");
-               return ret;
-       }
-
        /* powerdown unused blocks for now */
        kv_dpm_powergate_acp(rdev, true);
        kv_dpm_powergate_samu(rdev, true);
        kv_dpm_powergate_vce(rdev, true);
        kv_dpm_powergate_uvd(rdev, true);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), true);
-
-       kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
-
        return ret;
 }
 
 void kv_dpm_disable(struct radeon_device *rdev)
 {
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        kv_smc_bapm_enable(rdev, false);
 
        /* powerup blocks */
@@ -1779,11 +1771,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
        /*struct radeon_ps *old_ps = &pi->current_rps;*/
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        if (pi->bapm_enable) {
                ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power);
                if (ret) {
@@ -1849,11 +1836,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                }
        }
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
index f59a9e9fccf8a803ce6097e4e185d8824ad5f714..647b1d0fa62c3fc5bf0e7c424ffc6cb606aff9f2 100644 (file)
@@ -174,6 +174,7 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 extern void evergreen_program_aspm(struct radeon_device *rdev);
 extern void sumo_rlc_fini(struct radeon_device *rdev);
 extern int sumo_rlc_init(struct radeon_device *rdev);
+extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev);
 
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
@@ -1330,13 +1331,12 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
 {
        struct radeon_ring *ring = &rdev->ring[fence->ring];
        u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
+       u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
 
        /* flush read cache over gart for this vmid */
-       radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(ring, 0);
        radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-       radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+       radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
        radeon_ring_write(ring, 0xFFFFFFFF);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 10); /* poll interval */
@@ -1352,6 +1352,8 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
        struct radeon_ring *ring = &rdev->ring[ib->ring];
+       u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
 
        /* set to DX10/11 mode */
        radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
@@ -1376,14 +1378,11 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
                          (ib->vm ? (ib->vm->id << 24) : 0));
 
        /* flush read cache over gart for this vmid */
-       radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(ring, ib->vm ? ib->vm->id : 0);
        radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-       radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+       radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
        radeon_ring_write(ring, 0xFFFFFFFF);
        radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 10); /* poll interval */
+       radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* poll interval */
 }
 
 static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
@@ -1398,6 +1397,55 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
        }
 }
 
+u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else {
+               if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
+                       rptr = RREG32(CP_RB0_RPTR);
+               else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
+                       rptr = RREG32(CP_RB1_RPTR);
+               else
+                       rptr = RREG32(CP_RB2_RPTR);
+       }
+
+       return rptr;
+}
+
+u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
+               wptr = RREG32(CP_RB0_WPTR);
+       else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
+               wptr = RREG32(CP_RB1_WPTR);
+       else
+               wptr = RREG32(CP_RB2_WPTR);
+
+       return wptr;
+}
+
+void cayman_gfx_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
+               WREG32(CP_RB0_WPTR, ring->wptr);
+               (void)RREG32(CP_RB0_WPTR);
+       } else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) {
+               WREG32(CP_RB1_WPTR, ring->wptr);
+               (void)RREG32(CP_RB1_WPTR);
+       } else {
+               WREG32(CP_RB2_WPTR, ring->wptr);
+               (void)RREG32(CP_RB2_WPTR);
+       }
+}
+
 static int cayman_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -1526,6 +1574,16 @@ static int cayman_cp_resume(struct radeon_device *rdev)
                CP_RB1_BASE,
                CP_RB2_BASE
        };
+       static const unsigned cp_rb_rptr[] = {
+               CP_RB0_RPTR,
+               CP_RB1_RPTR,
+               CP_RB2_RPTR
+       };
+       static const unsigned cp_rb_wptr[] = {
+               CP_RB0_WPTR,
+               CP_RB1_WPTR,
+               CP_RB2_WPTR
+       };
        struct radeon_ring *ring;
        int i, r;
 
@@ -1584,8 +1642,8 @@ static int cayman_cp_resume(struct radeon_device *rdev)
                WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
 
                ring->rptr = ring->wptr = 0;
-               WREG32(ring->rptr_reg, ring->rptr);
-               WREG32(ring->wptr_reg, ring->wptr);
+               WREG32(cp_rb_rptr[i], ring->rptr);
+               WREG32(cp_rb_wptr[i], ring->wptr);
 
                mdelay(1);
                WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
@@ -1831,8 +1889,10 @@ int cayman_asic_reset(struct radeon_device *rdev)
 
        reset_mask = cayman_gpu_check_soft_reset(rdev);
 
-       if (!reset_mask)
-               r600_set_bios_scratch_engine_hung(rdev, false);
+       if (reset_mask)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
 
        return 0;
 }
@@ -1878,23 +1938,7 @@ static int cayman_startup(struct radeon_device *rdev)
 
        evergreen_mc_program(rdev);
 
-       if (rdev->flags & RADEON_IS_IGP) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-
+       if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) {
                r = ni_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
@@ -1981,23 +2025,18 @@ static int cayman_startup(struct radeon_device *rdev)
        evergreen_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -2016,7 +2055,6 @@ static int cayman_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -2063,6 +2101,8 @@ int cayman_resume(struct radeon_device *rdev)
        /* init golden registers */
        ni_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = cayman_startup(rdev);
        if (r) {
@@ -2075,6 +2115,7 @@ int cayman_resume(struct radeon_device *rdev)
 
 int cayman_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        if (ASIC_IS_DCE6(rdev))
                dce6_audio_fini(rdev);
        else
@@ -2145,6 +2186,27 @@ int cayman_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (rdev->flags & RADEON_IS_IGP) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
 
@@ -2204,6 +2266,7 @@ int cayman_init(struct radeon_device *rdev)
 
 void cayman_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        cayman_cp_fini(rdev);
        cayman_dma_fini(rdev);
        r600_irq_fini(rdev);
index bdeb65ed365831db35a94a0ffae523f3c8e419dd..51424ab79432788d3006ba6268c6a4229c4dd43f 100644 (file)
@@ -42,6 +42,75 @@ u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev);
  * Cayman and newer support two asynchronous DMA engines.
  */
 
+/**
+ * cayman_dma_get_rptr - get the current read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current rptr from the hardware (cayman+).
+ */
+uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring)
+{
+       u32 rptr, reg;
+
+       if (rdev->wb.enabled) {
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       } else {
+               if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+                       reg = DMA_RB_RPTR + DMA0_REGISTER_OFFSET;
+               else
+                       reg = DMA_RB_RPTR + DMA1_REGISTER_OFFSET;
+
+               rptr = RREG32(reg);
+       }
+
+       return (rptr & 0x3fffc) >> 2;
+}
+
+/**
+ * cayman_dma_get_wptr - get the current write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current wptr from the hardware (cayman+).
+ */
+uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
+       else
+               reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
+
+       return (RREG32(reg) & 0x3fffc) >> 2;
+}
+
+/**
+ * cayman_dma_set_wptr - commit the write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Write the wptr back to the hardware (cayman+).
+ */
+void cayman_dma_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
+       else
+               reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
+
+       WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+}
+
 /**
  * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine
  *
index 49c4d48f54d616b49b7af261d8fa2d71586ab8fd..c351226ecb31b0d9fa2d94a32ac23d504d61952b 100644 (file)
@@ -720,6 +720,8 @@ static const u32 cayman_sysls_enable[] =
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
+
 struct ni_power_info *ni_get_pi(struct radeon_device *rdev)
 {
         struct ni_power_info *pi = rdev->pm.dpm.priv;
@@ -3565,7 +3567,11 @@ void ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
 void ni_dpm_setup_asic(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       int r;
 
+       r = ni_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        ni_read_clock_registers(rdev);
        btc_read_arb_registers(rdev);
        rv770_get_memory_type(rdev);
@@ -3710,21 +3716,6 @@ int ni_dpm_enable(struct radeon_device *rdev)
        if (eg_pi->ls_clock_gating)
                ni_ls_clockgating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, 0xff * 1000);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        ni_update_current_ps(rdev, boot_ps);
index 22421bc80c0d0d0d33c8b87ef9922c3cf982fc15..d996033c243ee14f4509220a707edf50f9dbe489 100644 (file)
 #              define PACKET3_DB_ACTION_ENA        (1 << 26)
 #              define PACKET3_SH_ACTION_ENA        (1 << 27)
 #              define PACKET3_SX_ACTION_ENA        (1 << 28)
+#              define PACKET3_ENGINE_ME            (1 << 31)
 #define        PACKET3_ME_INITIALIZE                           0x44
 #define                PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
 #define        PACKET3_COND_WRITE                              0x45
index da43ab3288332faf705a3e673663c5fe7fbc30b3..2d532996c69795cc129cb4ac6c60a4dfc4b70808 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _PPTABLE_H
 #define _PPTABLE_H
 
-#pragma pack(push, 1)
+#pragma pack(1)
 
 typedef struct _ATOM_PPLIB_THERMALCONTROLLER
 
@@ -677,6 +677,6 @@ typedef struct _ATOM_PPLIB_PPM_Table
       ULONG  ulTjmax;
 } ATOM_PPLIB_PPM_Table;
 
-#pragma pack(pop)
+#pragma pack()
 
 #endif
index 10abc4d5a6cc396a85bb32d4b7d094b748757f99..ef024ce3f7ccfd39b1be47be9840a401b588b1dc 100644 (file)
@@ -1050,6 +1050,36 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
        return err;
 }
 
+u32 r100_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+       else
+               rptr = RREG32(RADEON_CP_RB_RPTR);
+
+       return rptr;
+}
+
+u32 r100_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(RADEON_CP_RB_WPTR);
+
+       return wptr;
+}
+
+void r100_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       WREG32(RADEON_CP_RB_WPTR, ring->wptr);
+       (void)RREG32(RADEON_CP_RB_WPTR);
+}
+
 static void r100_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -1102,7 +1132,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        ring_size = (1 << (rb_bufsz + 1)) * 4;
        r100_cp_load_microcode(rdev);
        r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r) {
                return r;
@@ -3913,6 +3942,8 @@ int r100_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r100_startup(rdev);
        if (r) {
@@ -3923,6 +3954,7 @@ int r100_resume(struct radeon_device *rdev)
 
 int r100_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -3933,6 +3965,7 @@ int r100_suspend(struct radeon_device *rdev)
 
 void r100_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -4039,6 +4072,9 @@ int r100_init(struct radeon_device *rdev)
        }
        r100_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r100_startup(rdev);
        if (r) {
index d8dd269b9159fcc0dfbed98cf8c3c2037742e671..7c63ef840e86abaf04f216201b32ee2f40323b9b 100644 (file)
@@ -1430,6 +1430,8 @@ int r300_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r300_startup(rdev);
        if (r) {
@@ -1440,6 +1442,7 @@ int r300_resume(struct radeon_device *rdev)
 
 int r300_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -1452,6 +1455,7 @@ int r300_suspend(struct radeon_device *rdev)
 
 void r300_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -1538,6 +1542,9 @@ int r300_init(struct radeon_device *rdev)
        }
        r300_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r300_startup(rdev);
        if (r) {
index 60170ea5e3a228c0483c18f0fd1652b30ec7760b..84b1d5367a11f6950026337f76117bbb8edda0bb 100644 (file)
@@ -75,7 +75,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
 
                for (i = 0; i < nr; ++i) {
-                       if (DRM_COPY_FROM_USER
+                       if (copy_from_user
                            (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
                                DRM_ERROR("copy cliprect faulted\n");
                                return -EFAULT;
@@ -928,12 +928,12 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
                buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
                *buf_idx *= 2; /* 8 bytes per buf */
 
-               if (DRM_COPY_TO_USER(ref_age_base + *buf_idx,
+               if (copy_to_user(ref_age_base + *buf_idx,
                                &dev_priv->scratch_ages[header.scratch.reg],
                                sizeof(u32)))
                        return -EINVAL;
 
-               if (DRM_COPY_FROM_USER(&h_pending,
+               if (copy_from_user(&h_pending,
                                ref_age_base + *buf_idx + 1,
                                sizeof(u32)))
                        return -EINVAL;
@@ -943,7 +943,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
 
                h_pending--;
 
-               if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1,
+               if (copy_to_user(ref_age_base + *buf_idx + 1,
                                        &h_pending,
                                        sizeof(u32)))
                        return -EINVAL;
index 6edf2b3a52b4d7e4ba82cc063048ffb73733a984..3768aab2710b3943261312c4fcc5184b4f18a6fb 100644 (file)
@@ -325,6 +325,8 @@ int r420_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
@@ -335,6 +337,7 @@ int r420_resume(struct radeon_device *rdev)
 
 int r420_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r420_cp_errata_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -348,6 +351,7 @@ int r420_suspend(struct radeon_device *rdev)
 
 void r420_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -444,6 +448,9 @@ int r420_init(struct radeon_device *rdev)
        }
        r420_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
index e1aece73b370c1ec9d6d9f86273caad0cbb14d36..e209eb75024f9dc1c441518cbe8f8d70a41844f5 100644 (file)
@@ -240,6 +240,8 @@ int r520_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r520_startup(rdev);
        if (r) {
@@ -312,6 +314,9 @@ int r520_init(struct radeon_device *rdev)
                return r;
        rv515_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r520_startup(rdev);
        if (r) {
index 9ad06732a78bc6d079914a6ce15e92b7e273b265..3dce370adc1b78aedc2b316f81ef8375c8ed7309 100644 (file)
@@ -105,6 +105,7 @@ void r600_fini(struct radeon_device *rdev);
 void r600_irq_disable(struct radeon_device *rdev);
 static void r600_pcie_gen2_enable(struct radeon_device *rdev);
 extern int evergreen_rlc_resume(struct radeon_device *rdev);
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 /**
  * r600_get_xclk - get the xclk
@@ -1644,6 +1645,67 @@ static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        r600_print_gpu_status_regs(rdev);
 }
 
+static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct rv515_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* Disable CP parsing/prefetching */
+       if (rdev->family >= CHIP_RV770)
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
+       else
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+
+       /* disable the RLC */
+       WREG32(RLC_CNTL, 0);
+
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       mdelay(50);
+
+       /* set mclk/sclk to bypass */
+       if (rdev->family >= CHIP_RV770)
+               rv770_set_clk_bypass_mode(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* disable mem access */
+       rv515_mc_stop(rdev, &save);
+       if (r600_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       /* BIF reset workaround.  Not sure if this is needed on 6xx */
+       tmp = RREG32(BUS_CNTL);
+       tmp |= VGA_COHE_SPEC_TIMER_DIS;
+       WREG32(BUS_CNTL, tmp);
+
+       tmp = RREG32(BIF_SCRATCH0);
+
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       mdelay(1);
+
+       /* BIF reset workaround.  Not sure if this is needed on 6xx */
+       tmp = SOFT_RESET_BIF;
+       WREG32(SRBM_SOFT_RESET, tmp);
+       mdelay(1);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int r600_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -1653,10 +1715,17 @@ int r600_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        r600_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = r600_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               r600_gpu_pci_config_reset(rdev);
+
+       reset_mask = r600_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -2382,6 +2451,36 @@ out:
        return err;
 }
 
+u32 r600_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(R600_CP_RB_RPTR);
+
+       return rptr;
+}
+
+u32 r600_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(R600_CP_RB_WPTR);
+
+       return wptr;
+}
+
+void r600_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       WREG32(R600_CP_RB_WPTR, ring->wptr);
+       (void)RREG32(R600_CP_RB_WPTR);
+}
+
 static int r600_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -2607,14 +2706,17 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence)
 {
        struct radeon_ring *ring = &rdev->ring[fence->ring];
+       u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
+
+       if (rdev->family >= CHIP_RV770)
+               cp_coher_cntl |= PACKET3_FULL_CACHE_ENA;
 
        if (rdev->wb.use_event) {
                u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
                /* flush read cache over gart */
                radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-               radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
-                                       PACKET3_VC_ACTION_ENA |
-                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(ring, cp_coher_cntl);
                radeon_ring_write(ring, 0xFFFFFFFF);
                radeon_ring_write(ring, 0);
                radeon_ring_write(ring, 10); /* poll interval */
@@ -2628,9 +2730,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        } else {
                /* flush read cache over gart */
                radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-               radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
-                                       PACKET3_VC_ACTION_ENA |
-                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(ring, cp_coher_cntl);
                radeon_ring_write(ring, 0xFFFFFFFF);
                radeon_ring_write(ring, 0);
                radeon_ring_write(ring, 10); /* poll interval */
@@ -2775,14 +2875,6 @@ static int r600_startup(struct radeon_device *rdev)
 
        r600_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-               r = r600_init_microcode(rdev);
-               if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
-                       return r;
-               }
-       }
-
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
        } else {
@@ -2826,14 +2918,12 @@ static int r600_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -2889,6 +2979,8 @@ int r600_resume(struct radeon_device *rdev)
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r600_startup(rdev);
        if (r) {
@@ -2902,6 +2994,7 @@ int r600_resume(struct radeon_device *rdev)
 
 int r600_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r600_cp_stop(rdev);
        r600_dma_stop(rdev);
@@ -2970,6 +3063,17 @@ int r600_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+               r = r600_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -3002,6 +3106,7 @@ int r600_init(struct radeon_device *rdev)
 
 void r600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r600_cp_fini(rdev);
        r600_dma_fini(rdev);
index d8eb48bff0ed204e9c52538342a11dcd1bd5b8ff..8c9b7e26533c6c81635a9dafa20e7cecb164b167 100644 (file)
@@ -2515,7 +2515,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
                buf = radeon_freelist_get(dev);
                if (!buf) {
                        DRM_DEBUG("EAGAIN\n");
-                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+                       if (copy_to_user(tex->image, image, sizeof(*image)))
                                return -EFAULT;
                        return -EAGAIN;
                }
@@ -2528,7 +2528,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
                buffer =
                    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
 
-               if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
+               if (copy_from_user(buffer, data, pass_size)) {
                        DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
                        return -EFAULT;
                }
index 5dceea6f71ae450cf925b0d7e119783c801d6ebd..7b399dc5fd5492d1e53dcaa5b5be728164dc85b2 100644 (file)
@@ -749,7 +749,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                }
 
                for (i = 0; i < 8; i++) {
-                       if ((tmp >> (i * 4)) & 0xF) {
+                       u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
+
+                       if (format != V_0280A0_COLOR_INVALID &&
+                           (tmp >> (i * 4)) & 0xF) {
                                /* at least one component is enabled */
                                if (track->cb_color_bo[i] == NULL) {
                                        dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
@@ -2386,7 +2389,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
        ib_chunk = &parser.chunks[parser.chunk_ib_idx];
        parser.ib.length_dw = ib_chunk->length_dw;
        *l = parser.ib.length_dw;
-       if (DRM_COPY_FROM_USER(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
+       if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
                r = -EFAULT;
                r600_cs_parser_fini(&parser, r);
                return r;
index 7844d15c139fcb97247880d596ab4354d4bea8d5..3452c8410bd76fa49a12cd5536f64793135ad9e7 100644 (file)
@@ -51,7 +51,14 @@ u32 r600_gpu_check_soft_reset(struct radeon_device *rdev);
 uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
                           struct radeon_ring *ring)
 {
-       return (radeon_ring_generic_get_rptr(rdev, ring) & 0x3fffc) >> 2;
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(DMA_RB_RPTR);
+
+       return (rptr & 0x3fffc) >> 2;
 }
 
 /**
@@ -65,7 +72,7 @@ uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
 uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
                           struct radeon_ring *ring)
 {
-       return (RREG32(ring->wptr_reg) & 0x3fffc) >> 2;
+       return (RREG32(DMA_RB_WPTR) & 0x3fffc) >> 2;
 }
 
 /**
@@ -79,7 +86,7 @@ uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
 void r600_dma_set_wptr(struct radeon_device *rdev,
                       struct radeon_ring *ring)
 {
-       WREG32(ring->wptr_reg, (ring->wptr << 2) & 0x3fffc);
+       WREG32(DMA_RB_WPTR, (ring->wptr << 2) & 0x3fffc);
 }
 
 /**
index 5513d8f06252e13e11e27e9d21d5aecae775b5a8..e4cc9b314ce974fe5caacf91a000cb9a76a584d6 100644 (file)
@@ -729,8 +729,8 @@ bool r600_is_uvd_state(u32 class, u32 class2)
        return false;
 }
 
-int r600_set_thermal_temperature_range(struct radeon_device *rdev,
-                                      int min_temp, int max_temp)
+static int r600_set_thermal_temperature_range(struct radeon_device *rdev,
+                                             int min_temp, int max_temp)
 {
        int low_temp = 0 * 1000;
        int high_temp = 255 * 1000;
@@ -777,6 +777,22 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor)
        }
 }
 
+int r600_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       if (rdev->irq.installed &&
+           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
+               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
+               if (ret)
+                       return ret;
+               rdev->irq.dpm_thermal = true;
+               radeon_irq_set(rdev);
+       }
+
+       return 0;
+}
+
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
        struct _ATOM_POWERPLAY_INFO_V2 info_2;
index 1000bf9719f2449af5d15a153b147f19c6af25e4..07eab2b04e81b5db420a6ee96152c8b8e94e4092 100644 (file)
@@ -213,8 +213,6 @@ void r600_wait_for_power_level(struct radeon_device *rdev,
 void r600_start_dpm(struct radeon_device *rdev);
 void r600_stop_dpm(struct radeon_device *rdev);
 
-int r600_set_thermal_temperature_range(struct radeon_device *rdev,
-                                      int min_temp, int max_temp);
 bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
 
 int r600_parse_extended_power_table(struct radeon_device *rdev);
index b7d3ecba43e34d3b559ee072800101532150c631..3016fc14f502c49a61c2343c3b2ca877d2590109 100644 (file)
@@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
                 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
index ebe38724a9765765041eaa245fc7994c4fec01fb..37455f65107f7fc8c0d2ff8a6a14d5abe43c13af 100644 (file)
 #define RLC_UCODE_DATA                                    0x3f30
 
 #define SRBM_SOFT_RESET                                   0xe60
+#       define SOFT_RESET_BIF                             (1 << 1)
 #       define SOFT_RESET_DMA                             (1 << 12)
 #       define SOFT_RESET_RLC                             (1 << 13)
 #       define SOFT_RESET_UVD                             (1 << 18)
 #       define RV770_SOFT_RESET_DMA                       (1 << 20)
 
+#define BIF_SCRATCH0                                      0x5438
+
+#define BUS_CNTL                                          0x5420
+#       define BIOS_ROM_DIS                               (1 << 1)
+#       define VGA_COHE_SPEC_TIMER_DIS                    (1 << 9)
+
 #define CP_INT_CNTL                                       0xc124
 #       define CNTX_BUSY_INT_ENABLE                       (1 << 19)
 #       define CNTX_EMPTY_INT_ENABLE                      (1 << 20)
 #              define PACKET3_CP_DMA_CMD_DAIC      (1 << 29)
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20) /* r7xx+ only */
 #              define PACKET3_TC_ACTION_ENA        (1 << 23)
 #              define PACKET3_VC_ACTION_ENA        (1 << 24)
 #              define PACKET3_CB_ACTION_ENA        (1 << 25)
index b1f990d0eaa101d1bce56fabfc4b286ff01de7e9..c5519ca4bbc4ac2b4eb84b93822ab3fe2f6b4643 100644 (file)
@@ -99,6 +99,7 @@ extern int radeon_fastfb;
 extern int radeon_dpm;
 extern int radeon_aspm;
 extern int radeon_runtime_pm;
+extern int radeon_hard_reset;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -139,6 +140,9 @@ extern int radeon_runtime_pm;
 #define RADEON_VA_RESERVED_SIZE                        (8 << 20)
 #define RADEON_IB_VM_MAX_SIZE                  (64 << 10)
 
+/* hard reset data */
+#define RADEON_ASIC_RESET_DATA                  0x39d5e86b
+
 /* reset flags */
 #define RADEON_RESET_GFX                       (1 << 0)
 #define RADEON_RESET_COMPUTE                   (1 << 1)
@@ -252,6 +256,7 @@ struct radeon_clock {
  * Power management
  */
 int radeon_pm_init(struct radeon_device *rdev);
+int radeon_pm_late_init(struct radeon_device *rdev);
 void radeon_pm_fini(struct radeon_device *rdev);
 void radeon_pm_compute_clocks(struct radeon_device *rdev);
 void radeon_pm_suspend(struct radeon_device *rdev);
@@ -413,6 +418,11 @@ struct radeon_mman {
        struct ttm_bo_device            bdev;
        bool                            mem_global_referenced;
        bool                            initialized;
+
+#if defined(CONFIG_DEBUG_FS)
+       struct dentry                   *vram;
+       struct dentry                   *gtt;
+#endif
 };
 
 /* bo virtual address in a specific vm */
@@ -779,13 +789,11 @@ struct radeon_ring {
        volatile uint32_t       *ring;
        unsigned                rptr;
        unsigned                rptr_offs;
-       unsigned                rptr_reg;
        unsigned                rptr_save_reg;
        u64                     next_rptr_gpu_addr;
        volatile u32            *next_rptr_cpu_addr;
        unsigned                wptr;
        unsigned                wptr_old;
-       unsigned                wptr_reg;
        unsigned                ring_size;
        unsigned                ring_free_dw;
        int                     count_dw;
@@ -949,7 +957,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring
 int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
                        unsigned size, uint32_t *data);
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop);
+                    unsigned rptr_offs, u32 nop);
 void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp);
 
 
@@ -1775,6 +1783,7 @@ struct radeon_asic {
                int (*init)(struct radeon_device *rdev);
                void (*setup_asic)(struct radeon_device *rdev);
                int (*enable)(struct radeon_device *rdev);
+               int (*late_enable)(struct radeon_device *rdev);
                void (*disable)(struct radeon_device *rdev);
                int (*pre_set_power_state)(struct radeon_device *rdev);
                int (*set_power_state)(struct radeon_device *rdev);
@@ -1940,7 +1949,7 @@ struct si_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -1970,7 +1979,7 @@ struct cik_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -2650,6 +2659,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev))
 #define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
 #define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
+#define radeon_dpm_late_enable(rdev) rdev->asic->dpm.late_enable((rdev))
 #define radeon_dpm_disable(rdev) rdev->asic->dpm.disable((rdev))
 #define radeon_dpm_pre_set_power_state(rdev) rdev->asic->dpm.pre_set_power_state((rdev))
 #define radeon_dpm_set_power_state(rdev) rdev->asic->dpm.set_power_state((rdev))
@@ -2668,6 +2678,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 /* Common functions */
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
+extern void radeon_pci_config_reset(struct radeon_device *rdev);
 extern void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung);
 extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
index c0425bb6223a99fae5eab07a069ab73ace19eec7..f74db43346fd86f4658e11cc62e6e08134127936 100644 (file)
@@ -182,9 +182,9 @@ static struct radeon_asic_ring r100_gfx_ring = {
        .ring_test = &r100_ring_test,
        .ib_test = &r100_ib_test,
        .is_lockup = &r100_gpu_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r100_gfx_get_rptr,
+       .get_wptr = &r100_gfx_get_wptr,
+       .set_wptr = &r100_gfx_set_wptr,
 };
 
 static struct radeon_asic r100_asic = {
@@ -330,9 +330,9 @@ static struct radeon_asic_ring r300_gfx_ring = {
        .ring_test = &r100_ring_test,
        .ib_test = &r100_ib_test,
        .is_lockup = &r100_gpu_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r100_gfx_get_rptr,
+       .get_wptr = &r100_gfx_get_wptr,
+       .set_wptr = &r100_gfx_set_wptr,
 };
 
 static struct radeon_asic r300_asic = {
@@ -883,9 +883,9 @@ static struct radeon_asic_ring r600_gfx_ring = {
        .ring_test = &r600_ring_test,
        .ib_test = &r600_ib_test,
        .is_lockup = &r600_gfx_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r600_gfx_get_rptr,
+       .get_wptr = &r600_gfx_get_wptr,
+       .set_wptr = &r600_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring r600_dma_ring = {
@@ -1045,6 +1045,7 @@ static struct radeon_asic rv6xx_asic = {
                .init = &rv6xx_dpm_init,
                .setup_asic = &rv6xx_setup_asic,
                .enable = &rv6xx_dpm_enable,
+               .late_enable = &r600_dpm_late_enable,
                .disable = &rv6xx_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rv6xx_dpm_set_power_state,
@@ -1135,6 +1136,7 @@ static struct radeon_asic rs780_asic = {
                .init = &rs780_dpm_init,
                .setup_asic = &rs780_dpm_setup_asic,
                .enable = &rs780_dpm_enable,
+               .late_enable = &r600_dpm_late_enable,
                .disable = &rs780_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rs780_dpm_set_power_state,
@@ -1239,6 +1241,7 @@ static struct radeon_asic rv770_asic = {
                .init = &rv770_dpm_init,
                .setup_asic = &rv770_dpm_setup_asic,
                .enable = &rv770_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &rv770_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rv770_dpm_set_power_state,
@@ -1267,9 +1270,9 @@ static struct radeon_asic_ring evergreen_gfx_ring = {
        .ring_test = &r600_ring_test,
        .ib_test = &r600_ib_test,
        .is_lockup = &evergreen_gfx_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r600_gfx_get_rptr,
+       .get_wptr = &r600_gfx_get_wptr,
+       .set_wptr = &r600_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring evergreen_dma_ring = {
@@ -1357,6 +1360,7 @@ static struct radeon_asic evergreen_asic = {
                .init = &cypress_dpm_init,
                .setup_asic = &cypress_dpm_setup_asic,
                .enable = &cypress_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &cypress_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &cypress_dpm_set_power_state,
@@ -1449,6 +1453,7 @@ static struct radeon_asic sumo_asic = {
                .init = &sumo_dpm_init,
                .setup_asic = &sumo_dpm_setup_asic,
                .enable = &sumo_dpm_enable,
+               .late_enable = &sumo_dpm_late_enable,
                .disable = &sumo_dpm_disable,
                .pre_set_power_state = &sumo_dpm_pre_set_power_state,
                .set_power_state = &sumo_dpm_set_power_state,
@@ -1540,6 +1545,7 @@ static struct radeon_asic btc_asic = {
                .init = &btc_dpm_init,
                .setup_asic = &btc_dpm_setup_asic,
                .enable = &btc_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &btc_dpm_disable,
                .pre_set_power_state = &btc_dpm_pre_set_power_state,
                .set_power_state = &btc_dpm_set_power_state,
@@ -1570,9 +1576,9 @@ static struct radeon_asic_ring cayman_gfx_ring = {
        .ib_test = &r600_ib_test,
        .is_lockup = &cayman_gfx_is_lockup,
        .vm_flush = &cayman_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cayman_gfx_get_rptr,
+       .get_wptr = &cayman_gfx_get_wptr,
+       .set_wptr = &cayman_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring cayman_dma_ring = {
@@ -1585,9 +1591,9 @@ static struct radeon_asic_ring cayman_dma_ring = {
        .ib_test = &r600_dma_ib_test,
        .is_lockup = &cayman_dma_is_lockup,
        .vm_flush = &cayman_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr
+       .get_rptr = &cayman_dma_get_rptr,
+       .get_wptr = &cayman_dma_get_wptr,
+       .set_wptr = &cayman_dma_set_wptr
 };
 
 static struct radeon_asic_ring cayman_uvd_ring = {
@@ -1683,6 +1689,7 @@ static struct radeon_asic cayman_asic = {
                .init = &ni_dpm_init,
                .setup_asic = &ni_dpm_setup_asic,
                .enable = &ni_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &ni_dpm_disable,
                .pre_set_power_state = &ni_dpm_pre_set_power_state,
                .set_power_state = &ni_dpm_set_power_state,
@@ -1783,6 +1790,7 @@ static struct radeon_asic trinity_asic = {
                .init = &trinity_dpm_init,
                .setup_asic = &trinity_dpm_setup_asic,
                .enable = &trinity_dpm_enable,
+               .late_enable = &trinity_dpm_late_enable,
                .disable = &trinity_dpm_disable,
                .pre_set_power_state = &trinity_dpm_pre_set_power_state,
                .set_power_state = &trinity_dpm_set_power_state,
@@ -1813,9 +1821,9 @@ static struct radeon_asic_ring si_gfx_ring = {
        .ib_test = &r600_ib_test,
        .is_lockup = &si_gfx_is_lockup,
        .vm_flush = &si_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cayman_gfx_get_rptr,
+       .get_wptr = &cayman_gfx_get_wptr,
+       .set_wptr = &cayman_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring si_dma_ring = {
@@ -1828,9 +1836,9 @@ static struct radeon_asic_ring si_dma_ring = {
        .ib_test = &r600_dma_ib_test,
        .is_lockup = &si_dma_is_lockup,
        .vm_flush = &si_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr,
+       .get_rptr = &cayman_dma_get_rptr,
+       .get_wptr = &cayman_dma_get_wptr,
+       .set_wptr = &cayman_dma_set_wptr,
 };
 
 static struct radeon_asic si_asic = {
@@ -1913,6 +1921,7 @@ static struct radeon_asic si_asic = {
                .init = &si_dpm_init,
                .setup_asic = &si_dpm_setup_asic,
                .enable = &si_dpm_enable,
+               .late_enable = &si_dpm_late_enable,
                .disable = &si_dpm_disable,
                .pre_set_power_state = &si_dpm_pre_set_power_state,
                .set_power_state = &si_dpm_set_power_state,
@@ -1943,9 +1952,9 @@ static struct radeon_asic_ring ci_gfx_ring = {
        .ib_test = &cik_ib_test,
        .is_lockup = &cik_gfx_is_lockup,
        .vm_flush = &cik_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cik_gfx_get_rptr,
+       .get_wptr = &cik_gfx_get_wptr,
+       .set_wptr = &cik_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring ci_cp_ring = {
@@ -1958,9 +1967,9 @@ static struct radeon_asic_ring ci_cp_ring = {
        .ib_test = &cik_ib_test,
        .is_lockup = &cik_gfx_is_lockup,
        .vm_flush = &cik_vm_flush,
-       .get_rptr = &cik_compute_ring_get_rptr,
-       .get_wptr = &cik_compute_ring_get_wptr,
-       .set_wptr = &cik_compute_ring_set_wptr,
+       .get_rptr = &cik_compute_get_rptr,
+       .get_wptr = &cik_compute_get_wptr,
+       .set_wptr = &cik_compute_set_wptr,
 };
 
 static struct radeon_asic_ring ci_dma_ring = {
@@ -1973,9 +1982,9 @@ static struct radeon_asic_ring ci_dma_ring = {
        .ib_test = &cik_sdma_ib_test,
        .is_lockup = &cik_sdma_is_lockup,
        .vm_flush = &cik_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr,
+       .get_rptr = &cik_sdma_get_rptr,
+       .get_wptr = &cik_sdma_get_wptr,
+       .set_wptr = &cik_sdma_set_wptr,
 };
 
 static struct radeon_asic ci_asic = {
@@ -2058,6 +2067,7 @@ static struct radeon_asic ci_asic = {
                .init = &ci_dpm_init,
                .setup_asic = &ci_dpm_setup_asic,
                .enable = &ci_dpm_enable,
+               .late_enable = &ci_dpm_late_enable,
                .disable = &ci_dpm_disable,
                .pre_set_power_state = &ci_dpm_pre_set_power_state,
                .set_power_state = &ci_dpm_set_power_state,
@@ -2159,6 +2169,7 @@ static struct radeon_asic kv_asic = {
                .init = &kv_dpm_init,
                .setup_asic = &kv_dpm_setup_asic,
                .enable = &kv_dpm_enable,
+               .late_enable = &kv_dpm_late_enable,
                .disable = &kv_dpm_disable,
                .pre_set_power_state = &kv_dpm_pre_set_power_state,
                .set_power_state = &kv_dpm_set_power_state,
@@ -2449,7 +2460,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2468,7 +2479,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CP_LS |
@@ -2493,7 +2504,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2521,7 +2532,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
index c9fd97b58076bd366e57e7916f93de5435c58c52..b3bc433eed4c3bd832424051306a845461c90aa8 100644 (file)
@@ -47,13 +47,6 @@ u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder);
 void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level);
 u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder);
 
-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring);
-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring);
-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
-                                 struct radeon_ring *ring);
-
 /*
  * r100,rv100,rs100,rv200,rs200
  */
@@ -148,6 +141,13 @@ extern void r100_post_page_flip(struct radeon_device *rdev, int crtc);
 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
 
+u32 r100_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 r100_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void r100_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
+
 /*
  * r200,rv250,rs300,rv280
  */
@@ -368,6 +368,12 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
 int r600_pcie_gart_init(struct radeon_device *rdev);
 void r600_scratch_init(struct radeon_device *rdev);
 int r600_init_microcode(struct radeon_device *rdev);
+u32 r600_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 r600_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void r600_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
 /* r600 irq */
 int r600_irq_process(struct radeon_device *rdev);
 int r600_irq_init(struct radeon_device *rdev);
@@ -392,6 +398,7 @@ int rv6xx_get_temp(struct radeon_device *rdev);
 int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int r600_dpm_pre_set_power_state(struct radeon_device *rdev);
 void r600_dpm_post_set_power_state(struct radeon_device *rdev);
+int r600_dpm_late_enable(struct radeon_device *rdev);
 /* r600 dma */
 uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
                           struct radeon_ring *ring);
@@ -454,6 +461,7 @@ int rv770_get_temp(struct radeon_device *rdev);
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(struct radeon_device *rdev);
+int rv770_dpm_late_enable(struct radeon_device *rdev);
 void rv770_dpm_disable(struct radeon_device *rdev);
 int rv770_dpm_set_power_state(struct radeon_device *rdev);
 void rv770_dpm_setup_asic(struct radeon_device *rdev);
@@ -545,6 +553,7 @@ u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
 bool btc_dpm_vblank_too_short(struct radeon_device *rdev);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
+int sumo_dpm_late_enable(struct radeon_device *rdev);
 void sumo_dpm_disable(struct radeon_device *rdev);
 int sumo_dpm_pre_set_power_state(struct radeon_device *rdev);
 int sumo_dpm_set_power_state(struct radeon_device *rdev);
@@ -591,6 +600,19 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
 
 void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 
+u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring);
+u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring);
+void cayman_gfx_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring);
+uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring);
+void cayman_dma_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+
 int ni_dpm_init(struct radeon_device *rdev);
 void ni_dpm_setup_asic(struct radeon_device *rdev);
 int ni_dpm_enable(struct radeon_device *rdev);
@@ -610,6 +632,7 @@ int ni_dpm_force_performance_level(struct radeon_device *rdev,
 bool ni_dpm_vblank_too_short(struct radeon_device *rdev);
 int trinity_dpm_init(struct radeon_device *rdev);
 int trinity_dpm_enable(struct radeon_device *rdev);
+int trinity_dpm_late_enable(struct radeon_device *rdev);
 void trinity_dpm_disable(struct radeon_device *rdev);
 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev);
 int trinity_dpm_set_power_state(struct radeon_device *rdev);
@@ -669,6 +692,7 @@ int si_get_temp(struct radeon_device *rdev);
 int si_dpm_init(struct radeon_device *rdev);
 void si_dpm_setup_asic(struct radeon_device *rdev);
 int si_dpm_enable(struct radeon_device *rdev);
+int si_dpm_late_enable(struct radeon_device *rdev);
 void si_dpm_disable(struct radeon_device *rdev);
 int si_dpm_pre_set_power_state(struct radeon_device *rdev);
 int si_dpm_set_power_state(struct radeon_device *rdev);
@@ -739,17 +763,30 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
                          uint32_t incr, uint32_t flags);
 void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring);
-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring);
-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
-                              struct radeon_ring *ring);
+u32 cik_gfx_get_rptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring);
+u32 cik_gfx_get_wptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring);
+void cik_gfx_set_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 cik_compute_get_rptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+u32 cik_compute_get_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+void cik_compute_set_wptr(struct radeon_device *rdev,
+                         struct radeon_ring *ring);
+u32 cik_sdma_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 cik_sdma_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void cik_sdma_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
 int ci_get_temp(struct radeon_device *rdev);
 int kv_get_temp(struct radeon_device *rdev);
 
 int ci_dpm_init(struct radeon_device *rdev);
 int ci_dpm_enable(struct radeon_device *rdev);
+int ci_dpm_late_enable(struct radeon_device *rdev);
 void ci_dpm_disable(struct radeon_device *rdev);
 int ci_dpm_pre_set_power_state(struct radeon_device *rdev);
 int ci_dpm_set_power_state(struct radeon_device *rdev);
@@ -770,6 +807,7 @@ void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
 
 int kv_dpm_init(struct radeon_device *rdev);
 int kv_dpm_enable(struct radeon_device *rdev);
+int kv_dpm_late_enable(struct radeon_device *rdev);
 void kv_dpm_disable(struct radeon_device *rdev);
 int kv_dpm_pre_set_power_state(struct radeon_device *rdev);
 int kv_dpm_set_power_state(struct radeon_device *rdev);
index 5c39bf7c3d88668bad65ef9667de82a0a145f196..f48bd6dc10cda2a9c993879c65f5fac574702728 100644 (file)
 #include "atom.h"
 #include "atom-bits.h"
 
-/* from radeon_encoder.c */
-extern uint32_t
-radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
-                       uint8_t dac);
-extern void radeon_link_encoder_connector(struct drm_device *dev);
 extern void
 radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
                        uint32_t supported_device, u16 caps);
 
-/* from radeon_connector.c */
-extern void
-radeon_add_atom_connector(struct drm_device *dev,
-                         uint32_t connector_id,
-                         uint32_t supported_device,
-                         int connector_type,
-                         struct radeon_i2c_bus_rec *i2c_bus,
-                         uint32_t igp_lane_info,
-                         uint16_t connector_object_id,
-                         struct radeon_hpd *hpd,
-                         struct radeon_router *router);
-
 /* from radeon_legacy_encoder.c */
 extern void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
@@ -1528,6 +1511,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v1.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
+                                       ss->percentage_divider = 100;
                                        return true;
                                }
                                ss_assign = (union asic_ss_assignment *)
@@ -1545,6 +1529,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v2.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
+                                       ss->percentage_divider = 100;
                                        if ((crev == 2) &&
                                            ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                             (id == ASIC_INTERNAL_MEMORY_SS)))
@@ -1566,6 +1551,11 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v3.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
+                                       if (ss_assign->v3.ucSpreadSpectrumMode &
+                                           SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK)
+                                               ss->percentage_divider = 1000;
+                                       else
+                                               ss->percentage_divider = 100;
                                        if ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                            (id == ASIC_INTERNAL_MEMORY_SS))
                                                ss->rate /= 100;
@@ -1809,7 +1799,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                if (misc & ATOM_DOUBLE_CLOCK_MODE)
                        mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
-               mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+               mode->crtc_clock = mode->clock =
+                       le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 
                if (index == 1) {
                        /* PAL timings appear to have wrong values for totals */
@@ -1852,7 +1843,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                if (misc & ATOM_DOUBLE_CLOCK_MODE)
                        mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
-               mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+               mode->crtc_clock = mode->clock =
+                       le16_to_cpu(dtd_timings->usPixClk) * 10;
                break;
        }
        return true;
@@ -3884,16 +3876,18 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
                                                        ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));
                                        }
                                        reg_table->last = i;
-                                       while ((*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) &&
+                                       while ((le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) &&
                                               (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) {
-                                               t_mem_id = (u8)((*(u32 *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT);
+                                               t_mem_id = (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK)
+                                                               >> MEM_ID_SHIFT);
                                                if (module_index == t_mem_id) {
                                                        reg_table->mc_reg_table_entry[num_ranges].mclk_max =
-                                                               (u32)((*(u32 *)reg_data & CLOCK_RANGE_MASK) >> CLOCK_RANGE_SHIFT);
+                                                               (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK)
+                                                                     >> CLOCK_RANGE_SHIFT);
                                                        for (i = 0, j = 1; i < reg_table->last; i++) {
                                                                if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
                                                                        reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
-                                                                               (u32)*((u32 *)reg_data + j);
+                                                                               (u32)le32_to_cpu(*((u32 *)reg_data + j));
                                                                        j++;
                                                                } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
                                                                        reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
@@ -3905,7 +3899,7 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
                                                reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
                                                        ((u8 *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize));
                                        }
-                                       if (*(u32 *)reg_data != END_OF_REG_DATA_BLOCK)
+                                       if (le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK)
                                                return -EINVAL;
                                        reg_table->num_entries = num_ranges;
                                } else
index 9d302eaeea1587b6fdb5439119b6f45c0de961db..485848f889f55c9f4b86bf61bd8c019e2ad96a27 100644 (file)
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
        bool atpx_detected;
        /* handle for device - and atpx */
        acpi_handle dhandle;
+       acpi_handle other_handle;
        struct radeon_atpx atpx;
 } radeon_atpx_priv;
 
@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
                return false;
 
        status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+               radeon_atpx_priv.other_handle = dhandle;
                return false;
-
+       }
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx.handle = atpx_handle;
        return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                radeon_atpx_priv.atpx_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when ATPX is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
+               acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
                return true;
        }
        return false;
index 68ce360560190af6505856452658e450d3f6878a..6651177110f08cd5afb9088f4849ad3f987f5a1b 100644 (file)
 #include <asm/pci-bridge.h>
 #endif /* CONFIG_PPC_PMAC */
 
-/* from radeon_encoder.c */
-extern uint32_t
-radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
-                       uint8_t dac);
-extern void radeon_link_encoder_connector(struct drm_device *dev);
-
-/* from radeon_connector.c */
-extern void
-radeon_add_legacy_connector(struct drm_device *dev,
-                           uint32_t connector_id,
-                           uint32_t supported_device,
-                           int connector_type,
-                           struct radeon_i2c_bus_rec *i2c_bus,
-                           uint16_t connector_object_id,
-                           struct radeon_hpd *hpd);
-
 /* from radeon_legacy_encoder.c */
 extern void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
index 20a768ac89a8e6532b33cbb3114928afc98749b7..82d4f865546ed9024b4078d67bfdd947f08a1060 100644 (file)
 
 #include <linux/pm_runtime.h>
 
-extern void
-radeon_combios_connected_scratch_regs(struct drm_connector *connector,
-                                     struct drm_encoder *encoder,
-                                     bool connected);
-extern void
-radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
-                                      struct drm_encoder *encoder,
-                                      bool connected);
-
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
index 3cae2bbc1854d73dda35f13f0b8cfc3201dc2c25..bb0d5c3a8311bf0dc274c2b47930078d7e657852 100644 (file)
@@ -2020,10 +2020,10 @@ static int radeon_cp_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+               if (copy_to_user(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+               if (copy_to_user(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
                        return -EFAULT;
 
@@ -2228,7 +2228,7 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv)
 
        dev_priv->ring.tail &= dev_priv->ring.tail_mask;
 
-       DRM_MEMORYBARRIER();
+       mb();
        GET_RING_HEAD( dev_priv );
 
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
index 0b366169d64de55c52e4c2d9c26d1c3b9db19b2d..a8e3342fd4a9d0d4a1f67c0a6cee0f3134ffa8d2 100644 (file)
@@ -192,7 +192,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                return -ENOMEM;
        }
        chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
-       if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr,
+       if (copy_from_user(p->chunks_array, chunk_array_ptr,
                               sizeof(uint64_t)*cs->num_chunks)) {
                return -EFAULT;
        }
@@ -208,7 +208,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                uint32_t __user *cdata;
 
                chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i];
-               if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr,
+               if (copy_from_user(&user_chunk, chunk_ptr,
                                       sizeof(struct drm_radeon_cs_chunk))) {
                        return -EFAULT;
                }
@@ -252,7 +252,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                if (p->chunks[i].kdata == NULL) {
                        return -ENOMEM;
                }
-               if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) {
+               if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
                        return -EFAULT;
                }
                if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
@@ -472,7 +472,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser
                        }
                        parser->const_ib.is_const_ib = true;
                        parser->const_ib.length_dw = ib_chunk->length_dw;
-                       if (DRM_COPY_FROM_USER(parser->const_ib.ptr,
+                       if (copy_from_user(parser->const_ib.ptr,
                                               ib_chunk->user_ptr,
                                               ib_chunk->length_dw * 4))
                                return -EFAULT;
@@ -495,7 +495,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser
        parser->ib.length_dw = ib_chunk->length_dw;
        if (ib_chunk->kdata)
                memcpy(parser->ib.ptr, ib_chunk->kdata, ib_chunk->length_dw * 4);
-       else if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4))
+       else if (copy_from_user(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4))
                return -EFAULT;
        return 0;
 }
index 39b033b441d2a6f76e8d021df7085568538887b3..b012cbbc3ed5a9b892b433eff0ee5f3134a130de 100644 (file)
@@ -144,6 +144,11 @@ void radeon_program_register_sequence(struct radeon_device *rdev,
        }
 }
 
+void radeon_pci_config_reset(struct radeon_device *rdev)
+{
+       pci_write_config_dword(rdev->pdev, 0x7c, RADEON_ASIC_RESET_DATA);
+}
+
 /**
  * radeon_surface_init - Clear GPU surface registers.
  *
@@ -249,7 +254,7 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
  * Init doorbell driver information (CIK)
  * Returns 0 on success, error on failure.
  */
-int radeon_doorbell_init(struct radeon_device *rdev)
+static int radeon_doorbell_init(struct radeon_device *rdev)
 {
        /* doorbell bar mapping */
        rdev->doorbell.base = pci_resource_start(rdev->pdev, 2);
@@ -278,7 +283,7 @@ int radeon_doorbell_init(struct radeon_device *rdev)
  *
  * Tear down doorbell driver information (CIK)
  */
-void radeon_doorbell_fini(struct radeon_device *rdev)
+static void radeon_doorbell_fini(struct radeon_device *rdev)
 {
        iounmap(rdev->doorbell.ptr);
        rdev->doorbell.ptr = NULL;
@@ -1330,6 +1335,7 @@ int radeon_device_init(struct radeon_device *rdev,
                if (r)
                        return r;
        }
+
        if ((radeon_testing & 1)) {
                if (rdev->accel_working)
                        radeon_test_moves(rdev);
@@ -1455,7 +1461,6 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
        radeon_save_bios_scratch_regs(rdev);
 
-       radeon_pm_suspend(rdev);
        radeon_suspend(rdev);
        radeon_hpd_fini(rdev);
        /* evict remaining vram memory */
@@ -1516,14 +1521,22 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        if (r)
                DRM_ERROR("ib ring test failed (%d).\n", r);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.dpm_enabled) {
+               /* do dpm late init */
+               r = radeon_pm_late_init(rdev);
+               if (r) {
+                       rdev->pm.dpm_enabled = false;
+                       DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+               }
+       }
+
        radeon_restore_bios_scratch_regs(rdev);
 
        if (fbcon) {
                radeon_fbdev_set_suspend(rdev, 0);
                console_unlock();
        }
-       
+
        /* init dig PHYs, disp eng pll */
        if (rdev->is_atom_bios) {
                radeon_atom_encoder_init(rdev);
index 7b253815a3237153b668d660e9ef7d56642597ec..d680608f6f5bc9a80e879b4f24769f8a9ffb1e8c 100644 (file)
@@ -306,7 +306,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
         * to complete in this vblank?
         */
        if (update_pending &&
-           (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
+           (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
                                                               &vpos, &hpos, NULL, NULL)) &&
            ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
             (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
@@ -1464,12 +1464,22 @@ int radeon_modeset_init(struct radeon_device *rdev)
        /* setup afmt */
        radeon_afmt_init(rdev);
 
-       /* Initialize power management */
-       radeon_pm_init(rdev);
-
        radeon_fbdev_init(rdev);
        drm_kms_helper_poll_init(rdev->ddev);
 
+       if (rdev->pm.dpm_enabled) {
+               /* do dpm late init */
+               ret = radeon_pm_late_init(rdev);
+               if (ret) {
+                       rdev->pm.dpm_enabled = false;
+                       DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+               }
+               /* set the dpm state for PX since there won't be
+                * a modeset to call this.
+                */
+               radeon_pm_compute_clocks(rdev);
+       }
+
        return 0;
 }
 
@@ -1477,7 +1487,6 @@ void radeon_modeset_fini(struct radeon_device *rdev)
 {
        radeon_fbdev_fini(rdev);
        kfree(rdev->mode_info.bios_hardcoded_edid);
-       radeon_pm_fini(rdev);
 
        if (rdev->mode_info.mode_config_initialized) {
                radeon_afmt_fini(rdev);
@@ -1601,6 +1610,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
  *
  * \param dev Device to query.
  * \param crtc Crtc to query.
+ * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
  * \param *vpos Location where vertical scanout position should be stored.
  * \param *hpos Location where horizontal scanout position should go.
  * \param *stime Target location for timestamp taken immediately before
@@ -1622,8 +1632,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
  * unknown small number of scanlines wrt. real scanout position.
  *
  */
-int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos,
-                              ktime_t *stime, ktime_t *etime)
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
+                              int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
 {
        u32 stat_crtc = 0, vbl = 0, position = 0;
        int vbl_start, vbl_end, vtotal, ret = 0;
@@ -1765,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int
        if (in_vbl)
                ret |= DRM_SCANOUTPOS_INVBL;
 
+       /* Is vpos outside nominal vblank area, but less than
+        * 1/100 of a frame height away from start of vblank?
+        * If so, assume this isn't a massively delayed vblank
+        * interrupt, but a vblank interrupt that fired a few
+        * microseconds before true start of vblank. Compensate
+        * by adding a full frame duration to the final timestamp.
+        * Happens, e.g., on ATI R500, R600.
+        *
+        * We only do this if DRM_CALLED_FROM_VBLIRQ.
+        */
+       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
+               vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+               vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+
+               if (vbl_start - *vpos < vtotal / 100) {
+                       *vpos -= vtotal;
+
+                       /* Signal this correction as "applied". */
+                       ret |= 0x8;
+               }
+       }
+
        return ret;
 }
index 1958b36ad0e5cdddf623b8a54a16df0c501ca668..1235a78fbba15716d9987b3cb645120fca6bc30d 100644 (file)
  *   2.33.0 - Add SI tiling mode array query
  *   2.34.0 - Add CIK tiling mode array query
  *   2.35.0 - Add CIK macrotile mode array query
+ *   2.36.0 - Fix CIK DCE tiling setup
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       35
+#define KMS_DRIVER_MINOR       36
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -101,13 +102,14 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
 void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
 int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
 void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
-irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
+irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg);
 void radeon_gem_object_free(struct drm_gem_object *obj);
 int radeon_gem_object_open(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
 void radeon_gem_object_close(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
                                      ktime_t *etime);
 extern const struct drm_ioctl_desc radeon_ioctls_kms[];
@@ -167,6 +169,7 @@ int radeon_fastfb = 0;
 int radeon_dpm = -1;
 int radeon_aspm = -1;
 int radeon_runtime_pm = -1;
+int radeon_hard_reset = 0;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -231,6 +234,9 @@ module_param_named(aspm, radeon_aspm, int, 0444);
 MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)");
 module_param_named(runpm, radeon_runtime_pm, int, 0444);
 
+MODULE_PARM_DESC(hard_reset, "PCI config reset (1 = force enable, 0 = disable (default))");
+module_param_named(hard_reset, radeon_hard_reset, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
        radeon_PCI_IDS
 };
index 00e0d449021c343015540ea3baf1028b85a10090..dafd812e45710b0ffed36c33f3e37de20ec64733 100644 (file)
@@ -405,7 +405,7 @@ extern void radeon_do_release(struct drm_device * dev);
 extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
 extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
-extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
 extern int radeon_driver_irq_postinstall(struct drm_device *dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
index d3a86e43c0123715e0cf765a738e6664f42ab6e0..866744e47cfacc20c98a19151c9b7529eb9c447b 100644 (file)
@@ -841,6 +841,8 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
                if (!rdev->fence_drv[i].initialized)
                        continue;
 
+               radeon_fence_process(rdev, i);
+
                seq_printf(m, "--- ring %d ---\n", i);
                seq_printf(m, "Last signaled fence 0x%016llx\n",
                           (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
index 805c5e566b9a1f29539a4cf1148183056dc90579..b96c819024b3cdb7b2ea8f387c1e267a563ed8df 100644 (file)
@@ -86,7 +86,7 @@ retry:
        return 0;
 }
 
-int radeon_gem_set_domain(struct drm_gem_object *gobj,
+static int radeon_gem_set_domain(struct drm_gem_object *gobj,
                          uint32_t rdomain, uint32_t wdomain)
 {
        struct radeon_bo *robj;
index fc60b74ee304dd779d98db03b3ec60c58767ed9a..e24ca6ab96decdf94c3e86a097d949f2705a1f7c 100644 (file)
@@ -1020,6 +1020,9 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 /* Add the default buses */
 void radeon_i2c_init(struct radeon_device *rdev)
 {
+       if (radeon_hw_i2c)
+               DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n");
+
        if (rdev->is_atom_bios)
                radeon_atombios_i2c_init(rdev);
        else
index 8d68e972789a343f08186c3a4560d7c18db24999..244b19bab2e72406648ef1b2eae8ef7965bfcf01 100644 (file)
@@ -181,7 +181,7 @@ static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_dis
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t radeon_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_radeon_private_t *dev_priv =
@@ -203,7 +203,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
 
        /* SW interrupt */
        if (stat & RADEON_SW_INT_TEST)
-               DRM_WAKEUP(&dev_priv->swi_queue);
+               wake_up(&dev_priv->swi_queue);
 
        /* VBLANK interrupt */
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
@@ -249,7 +249,7 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ,
                    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
 
        return ret;
@@ -302,7 +302,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr
 
        result = radeon_emit_irq(dev);
 
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
@@ -354,7 +354,7 @@ int radeon_driver_irq_postinstall(struct drm_device *dev)
            (drm_radeon_private_t *) dev->dev_private;
 
        atomic_set(&dev_priv->swi_emitted, 0);
-       DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+       init_waitqueue_head(&dev_priv->swi_queue);
 
        dev->max_vblank_count = 0x001fffff;
 
index ec6240b00469a18c471e181d59c4670b2e05069d..089c9ffb0aa95e8e47c964f190b07e0e8fe93c32 100644 (file)
 /**
  * radeon_driver_irq_handler_kms - irq handler for KMS
  *
- * @DRM_IRQ_ARGS: args
+ * @int irq, void *arg: args
  *
  * This is the irq handler for the radeon KMS driver (all asics).
  * radeon_irq_process is a macro that points to the per-asic
  * irq handler callback.
  */
-irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
+irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct radeon_device *rdev = dev->dev_private;
index 55d0b474bd371ae83f1cea0ec08d30504b371816..114d1672d616d0b5d7b85ab5d739da66f2db823e 100644 (file)
@@ -191,7 +191,7 @@ static void radeon_set_filp_rights(struct drm_device *dev,
  * etc. (all asics).
  * Returns 0 on success, -EINVAL on failure.
  */
-int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_radeon_info *info = data;
@@ -223,7 +223,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        *value = rdev->accel_working;
                break;
        case RADEON_INFO_CRTC_FROM_ID:
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -269,7 +269,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                 *
                 * When returning, the value is 1 if filp owns hyper-z access,
                 * 0 otherwise. */
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -281,7 +281,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                break;
        case RADEON_INFO_WANT_CMASK:
                /* The same logic as Hyper-Z. */
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -417,7 +417,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                *value = rdev->fastfb_working;
                break;
        case RADEON_INFO_RING_WORKING:
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -461,11 +461,27 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_SI_CP_DMA_COMPUTE:
                *value = 1;
                break;
+       case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
+               if (rdev->family >= CHIP_BONAIRE) {
+                       *value = rdev->config.cik.backend_enable_mask;
+               } else if (rdev->family >= CHIP_TAHITI) {
+                       *value = rdev->config.si.backend_enable_mask;
+               } else {
+                       DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+               }
+               break;
+       case RADEON_INFO_MAX_SCLK:
+               if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
+                   rdev->pm.dpm_enabled)
+                       *value = rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10;
+               else
+                       *value = rdev->pm.default_sclk * 10;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
        }
-       if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) {
+       if (copy_to_user(value_ptr, (char*)value, value_size)) {
                DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
                return -EFAULT;
        }
@@ -703,11 +719,12 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
                                                     vblank_time, flags,
-                                                    drmcrtc);
+                                                    drmcrtc, &drmcrtc->hwmode);
 }
 
 #define KMS_INVALID_IOCTL(name)                                                \
-int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\
+static int name(struct drm_device *dev, void *data, struct drm_file    \
+               *file_priv)                                             \
 {                                                                      \
        DRM_ERROR("invalid ioctl with kms %s\n", __func__);             \
        return -EINVAL;                                                 \
index d54d2d7c9031a7ff957fec87b1d58c0ed927e6a5..146d253f1131a4780e889893b3e566336548b3f7 100644 (file)
@@ -243,7 +243,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p
        if (!block)
                return -ENOMEM;
 
-       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+       if (copy_to_user(alloc->region_offset, &block->start,
                             sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
index 3f0dd664af90d6815b2edea895662936cc1982e4..402dbe32c23483afb3524d3397e3ce1b7c3cc281 100644 (file)
@@ -291,6 +291,7 @@ struct radeon_tv_regs {
 
 struct radeon_atom_ss {
        uint16_t percentage;
+       uint16_t percentage_divider;
        uint8_t type;
        uint16_t step;
        uint8_t delay;
@@ -624,6 +625,30 @@ struct atom_voltage_table
        struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES];
 };
 
+
+extern void
+radeon_add_atom_connector(struct drm_device *dev,
+                         uint32_t connector_id,
+                         uint32_t supported_device,
+                         int connector_type,
+                         struct radeon_i2c_bus_rec *i2c_bus,
+                         uint32_t igp_lane_info,
+                         uint16_t connector_object_id,
+                         struct radeon_hpd *hpd,
+                         struct radeon_router *router);
+extern void
+radeon_add_legacy_connector(struct drm_device *dev,
+                           uint32_t connector_id,
+                           uint32_t supported_device,
+                           int connector_type,
+                           struct radeon_i2c_bus_rec *i2c_bus,
+                           uint16_t connector_object_id,
+                           struct radeon_hpd *hpd);
+extern uint32_t
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+                       uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
 extern enum radeon_tv_std
@@ -631,6 +656,15 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
 extern void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
                                                 u16 *vddc, u16 *vddci, u16 *mvdd);
 
+extern void
+radeon_combios_connected_scratch_regs(struct drm_connector *connector,
+                                     struct drm_encoder *encoder,
+                                     bool connected);
+extern void
+radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
+                                      struct drm_encoder *encoder,
+                                      bool connected);
+
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 extern struct drm_connector *
@@ -666,6 +700,7 @@ extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
 extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                                u8 write_byte, u8 *read_byte);
+void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
 
 extern void radeon_i2c_init(struct radeon_device *rdev);
 extern void radeon_i2c_fini(struct radeon_device *rdev);
@@ -766,6 +801,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                                   int x, int y);
 
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
                                      ktime_t *etime);
 
index c0fa4aa9ceea8ad8d22c7485b28f4bf045a3a7dd..08595cf90b0139ee0da24f4ac3725e30dcbf9d68 100644 (file)
@@ -46,7 +46,7 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
  * function are calling it.
  */
 
-void radeon_bo_clear_va(struct radeon_bo *bo)
+static void radeon_bo_clear_va(struct radeon_bo *bo)
 {
        struct radeon_bo_va *bo_va, *tmp;
 
index 984097b907ef5ee67c8e59faf4198ccf8add5f1b..8e8153e471c20a6b0dba28b38ce36bcd78f41a7b 100644 (file)
@@ -924,6 +924,10 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
 
        if (rdev->asic->dpm.powergate_uvd) {
                mutex_lock(&rdev->pm.mutex);
+               /* don't powergate anything if we
+                  have active but pause streams */
+               enable |= rdev->pm.dpm.sd > 0;
+               enable |= rdev->pm.dpm.hd > 0;
                /* enable/disable UVD */
                radeon_dpm_powergate_uvd(rdev, !enable);
                mutex_unlock(&rdev->pm.mutex);
@@ -1010,8 +1014,10 @@ static void radeon_pm_resume_old(struct radeon_device *rdev)
        rdev->pm.current_clock_mode_index = 0;
        rdev->pm.current_sclk = rdev->pm.default_sclk;
        rdev->pm.current_mclk = rdev->pm.default_mclk;
-       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
-       rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       if (rdev->pm.power_state) {
+               rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+               rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       }
        if (rdev->pm.pm_method == PM_METHOD_DYNPM
            && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
                rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
@@ -1032,25 +1038,27 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               DRM_ERROR("radeon: dpm resume failed\n");
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-       } else {
-               rdev->pm.dpm_enabled = true;
-               radeon_pm_compute_clocks(rdev);
+       if (ret)
+               goto dpm_resume_fail;
+       rdev->pm.dpm_enabled = true;
+       radeon_pm_compute_clocks(rdev);
+       return;
+
+dpm_resume_fail:
+       DRM_ERROR("radeon: dpm resume failed\n");
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
        }
 }
 
@@ -1170,51 +1178,50 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               rdev->pm.dpm_enabled = false;
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-               DRM_ERROR("radeon: dpm initialization failed\n");
-               return ret;
-       }
+       if (ret)
+               goto dpm_failed;
        rdev->pm.dpm_enabled = true;
-       radeon_pm_compute_clocks(rdev);
 
-       if (rdev->pm.num_power_states > 1) {
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               /* XXX: these are noops for dpm but are here for backwards compat */
-               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power profile\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_method);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power method\n");
-
-               if (radeon_debugfs_pm_init(rdev)) {
-                       DRM_ERROR("Failed to register debugfs file for dpm!\n");
-               }
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       /* XXX: these are noops for dpm but are here for backwards compat */
+       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+       if (ret)
+               DRM_ERROR("failed to create device file for power profile\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_method);
+       if (ret)
+               DRM_ERROR("failed to create device file for power method\n");
 
-               DRM_INFO("radeon: dpm initialized\n");
+       if (radeon_debugfs_pm_init(rdev)) {
+               DRM_ERROR("Failed to register debugfs file for dpm!\n");
        }
 
+       DRM_INFO("radeon: dpm initialized\n");
+
        return 0;
+
+dpm_failed:
+       rdev->pm.dpm_enabled = false;
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
+       }
+       DRM_ERROR("radeon: dpm initialization failed\n");
+       return ret;
 }
 
 int radeon_pm_init(struct radeon_device *rdev)
@@ -1228,11 +1235,10 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_RV670:
        case CHIP_RS780:
        case CHIP_RS880:
+       case CHIP_BARTS:
+       case CHIP_TURKS:
+       case CHIP_CAICOS:
        case CHIP_CAYMAN:
-       case CHIP_BONAIRE:
-       case CHIP_KABINI:
-       case CHIP_KAVERI:
-       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1257,15 +1263,16 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_PALM:
        case CHIP_SUMO:
        case CHIP_SUMO2:
-       case CHIP_BARTS:
-       case CHIP_TURKS:
-       case CHIP_CAICOS:
        case CHIP_ARUBA:
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
        case CHIP_VERDE:
        case CHIP_OLAND:
        case CHIP_HAINAN:
+       case CHIP_BONAIRE:
+       case CHIP_KABINI:
+       case CHIP_KAVERI:
+       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1290,6 +1297,18 @@ int radeon_pm_init(struct radeon_device *rdev)
                return radeon_pm_init_old(rdev);
 }
 
+int radeon_pm_late_init(struct radeon_device *rdev)
+{
+       int ret = 0;
+
+       if (rdev->pm.pm_method == PM_METHOD_DPM) {
+               mutex_lock(&rdev->pm.mutex);
+               ret = radeon_dpm_late_enable(rdev);
+               mutex_unlock(&rdev->pm.mutex);
+       }
+       return ret;
+}
+
 static void radeon_pm_fini_old(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states > 1) {
@@ -1420,6 +1439,9 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;
 
+       if (!rdev->pm.dpm_enabled)
+               return;
+
        mutex_lock(&rdev->pm.mutex);
 
        /* update active crtc counts */
@@ -1464,7 +1486,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
         */
        for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
                if (rdev->pm.active_crtcs & (1 << crtc)) {
-                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos, NULL, NULL);
+                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL);
                        if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
                            !(vbl_status & DRM_SCANOUTPOS_INVBL))
                                in_vbl = false;
index 9214403ae173c146573cf8c4441a6a71cf052665..1b783f0e6d3ad084b0a62629a4b5d67c9e92453f 100644 (file)
@@ -332,36 +332,6 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
        }
 }
 
-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring)
-{
-       u32 rptr;
-
-       if (rdev->wb.enabled)
-               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
-       else
-               rptr = RREG32(ring->rptr_reg);
-
-       return rptr;
-}
-
-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring)
-{
-       u32 wptr;
-
-       wptr = RREG32(ring->wptr_reg);
-
-       return wptr;
-}
-
-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
-                                 struct radeon_ring *ring)
-{
-       WREG32(ring->wptr_reg, ring->wptr);
-       (void)RREG32(ring->wptr_reg);
-}
-
 /**
  * radeon_ring_free_size - update the free size
  *
@@ -463,7 +433,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
        while (ring->wptr & ring->align_mask) {
                radeon_ring_write(ring, ring->nop);
        }
-       DRM_MEMORYBARRIER();
+       mb();
        radeon_ring_set_wptr(rdev, ring);
 }
 
@@ -689,22 +659,18 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
  * @ring: radeon_ring structure holding ring information
  * @ring_size: size of the ring
  * @rptr_offs: offset of the rptr writeback location in the WB buffer
- * @rptr_reg: MMIO offset of the rptr register
- * @wptr_reg: MMIO offset of the wptr register
  * @nop: nop packet for this ring
  *
  * Initialize the driver information for the selected ring (all asics).
  * Returns 0 on success, error on failure.
  */
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop)
+                    unsigned rptr_offs, u32 nop)
 {
        int r;
 
        ring->ring_size = ring_size;
        ring->rptr_offs = rptr_offs;
-       ring->rptr_reg = rptr_reg;
-       ring->wptr_reg = wptr_reg;
        ring->nop = nop;
        /* Allocate ring buffer */
        if (ring->ring_obj == NULL) {
@@ -790,34 +756,54 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
        struct radeon_device *rdev = dev->dev_private;
        int ridx = *(int*)node->info_ent->data;
        struct radeon_ring *ring = &rdev->ring[ridx];
+
+       uint32_t rptr, wptr, rptr_next;
        unsigned count, i, j;
-       u32 tmp;
 
        radeon_ring_free_size(rdev, ring);
        count = (ring->ring_size / 4) - ring->ring_free_dw;
-       tmp = radeon_ring_get_wptr(rdev, ring);
-       seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp);
-       tmp = radeon_ring_get_rptr(rdev, ring);
-       seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp);
+
+       wptr = radeon_ring_get_wptr(rdev, ring);
+       seq_printf(m, "wptr: 0x%08x [%5d]\n",
+                  wptr, wptr);
+
+       rptr = radeon_ring_get_rptr(rdev, ring);
+       seq_printf(m, "rptr: 0x%08x [%5d]\n",
+                  rptr, rptr);
+
        if (ring->rptr_save_reg) {
-               seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,
-                          RREG32(ring->rptr_save_reg));
-       }
-       seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
-       seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
-       seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
-       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n", ring->last_semaphore_wait_addr);
+               rptr_next = RREG32(ring->rptr_save_reg);
+               seq_printf(m, "rptr next(0x%04x): 0x%08x [%5d]\n",
+                          ring->rptr_save_reg, rptr_next, rptr_next);
+       } else
+               rptr_next = ~0;
+
+       seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n",
+                  ring->wptr, ring->wptr);
+       seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n",
+                  ring->rptr, ring->rptr);
+       seq_printf(m, "last semaphore signal addr : 0x%016llx\n",
+                  ring->last_semaphore_signal_addr);
+       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n",
+                  ring->last_semaphore_wait_addr);
        seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
        seq_printf(m, "%u dwords in ring\n", count);
+
+       if (!ring->ready)
+               return 0;
+
        /* print 8 dw before current rptr as often it's the last executed
         * packet that is the root issue
         */
-       i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
-       if (ring->ready) {
-               for (j = 0; j <= (count + 32); j++) {
-                       seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
-                       i = (i + 1) & ring->ptr_mask;
-               }
+       i = (rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
+       for (j = 0; j <= (count + 32); j++) {
+               seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]);
+               if (rptr == i)
+                       seq_puts(m, " *");
+               if (rptr_next == i)
+                       seq_puts(m, " #");
+               seq_puts(m, "\n");
+               i = (i + 1) & ring->ptr_mask;
        }
        return 0;
 }
index f0bac68254b79a5dd31cfdc14ce80a98bca91065..c0625805cdd769b826d0605141f6cc80ce80ad72 100644 (file)
@@ -402,13 +402,15 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
 
        spin_lock(&sa_manager->wq.lock);
        list_for_each_entry(i, &sa_manager->olist, olist) {
+               uint64_t soffset = i->soffset + sa_manager->gpu_addr;
+               uint64_t eoffset = i->eoffset + sa_manager->gpu_addr;
                if (&i->olist == sa_manager->hole) {
                        seq_printf(m, ">");
                } else {
                        seq_printf(m, " ");
                }
-               seq_printf(m, "[0x%08x 0x%08x] size %8d",
-                          i->soffset, i->eoffset, i->eoffset - i->soffset);
+               seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
+                          soffset, eoffset, eoffset - soffset);
                if (i->fence) {
                        seq_printf(m, " protected by 0x%016llx on ring %d",
                                   i->fence->seq, i->fence->ring);
index 4d20910899d4c7ed8ad85f29788bfd35cc359fb5..956ab7f14e1650607c8dd09f1b9c96daaee3169a 100644 (file)
@@ -1810,7 +1810,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
                }
                if (!buf) {
                        DRM_DEBUG("EAGAIN\n");
-                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+                       if (copy_to_user(tex->image, image, sizeof(*image)))
                                return -EFAULT;
                        return -EAGAIN;
                }
@@ -1823,7 +1823,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
 
 #define RADEON_COPY_MT(_buf, _data, _width) \
        do { \
-               if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+               if (copy_from_user(_buf, _data, (_width))) {\
                        DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
                        return -EFAULT; \
                } \
@@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
        if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-       if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
+       if (copy_from_user(&depth_boxes, clear->depth_boxes,
                               sarea_priv->nbox * sizeof(depth_boxes[0])))
                return -EFAULT;
 
@@ -2436,7 +2436,7 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file
                return -EINVAL;
        }
 
-       if (DRM_COPY_FROM_USER(&image,
+       if (copy_from_user(&image,
                               (drm_radeon_tex_image_t __user *) tex->image,
                               sizeof(image)))
                return -EFAULT;
@@ -2460,7 +2460,7 @@ static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+       if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
                return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
@@ -2585,13 +2585,13 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
                drm_radeon_prim_t prim;
                drm_radeon_tcl_prim_t tclprim;
 
-               if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
+               if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim)))
                        return -EFAULT;
 
                if (prim.stateidx != laststate) {
                        drm_radeon_state_t state;
 
-                       if (DRM_COPY_FROM_USER(&state,
+                       if (copy_from_user(&state,
                                               &vertex->state[prim.stateidx],
                                               sizeof(state)))
                                return -EFAULT;
@@ -2799,7 +2799,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
 
        do {
                if (i < cmdbuf->nbox) {
-                       if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
+                       if (copy_from_user(&box, &boxes[i], sizeof(box)))
                                return -EFAULT;
                        /* FIXME The second and subsequent times round
                         * this loop, send a WAIT_UNTIL_3D_IDLE before
@@ -3116,7 +3116,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index 71245d6f34a20c0f64a6eff3057eb6d7ae37f388..77f5b0c3edb8d8b1f4835620d626c3981171c7a6 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/swiotlb.h>
+#include <linux/debugfs.h>
 #include "radeon_reg.h"
 #include "radeon.h"
 
 #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
 static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
+static void radeon_ttm_debugfs_fini(struct radeon_device *rdev);
 
 static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
 {
@@ -142,7 +144,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
 #if __OS_HAS_AGP
                if (rdev->flags & RADEON_IS_AGP) {
-                       if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) {
+                       if (!rdev->ddev->agp) {
                                DRM_ERROR("AGP is not enabled for memory type %u\n",
                                          (unsigned)type);
                                return -EINVAL;
@@ -753,6 +755,7 @@ void radeon_ttm_fini(struct radeon_device *rdev)
 
        if (!rdev->mman.initialized)
                return;
+       radeon_ttm_debugfs_fini(rdev);
        if (rdev->stollen_vga_memory) {
                r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
                if (r == 0) {
@@ -832,16 +835,15 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-
-#define RADEON_DEBUGFS_MEM_TYPES 2
-
 #if defined(CONFIG_DEBUG_FS)
+
 static int radeon_mm_dump_table(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *)m->private;
-       struct drm_mm *mm = (struct drm_mm *)node->info_ent->data;
+       unsigned ttm_pl = *(int *)node->info_ent->data;
        struct drm_device *dev = node->minor->dev;
        struct radeon_device *rdev = dev->dev_private;
+       struct drm_mm *mm = (struct drm_mm *)rdev->mman.bdev.man[ttm_pl].priv;
        int ret;
        struct ttm_bo_global *glob = rdev->mman.bdev.glob;
 
@@ -850,46 +852,169 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data)
        spin_unlock(&glob->lru_lock);
        return ret;
 }
+
+static int ttm_pl_vram = TTM_PL_VRAM;
+static int ttm_pl_tt = TTM_PL_TT;
+
+static struct drm_info_list radeon_ttm_debugfs_list[] = {
+       {"radeon_vram_mm", radeon_mm_dump_table, 0, &ttm_pl_vram},
+       {"radeon_gtt_mm", radeon_mm_dump_table, 0, &ttm_pl_tt},
+       {"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL},
+#ifdef CONFIG_SWIOTLB
+       {"ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL}
 #endif
+};
 
-static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+static int radeon_ttm_vram_open(struct inode *inode, struct file *filep)
 {
-#if defined(CONFIG_DEBUG_FS)
-       static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2];
-       static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32];
-       unsigned i;
+       struct radeon_device *rdev = inode->i_private;
+       i_size_write(inode, rdev->mc.mc_vram_size);
+       filep->private_data = inode->i_private;
+       return 0;
+}
 
-       for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
-               if (i == 0)
-                       sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
-               else
-                       sprintf(radeon_mem_types_names[i], "radeon_gtt_mm");
-               radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-               radeon_mem_types_list[i].show = &radeon_mm_dump_table;
-               radeon_mem_types_list[i].driver_features = 0;
-               if (i == 0)
-                       radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv;
-               else
-                       radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv;
+static ssize_t radeon_ttm_vram_read(struct file *f, char __user *buf,
+                                   size_t size, loff_t *pos)
+{
+       struct radeon_device *rdev = f->private_data;
+       ssize_t result = 0;
+       int r;
 
+       if (size & 0x3 || *pos & 0x3)
+               return -EINVAL;
+
+       while (size) {
+               unsigned long flags;
+               uint32_t value;
+
+               if (*pos >= rdev->mc.mc_vram_size)
+                       return result;
+
+               spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+               WREG32(RADEON_MM_INDEX, ((uint32_t)*pos) | 0x80000000);
+               if (rdev->family >= CHIP_CEDAR)
+                       WREG32(EVERGREEN_MM_INDEX_HI, *pos >> 31);
+               value = RREG32(RADEON_MM_DATA);
+               spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+               r = put_user(value, (uint32_t *)buf);
+               if (r)
+                       return r;
+
+               result += 4;
+               buf += 4;
+               *pos += 4;
+               size -= 4;
        }
-       /* Add ttm page pool to debugfs */
-       sprintf(radeon_mem_types_names[i], "ttm_page_pool");
-       radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-       radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs;
-       radeon_mem_types_list[i].driver_features = 0;
-       radeon_mem_types_list[i++].data = NULL;
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl()) {
-               sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool");
-               radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-               radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs;
-               radeon_mem_types_list[i].driver_features = 0;
-               radeon_mem_types_list[i++].data = NULL;
+
+       return result;
+}
+
+static const struct file_operations radeon_ttm_vram_fops = {
+       .owner = THIS_MODULE,
+       .open = radeon_ttm_vram_open,
+       .read = radeon_ttm_vram_read,
+       .llseek = default_llseek
+};
+
+static int radeon_ttm_gtt_open(struct inode *inode, struct file *filep)
+{
+       struct radeon_device *rdev = inode->i_private;
+       i_size_write(inode, rdev->mc.gtt_size);
+       filep->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf,
+                                  size_t size, loff_t *pos)
+{
+       struct radeon_device *rdev = f->private_data;
+       ssize_t result = 0;
+       int r;
+
+       while (size) {
+               loff_t p = *pos / PAGE_SIZE;
+               unsigned off = *pos & ~PAGE_MASK;
+               ssize_t cur_size = min(size, PAGE_SIZE - off);
+               struct page *page;
+               void *ptr;
+
+               if (p >= rdev->gart.num_cpu_pages)
+                       return result;
+
+               page = rdev->gart.pages[p];
+               if (page) {
+                       ptr = kmap(page);
+                       ptr += off;
+
+                       r = copy_to_user(buf, ptr, cur_size);
+                       kunmap(rdev->gart.pages[p]);
+               } else
+                       r = clear_user(buf, cur_size);
+
+               if (r)
+                       return -EFAULT;
+
+               result += cur_size;
+               buf += cur_size;
+               *pos += cur_size;
+               size -= cur_size;
        }
+
+       return result;
+}
+
+static const struct file_operations radeon_ttm_gtt_fops = {
+       .owner = THIS_MODULE,
+       .open = radeon_ttm_gtt_open,
+       .read = radeon_ttm_gtt_read,
+       .llseek = default_llseek
+};
+
 #endif
-       return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i);
 
+static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+       unsigned count;
+
+       struct drm_minor *minor = rdev->ddev->primary;
+       struct dentry *ent, *root = minor->debugfs_root;
+
+       ent = debugfs_create_file("radeon_vram", S_IFREG | S_IRUGO, root,
+                                 rdev, &radeon_ttm_vram_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+       rdev->mman.vram = ent;
+
+       ent = debugfs_create_file("radeon_gtt", S_IFREG | S_IRUGO, root,
+                                 rdev, &radeon_ttm_gtt_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+       rdev->mman.gtt = ent;
+
+       count = ARRAY_SIZE(radeon_ttm_debugfs_list);
+
+#ifdef CONFIG_SWIOTLB
+       if (!swiotlb_nr_tbl())
+               --count;
 #endif
+
+       return radeon_debugfs_add_files(rdev, radeon_ttm_debugfs_list, count);
+#else
+
        return 0;
+#endif
+}
+
+static void radeon_ttm_debugfs_fini(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+
+       debugfs_remove(rdev->mman.vram);
+       rdev->mman.vram = NULL;
+
+       debugfs_remove(rdev->mman.gtt);
+       rdev->mman.gtt = NULL;
+#endif
 }
index 373d088bac66db910291045424e075921d39d202..6781fee1eaadc21a68e50de696dd353be0a3e9e5 100644 (file)
@@ -91,6 +91,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
        case CHIP_VERDE:
        case CHIP_PITCAIRN:
        case CHIP_ARUBA:
+       case CHIP_OLAND:
                fw_name = FIRMWARE_TAHITI;
                break;
 
@@ -473,7 +474,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       if ((start >> 28) != (end >> 28)) {
+       if ((start >> 28) != ((end - 1) >> 28)) {
                DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
                          start, end);
                return -EINVAL;
@@ -778,6 +779,8 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
 
        if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
                if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+                       radeon_uvd_count_handles(rdev, &rdev->pm.dpm.sd,
+                                                &rdev->pm.dpm.hd);
                        radeon_dpm_enable_uvd(rdev, false);
                } else {
                        radeon_set_uvd_clocks(rdev, 0, 0);
index 9566b5940a5ae723f90dfa11427e3f09bac233b3..b5c2369cda2fe28ca043fe91f4fcfe12fc227fc6 100644 (file)
@@ -474,6 +474,8 @@ int rs400_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs400_startup(rdev);
        if (r) {
@@ -484,6 +486,7 @@ int rs400_resume(struct radeon_device *rdev)
 
 int rs400_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -493,6 +496,7 @@ int rs400_suspend(struct radeon_device *rdev)
 
 void rs400_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -560,6 +564,9 @@ int rs400_init(struct radeon_device *rdev)
                return r;
        r300_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs400_startup(rdev);
        if (r) {
index 76cc8d3aafec461d0b41668f25500f2a4753dbc3..fdcde7693032c28cc30008b494fd573fd82e58f3 100644 (file)
@@ -1048,6 +1048,8 @@ int rs600_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs600_startup(rdev);
        if (r) {
@@ -1058,6 +1060,7 @@ int rs600_resume(struct radeon_device *rdev)
 
 int rs600_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -1068,6 +1071,7 @@ int rs600_suspend(struct radeon_device *rdev)
 
 void rs600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
@@ -1136,6 +1140,9 @@ int rs600_init(struct radeon_device *rdev)
                return r;
        rs600_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs600_startup(rdev);
        if (r) {
index e7dab069cccf48a05e19cfd7caf27bd65d38c53d..35950738bd5e449465e0e5062d096e3e8ae9ff0e 100644 (file)
@@ -756,6 +756,8 @@ int rs690_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs690_startup(rdev);
        if (r) {
@@ -766,6 +768,7 @@ int rs690_resume(struct radeon_device *rdev)
 
 int rs690_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -776,6 +779,7 @@ int rs690_suspend(struct radeon_device *rdev)
 
 void rs690_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
@@ -845,6 +849,9 @@ int rs690_init(struct radeon_device *rdev)
                return r;
        rs600_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs690_startup(rdev);
        if (r) {
index 6af8505cf4d2db624ee64811ba4575158d90e974..8512085b0aefe0139c6ffabdc69114510ae3e2f3 100644 (file)
@@ -623,14 +623,6 @@ int rs780_dpm_enable(struct radeon_device *rdev)
        if (pi->gfx_clock_gating)
                r600_gfx_clockgating_enable(rdev, true);
 
-       if (rdev->irq.installed && (rdev->pm.int_thermal_type == THERMAL_TYPE_RV6XX)) {
-               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-       }
-
        return 0;
 }
 
index 5d1c316115efa31ab7b029de44db66e399322e71..98e8138ff77945ecdba447bdcb94310c30dcb1c7 100644 (file)
@@ -586,6 +586,8 @@ int rv515_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r =  rv515_startup(rdev);
        if (r) {
@@ -596,6 +598,7 @@ int rv515_resume(struct radeon_device *rdev)
 
 int rv515_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        rs600_irq_disable(rdev);
@@ -612,6 +615,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
 
 void rv515_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -685,6 +689,9 @@ int rv515_init(struct radeon_device *rdev)
                return r;
        rv515_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rv515_startup(rdev);
        if (r) {
index 26633a0252522051bc5a504357d93bd9b6257c67..bebf31c4d841ccaa07b86d9bae96c7abb5c223be 100644 (file)
@@ -1546,7 +1546,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
 {
        struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
-       int ret;
 
        if (r600_dynamicpm_enabled(rdev))
                return -EINVAL;
@@ -1594,15 +1593,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
        r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, true);
        r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-       }
-
        rv6xx_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        r600_start_dpm(rdev);
index 9f5846743c9e0a26dbcf76662250bfb957f6ced1..18e02889ec7d748791d06ab18e521bfa55cd33ee 100644 (file)
@@ -1123,6 +1123,35 @@ void r700_cp_fini(struct radeon_device *rdev)
        radeon_scratch_free(rdev, ring->rptr_save_reg);
 }
 
+void rv770_set_clk_bypass_mode(struct radeon_device *rdev)
+{
+       u32 tmp, i;
+
+       if (rdev->flags & RADEON_IS_IGP)
+               return;
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp &= SCLK_MUX_SEL_MASK;
+       tmp |= SCLK_MUX_SEL(1) | SCLK_MUX_UPDATE;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CG_SPLL_STATUS) & SPLL_CHG_STATUS)
+                       break;
+               udelay(1);
+       }
+
+       tmp &= ~SCLK_MUX_UPDATE;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       tmp = RREG32(MPLL_CNTL_MODE);
+       if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+               tmp &= ~RV730_MPLL_MCLK_SEL;
+       else
+               tmp &= ~MPLL_MCLK_SEL;
+       WREG32(MPLL_CNTL_MODE, tmp);
+}
+
 /*
  * Core functions
  */
@@ -1665,14 +1694,6 @@ static int rv770_startup(struct radeon_device *rdev)
 
        rv770_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-               r = r600_init_microcode(rdev);
-               if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
-                       return r;
-               }
-       }
-
        if (rdev->flags & RADEON_IS_AGP) {
                rv770_agp_enable(rdev);
        } else {
@@ -1728,14 +1749,12 @@ static int rv770_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -1754,7 +1773,6 @@ static int rv770_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -1792,6 +1810,8 @@ int rv770_resume(struct radeon_device *rdev)
        /* init golden registers */
        rv770_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rv770_startup(rdev);
        if (r) {
@@ -1806,6 +1826,7 @@ int rv770_resume(struct radeon_device *rdev)
 
 int rv770_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_suspend(rdev);
@@ -1876,6 +1897,17 @@ int rv770_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+               r = r600_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -1915,6 +1947,7 @@ int rv770_init(struct radeon_device *rdev)
 
 void rv770_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r700_cp_fini(rdev);
        r600_dma_fini(rdev);
        r600_irq_fini(rdev);
index 374499db20c7e59b55d956b066a30bdc42b4f71f..80c595aba359b53c4f748feae3aeab9d207f5db8 100644 (file)
@@ -1863,8 +1863,8 @@ void rv770_enable_auto_throttle_source(struct radeon_device *rdev,
        }
 }
 
-int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
-                                       int min_temp, int max_temp)
+static int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
+                                              int min_temp, int max_temp)
 {
        int low_temp = 0 * 1000;
        int high_temp = 255 * 1000;
@@ -1966,6 +1966,15 @@ int rv770_dpm_enable(struct radeon_device *rdev)
        if (pi->mg_clock_gating)
                rv770_mg_clock_gating_enable(rdev, true);
 
+       rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       return 0;
+}
+
+int rv770_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                PPSMC_Result result;
@@ -1981,8 +1990,6 @@ int rv770_dpm_enable(struct radeon_device *rdev)
                        DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
        }
 
-       rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
        return 0;
 }
 
@@ -2244,14 +2251,12 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
                pl->vddci = vddci;
        }
 
-       if (rdev->family >= CHIP_BARTS) {
-               if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
-                   ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
-               }
+       if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
+           ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
        }
 }
 
@@ -2531,6 +2536,12 @@ bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
            (rdev->pdev->subsystem_device == 0x1c42))
                switch_limit = 200;
 
+       /* RV770 */
+       /* mclk switching doesn't seem to work reliably on desktop RV770s */
+       if ((rdev->family == CHIP_RV770) &&
+           !(rdev->flags & RADEON_IS_MOBILITY))
+               switch_limit = 0xffffffff; /* disable mclk switching */
+
        if (vblank_time < switch_limit)
                return true;
        else
index 9244effc6b59e2e69c6882b0d4dc35dd2517379c..f776634840c9782bde2e9228007720448aa469d1 100644 (file)
@@ -283,8 +283,4 @@ int rv770_read_smc_soft_register(struct radeon_device *rdev,
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
                                  u16 reg_offset, u32 value);
 
-/* thermal */
-int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
-                                       int min_temp, int max_temp);
-
 #endif
index 1ae277152cc7f0c66f7babbcb0cdfcec5ab04f71..3cf1e2921545f9a980569925088d720e347505d1 100644 (file)
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
+#define        CG_SPLL_STATUS                                  0x60c
+#define                SPLL_CHG_STATUS                         (1 << 1)
 
 #define        SPLL_CNTL_MODE                                  0x610
 #define                SPLL_DIV_SYNC                           (1 << 5)
 
+#define MPLL_CNTL_MODE                                  0x61c
+#       define MPLL_MCLK_SEL                            (1 << 11)
+#       define RV730_MPLL_MCLK_SEL                      (1 << 25)
+
 #define        MPLL_AD_FUNC_CNTL                               0x624
 #define                CLKF(x)                                 ((x) << 0)
 #define                CLKF_MASK                               (0x7f << 0)
index a36736dab5e0694cd5a7b78d6dbb013b484cb8f6..07ce58716e44c4b507358ee54009063c4474a32f 100644 (file)
@@ -80,6 +80,8 @@ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
 extern bool evergreen_is_display_hung(struct radeon_device *rdev);
 static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
                                         bool enable);
+static void si_init_pg(struct radeon_device *rdev);
+static void si_init_cg(struct radeon_device *rdev);
 static void si_fini_pg(struct radeon_device *rdev);
 static void si_fini_cg(struct radeon_device *rdev);
 static void si_rlc_stop(struct radeon_device *rdev);
@@ -1460,7 +1462,7 @@ static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
 };
 
 /* ucode loading */
-static int si_mc_load_microcode(struct radeon_device *rdev)
+int si_mc_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
        u32 running, blackout = 0;
@@ -2811,7 +2813,7 @@ static void si_setup_spi(struct radeon_device *rdev,
 }
 
 static u32 si_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -2825,14 +2827,14 @@ static u32 si_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
 
 static void si_setup_rb(struct radeon_device *rdev,
                        u32 se_num, u32 sh_per_se,
-                       u32 max_rb_num)
+                       u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -2842,19 +2844,21 @@ static void si_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        si_select_se_sh(rdev, i, j);
-                       data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
                }
        }
        si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.si.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                si_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3722,6 +3726,106 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        evergreen_print_gpu_status_regs(rdev);
 }
 
+static void si_set_clk_bypass_mode(struct radeon_device *rdev)
+{
+       u32 tmp, i;
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_BYPASS_EN;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp |= SPLL_CTLREQ_CHG;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS)
+                       break;
+               udelay(1);
+       }
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE);
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       tmp = RREG32(MPLL_CNTL_MODE);
+       tmp &= ~MPLL_MCLK_SEL;
+       WREG32(MPLL_CNTL_MODE, tmp);
+}
+
+static void si_spll_powerdown(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG32(SPLL_CNTL_MODE);
+       tmp |= SPLL_SW_DIR_CONTROL;
+       WREG32(SPLL_CNTL_MODE, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_RESET;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_SLEEP;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(SPLL_CNTL_MODE);
+       tmp &= ~SPLL_SW_DIR_CONTROL;
+       WREG32(SPLL_CNTL_MODE, tmp);
+}
+
+static void si_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* disable cg/pg */
+       si_fini_pg(rdev);
+       si_fini_cg(rdev);
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc, disable cp internal ints */
+       si_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+
+       /* set mclk/sclk to bypass */
+       si_set_clk_bypass_mode(rdev);
+       /* powerdown spll */
+       si_spll_powerdown(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int si_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -3731,10 +3835,17 @@ int si_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        si_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = si_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               si_gpu_pci_config_reset(rdev);
+
+       reset_mask = si_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5210,8 +5321,8 @@ static void si_enable_hdp_ls(struct radeon_device *rdev,
                WREG32(HDP_MEM_POWER_LS, data);
 }
 
-void si_update_cg(struct radeon_device *rdev,
-                 u32 block, bool enable)
+static void si_update_cg(struct radeon_device *rdev,
+                        u32 block, bool enable)
 {
        if (block & RADEON_CG_BLOCK_GFX) {
                si_enable_gui_idle_interrupt(rdev, false);
@@ -5377,6 +5488,9 @@ static void si_init_pg(struct radeon_device *rdev)
                si_init_ao_cu_mask(rdev);
                if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
                        si_init_gfx_cgpg(rdev);
+               } else {
+                       WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
+                       WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
                }
                si_enable_dma_pg(rdev, true);
                si_enable_gfx_cgpg(rdev, true);
@@ -6322,21 +6436,14 @@ static int si_startup(struct radeon_device *rdev)
 
        si_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-           !rdev->rlc_fw || !rdev->mc_fw) {
-               r = si_init_microcode(rdev);
+       if (!rdev->pm.dpm_enabled) {
+               r = si_mc_load_microcode(rdev);
                if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
+                       DRM_ERROR("Failed to load MC firmware!\n");
                        return r;
                }
        }
 
-       r = si_mc_load_microcode(rdev);
-       if (r) {
-               DRM_ERROR("Failed to load MC firmware!\n");
-               return r;
-       }
-
        r = si_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -6419,37 +6526,30 @@ static int si_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
-                            CP_RB1_RPTR, CP_RB1_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
-                            CP_RB2_RPTR, CP_RB2_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
        if (r)
                return r;
@@ -6469,7 +6569,6 @@ static int si_startup(struct radeon_device *rdev)
                ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
                if (ring->ring_size) {
                        r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                            UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                             RADEON_CP_PACKET2);
                        if (!r)
                                r = uvd_v1_0_init(rdev);
@@ -6511,6 +6610,8 @@ int si_resume(struct radeon_device *rdev)
        /* init golden registers */
        si_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = si_startup(rdev);
        if (r) {
@@ -6525,6 +6626,7 @@ int si_resume(struct radeon_device *rdev)
 
 int si_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        dce6_audio_fini(rdev);
        radeon_vm_manager_fini(rdev);
        si_cp_enable(rdev, false);
@@ -6598,6 +6700,18 @@ int si_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+           !rdev->rlc_fw || !rdev->mc_fw) {
+               r = si_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
@@ -6664,6 +6778,7 @@ int si_init(struct radeon_device *rdev)
 
 void si_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        si_cp_fini(rdev);
        cayman_dma_fini(rdev);
        si_fini_pg(rdev);
index 0b00c790fb7713d8b4cbddb91c9b319ecc41c3b9..36a5da4791ce7354aec03a33e670f8bfc8f4484f 100644 (file)
@@ -1738,6 +1738,8 @@ struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 struct ni_power_info *ni_get_pi(struct radeon_device *rdev);
 struct ni_ps *ni_get_ps(struct radeon_ps *rps);
 
+extern int si_mc_load_microcode(struct radeon_device *rdev);
+
 static int si_populate_voltage_value(struct radeon_device *rdev,
                                     const struct atom_voltage_table *table,
                                     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage);
@@ -1753,9 +1755,6 @@ static int si_calculate_sclk_params(struct radeon_device *rdev,
                                    u32 engine_clock,
                                    SISLANDS_SMC_SCLK_VALUE *sclk);
 
-extern void si_update_cg(struct radeon_device *rdev,
-                        u32 block, bool enable);
-
 static struct si_power_info *si_get_pi(struct radeon_device *rdev)
 {
         struct si_power_info *pi = rdev->pm.dpm.priv;
@@ -2396,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev,
        if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
@@ -5414,7 +5413,7 @@ static void si_populate_mc_reg_addresses(struct radeon_device *rdev,
 
        for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {
                if (si_pi->mc_reg_table.valid_flag & (1 << j)) {
-                       if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+                       if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
                                break;
                        mc_reg_table->address[i].s0 =
                                cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);
@@ -5754,6 +5753,11 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
 
 void si_dpm_setup_asic(struct radeon_device *rdev)
 {
+       int r;
+
+       r = si_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        rv770_get_memory_type(rdev);
        si_read_clock_registers(rdev);
        si_enable_acpi_power_management(rdev);
@@ -5791,13 +5795,6 @@ int si_dpm_enable(struct radeon_device *rdev)
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
        int ret;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        if (si_is_smc_running(rdev))
                return -EINVAL;
        if (pi->voltage_control)
@@ -5900,6 +5897,17 @@ int si_dpm_enable(struct radeon_device *rdev)
        si_enable_sclk_control(rdev, true);
        si_start_dpm(rdev);
 
+       si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       ni_update_current_ps(rdev, boot_ps);
+
+       return 0;
+}
+
+int si_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                PPSMC_Result result;
@@ -5915,17 +5923,6 @@ int si_dpm_enable(struct radeon_device *rdev)
                        DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
        }
 
-       si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), true);
-
-       ni_update_current_ps(rdev, boot_ps);
-
        return 0;
 }
 
@@ -5934,13 +5931,6 @@ void si_dpm_disable(struct radeon_device *rdev)
        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        if (!si_is_smc_running(rdev))
                return;
        si_disable_ulv(rdev);
@@ -6005,13 +5995,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = &eg_pi->current_rps;
        int ret;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        ret = si_disable_ulv(rdev);
        if (ret) {
                DRM_ERROR("si_disable_ulv failed\n");
@@ -6104,13 +6087,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
                return ret;
        }
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
index d422a1cbf727b375c467bcf78dc417431c7db2fd..e80efcf0c2306e812b4462ab930464bc03c8c5b5 100644 (file)
@@ -28,6 +28,7 @@
 #include "sid.h"
 #include "ppsmc.h"
 #include "radeon_ucode.h"
+#include "sislands_smc.h"
 
 static int si_set_smc_sram_address(struct radeon_device *rdev,
                                   u32 smc_address, u32 limit)
index b322acc48097f632a0fa1ac3204facc3287912f5..caa3e61a38c25b587537933850317ac5d89e10bf 100644 (file)
@@ -94,6 +94,8 @@
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SPLL_CTLREQ_CHG                         (1 << 23)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
 #define        CG_SPLL_FUNC_CNTL_4                             0x60c
 
+#define        SPLL_STATUS                                     0x614
+#define                SPLL_CHG_STATUS                         (1 << 1)
 #define        SPLL_CNTL_MODE                                  0x618
+#define                SPLL_SW_DIR_CONTROL                     (1 << 0)
 #      define SPLL_REFCLK_SEL(x)                       ((x) << 8)
 #      define SPLL_REFCLK_SEL_MASK                     0xFF00
 
 #       define MRDCK0_BYPASS                            (1 << 24)
 #       define MRDCK1_BYPASS                            (1 << 25)
 
+#define        MPLL_CNTL_MODE                                  0x2bb0
+#       define MPLL_MCLK_SEL                            (1 << 11)
 #define        MPLL_FUNC_CNTL                                  0x2bb4
 #define                BWCTRL(x)                               ((x) << 20)
 #define                BWCTRL_MASK                             (0xff << 20)
index 5578e9837026fec65ac023a71c5ed3400d8d0734..10e945a49479e3e9bb611ec98cb62b409046acf6 100644 (file)
@@ -374,8 +374,6 @@ typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration;
 
 #pragma pack(pop)
 
-int si_set_smc_sram_address(struct radeon_device *rdev,
-                           u32 smc_address, u32 limit);
 int si_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit);
index 96ea6db8bf575e7a45f6af501e26120f7e996a9a..f121efe12dc5c10a4fd6f1c5283ee7f87e8b0797 100644 (file)
@@ -71,7 +71,7 @@ static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] =
        SUMO_DTC_DFLT_14,
 };
 
-struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
+static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
 {
        struct sumo_ps *ps = rps->ps_priv;
 
@@ -1202,14 +1202,10 @@ static void sumo_update_requested_ps(struct radeon_device *rdev,
 int sumo_dpm_enable(struct radeon_device *rdev)
 {
        struct sumo_power_info *pi = sumo_get_pi(rdev);
-       int ret;
 
        if (sumo_dpm_enabled(rdev))
                return -EINVAL;
 
-       ret = sumo_enable_clock_power_gating(rdev);
-       if (ret)
-               return ret;
        sumo_program_bootup_state(rdev);
        sumo_init_bsp(rdev);
        sumo_reset_am(rdev);
@@ -1233,6 +1229,19 @@ int sumo_dpm_enable(struct radeon_device *rdev)
        if (pi->enable_boost)
                sumo_enable_boost_timer(rdev);
 
+       sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return 0;
+}
+
+int sumo_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       ret = sumo_enable_clock_power_gating(rdev);
+       if (ret)
+               return ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1242,8 +1251,6 @@ int sumo_dpm_enable(struct radeon_device *rdev)
                radeon_irq_set(rdev);
        }
 
-       sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
-
        return 0;
 }
 
index 18abba5b5810b467f23efb012b9eee24e5e3a155..fb081d2ae37477e37b0ec28068c7d45112e19bc0 100644 (file)
@@ -31,7 +31,6 @@
 #define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY  27
 #define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20  20
 
-struct sumo_ps *sumo_get_ps(struct radeon_ps *rps);
 struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev);
 
 static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id)
index d700698a1f224bea67bd585061289e56735072e4..2d447192d6f7356b1f37af690e1242932b23d7bf 100644 (file)
@@ -342,14 +342,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
                                             struct radeon_ps *new_rps,
                                             struct radeon_ps *old_rps);
 
-struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
+static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
 {
        struct trinity_ps *ps = rps->ps_priv;
 
        return ps;
 }
 
-struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
+static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
 {
        struct trinity_power_info *pi = rdev->pm.dpm.priv;
 
@@ -1082,7 +1082,6 @@ void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
 int trinity_dpm_enable(struct radeon_device *rdev)
 {
        struct trinity_power_info *pi = trinity_get_pi(rdev);
-       int ret;
 
        trinity_acquire_mutex(rdev);
 
@@ -1091,7 +1090,6 @@ int trinity_dpm_enable(struct radeon_device *rdev)
                return -EINVAL;
        }
 
-       trinity_enable_clock_power_gating(rdev);
        trinity_program_bootup_state(rdev);
        sumo_program_vc(rdev, 0x00C00033);
        trinity_start_am(rdev);
@@ -1105,6 +1103,18 @@ int trinity_dpm_enable(struct radeon_device *rdev)
        trinity_dpm_bapm_enable(rdev, false);
        trinity_release_mutex(rdev);
 
+       trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return 0;
+}
+
+int trinity_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       trinity_acquire_mutex(rdev);
+       trinity_enable_clock_power_gating(rdev);
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1115,8 +1125,7 @@ int trinity_dpm_enable(struct radeon_device *rdev)
                rdev->irq.dpm_thermal = true;
                radeon_irq_set(rdev);
        }
-
-       trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+       trinity_release_mutex(rdev);
 
        return 0;
 }
index 9672bcbc7312218a357f07ae54393ed511284279..99dd0455334d1a433c880565ee84dd60e14989c9 100644 (file)
@@ -27,9 +27,6 @@
 #include "trinity_dpm.h"
 #include "ppsmc.h"
 
-struct trinity_ps *trinity_get_ps(struct radeon_ps *rps);
-struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev);
-
 static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
 {
        int i;
index b19ef4951085b06422aa7b2f8b1f634fba086d87..824550db3fed59e2220953e9e9976b8b28443260 100644 (file)
@@ -153,6 +153,7 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
                chip_id = 0x01000015;
                break;
        case CHIP_PITCAIRN:
+       case CHIP_OLAND:
                chip_id = 0x01000016;
                break;
        case CHIP_ARUBA:
index a9d24e4bf79280c90991c155634c0ca8bd87c1d9..fbf4be316d0b675f89be45db4d820952af079287 100644 (file)
@@ -371,7 +371,6 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
                goto error;
 
        rcrtc->plane->format = format;
-       rcrtc->plane->pitch = crtc->fb->pitches[0];
 
        rcrtc->plane->src_x = x;
        rcrtc->plane->src_y = y;
@@ -413,7 +412,7 @@ static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        rcrtc->plane->src_x = x;
        rcrtc->plane->src_y = y;
 
-       rcar_du_crtc_update_base(to_rcar_crtc(crtc));
+       rcar_du_crtc_update_base(rcrtc);
 
        return 0;
 }
index 0023f9719cf18fda9e2f3232bae5bf178e15de7d..792fd1d20e865df1125294dcfbf626e6a7a16524 100644 (file)
@@ -224,7 +224,9 @@ static int rcar_du_probe(struct platform_device *pdev)
 
 static int rcar_du_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&rcar_du_driver, pdev);
+       struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+
+       drm_put_dev(rcdu->ddev);
 
        return 0;
 }
@@ -249,8 +251,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
-       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B
-                 | RCAR_DU_FEATURE_DEFR8,
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
+       .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
        .num_crtcs = 3,
        .routes = {
                /* R8A7790 has one RGB output, two LVDS outputs and one
@@ -272,9 +274,29 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
        .num_lvds = 2,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7791_info = {
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
+       .num_crtcs = 2,
+       .routes = {
+               /* R8A7791 has one RGB output, one LVDS output and one
+                * (currently unsupported) TCON output.
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(1),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+               },
+               [RCAR_DU_OUTPUT_LVDS0] = {
+                       .possible_crtcs = BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_LVDS,
+               },
+       },
+       .num_lvds = 1,
+};
+
 static const struct platform_device_id rcar_du_id_table[] = {
        { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
        { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
+       { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
        { }
 };
 
index 65d2d636b002d9fbf32fb2c6391b8df4bc63ff03..e31b735d3f258b69b65ab97320ddfe7440d7d6b9 100644 (file)
@@ -28,8 +28,10 @@ struct rcar_du_device;
 struct rcar_du_lvdsenc;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0)        /* Per-CRTC IRQ and clock */
-#define RCAR_DU_FEATURE_ALIGN_128B     (1 << 1)        /* Align pitches to 128 bytes */
-#define RCAR_DU_FEATURE_DEFR8          (1 << 2)        /* Has DEFR8 register */
+#define RCAR_DU_FEATURE_DEFR8          (1 << 1)        /* Has DEFR8 register */
+
+#define RCAR_DU_QUIRK_ALIGN_128B       (1 << 0)        /* Align pitches to 128 bytes */
+#define RCAR_DU_QUIRK_LVDS_LANES       (1 << 1)        /* LVDS lanes 1 and 3 inverted */
 
 /*
  * struct rcar_du_output_routing - Output routing specification
@@ -48,12 +50,14 @@ struct rcar_du_output_routing {
 /*
  * struct rcar_du_device_info - DU model-specific information
  * @features: device features (RCAR_DU_FEATURE_*)
+ * @quirks: device quirks (RCAR_DU_QUIRK_*)
  * @num_crtcs: total number of CRTCs
  * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
        unsigned int features;
+       unsigned int quirks;
        unsigned int num_crtcs;
        struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
        unsigned int num_lvds;
@@ -84,6 +88,12 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu,
        return rcdu->info->features & feature;
 }
 
+static inline bool rcar_du_needs(struct rcar_du_device *rcdu,
+                                unsigned int quirk)
+{
+       return rcdu->info->quirks & quirk;
+}
+
 static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
 {
        return ioread32(rcdu->mmio + reg);
index b31ac080c4a77ba6554ae281d0fd90754e8d633b..fbeabd9a281f9a71c2e283df478fb7e3428a7655 100644 (file)
@@ -119,7 +119,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
        /* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
         * but the R8A7790 DU seems to require a 128 bytes pitch alignment.
         */
-       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+       if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
                align = 128;
        else
                align = 16 * args->bpp / 8;
@@ -144,7 +144,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                return ERR_PTR(-EINVAL);
        }
 
-       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+       if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
                align = 128;
        else
                align = 16 * format->bpp / 8;
index a0f6a17819252b51c0f201861777b8c73fc30ef1..df30a075d793ce5d97c550c80a2f01ce172fbdc1 100644 (file)
@@ -44,6 +44,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
        const struct drm_display_mode *mode = &rcrtc->crtc.mode;
        unsigned int freq = mode->clock;
        u32 lvdcr0;
+       u32 lvdhcr;
        u32 pllcr;
        int ret;
 
@@ -72,15 +73,19 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
         * VSYNC -> CTRL1
         * DISP  -> CTRL2
         * 0     -> CTRL3
-        *
-        * Channels 1 and 3 are switched on ES1.
         */
        rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
                        LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
                        LVDCTRCR_CTR0SEL_HSYNC);
-       rcar_lvds_write(lvds, LVDCHCR,
-                       LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) |
-                       LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1));
+
+       if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
+               lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
+                      | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
+       else
+               lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
+                      | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
+
+       rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
 
        /* Select the input, hardcode mode 0, enable LVDS operation and turn
         * bias circuitry on.
@@ -144,18 +149,9 @@ static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
        sprintf(name, "lvds.%u", lvds->index);
 
        mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-       if (mem == NULL) {
-               dev_err(&pdev->dev, "failed to get memory resource for %s\n",
-                       name);
-               return -EINVAL;
-       }
-
        lvds->mmio = devm_ioremap_resource(&pdev->dev, mem);
-       if (lvds->mmio == NULL) {
-               dev_err(&pdev->dev, "failed to remap memory resource for %s\n",
-                       name);
-               return -ENOMEM;
-       }
+       if (IS_ERR(lvds->mmio))
+               return PTR_ERR(lvds->mmio);
 
        lvds->clock = devm_clk_get(&pdev->dev, name);
        if (IS_ERR(lvds->clock)) {
index 53000644733f29c25a5db1edb5d24e5090bbc666..3fb69d9ae61bd15fdea9e1801a5e0c69a19d13df 100644 (file)
@@ -104,6 +104,15 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
 {
        struct rcar_du_group *rgrp = plane->group;
        unsigned int index = plane->hwindex;
+       u32 mwr;
+
+       /* Memory pitch (expressed in pixels) */
+       if (plane->format->planes == 2)
+               mwr = plane->pitch;
+       else
+               mwr = plane->pitch * 8 / plane->format->bpp;
+
+       rcar_du_plane_write(rgrp, index, PnMWR, mwr);
 
        /* The Y position is expressed in raster line units and must be doubled
         * for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -133,6 +142,8 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
 {
        struct drm_gem_cma_object *gem;
 
+       plane->pitch = fb->pitches[0];
+
        gem = drm_fb_cma_get_gem_obj(fb, 0);
        plane->dma[0] = gem->paddr + fb->offsets[0];
 
@@ -209,7 +220,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
        struct rcar_du_group *rgrp = plane->group;
        u32 ddcr2 = PnDDCR2_CODE;
        u32 ddcr4;
-       u32 mwr;
 
        /* Data format
         *
@@ -240,14 +250,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
        rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
        rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
-       /* Memory pitch (expressed in pixels) */
-       if (plane->format->planes == 2)
-               mwr = plane->pitch;
-       else
-               mwr = plane->pitch * 8 / plane->format->bpp;
-
-       rcar_du_plane_write(rgrp, index, PnMWR, mwr);
-
        /* Destination position and size */
        rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
        rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
@@ -309,7 +311,6 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 
        rplane->crtc = crtc;
        rplane->format = format;
-       rplane->pitch = fb->pitches[0];
 
        rplane->src_x = src_x >> 16;
        rplane->src_y = src_y >> 16;
index b17d0710871abc77487973d837dfe212d17eb5df..d2b2df9e26f3692b51d7495b5197b66ad9d6387b 100644 (file)
@@ -49,7 +49,7 @@ savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
 #endif
 
        for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
+               mb();
                status = dev_priv->status_ptr[0];
                if ((status & mask) < threshold)
                        return 0;
@@ -123,7 +123,7 @@ savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
        int i;
 
        for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
+               mb();
                status = dev_priv->status_ptr[1];
                if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
                    (status & 0xffff) == 0)
@@ -449,7 +449,7 @@ static void savage_dma_flush(drm_savage_private_t * dev_priv)
                }
        }
 
-       DRM_MEMORYBARRIER();
+       mb();
 
        /* do flush ... */
        phys_addr = dev_priv->cmd_dma->offset +
@@ -990,10 +990,10 @@ static int savage_bci_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
+               if (copy_to_user(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+               if (copy_to_user(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
                        return -EFAULT;
 
index b35e75ed890c0384c48130108858d5e2f95297c3..c01ad0aeaa5806dd034910eff873d48a149fdbc5 100644 (file)
@@ -992,7 +992,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                if (kcmd_addr == NULL)
                        return -ENOMEM;
 
-               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
+               if (copy_from_user(kcmd_addr, cmdbuf->cmd_addr,
                                       cmdbuf->size * 8))
                {
                        kfree(kcmd_addr);
@@ -1007,7 +1007,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr,
+               if (copy_from_user(kvb_addr, cmdbuf->vb_addr,
                                       cmdbuf->vb_size)) {
                        ret = -EFAULT;
                        goto done;
@@ -1022,7 +1022,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr,
+               if (copy_from_user(kbox_addr, cmdbuf->box_addr,
                                       cmdbuf->nbox * sizeof(struct drm_clip_rect))) {
                        ret = -EFAULT;
                        goto done;
@@ -1032,7 +1032,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
 
        /* Make sure writes to DMA buffers are finished before sending
         * DMA commands to the graphics hardware. */
-       DRM_MEMORYBARRIER();
+       mb();
 
        /* Coming from user space. Don't know if the Xserver has
         * emitted wait commands. Assuming the worst. */
index 562f9a401cf65996bb5b0fa99982451271537736..0428076f1ce8723d025e64cdea77df33777288b6 100644 (file)
  * Clock management
  */
 
-static void shmob_drm_clk_on(struct shmob_drm_device *sdev)
+static int shmob_drm_clk_on(struct shmob_drm_device *sdev)
 {
-       if (sdev->clock)
-               clk_prepare_enable(sdev->clock);
+       int ret;
+
+       if (sdev->clock) {
+               ret = clk_prepare_enable(sdev->clock);
+               if (ret < 0)
+                       return ret;
+       }
 #if 0
        if (sdev->meram_dev && sdev->meram_dev->pdev)
                pm_runtime_get_sync(&sdev->meram_dev->pdev->dev);
 #endif
+
+       return 0;
 }
 
 static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
@@ -161,6 +168,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
        struct drm_device *dev = sdev->ddev;
        struct drm_plane *plane;
        u32 value;
+       int ret;
 
        if (scrtc->started)
                return;
@@ -170,7 +178,9 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
                return;
 
        /* Enable clocks before accessing the hardware. */
-       shmob_drm_clk_on(sdev);
+       ret = shmob_drm_clk_on(sdev);
+       if (ret < 0)
+               return;
 
        /* Reset and enable the LCDC. */
        lcdc_write(sdev, LDCNT2R, lcdc_read(sdev, LDCNT2R) | LDCNT2R_BR);
index 015551866b4a0d3c6f9912c361993f99c3b548b1..c839c9c89efbf6f4eb4a37cac2fba654435bd1f9 100644 (file)
@@ -336,7 +336,9 @@ static int shmob_drm_probe(struct platform_device *pdev)
 
 static int shmob_drm_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&shmob_drm_driver, pdev);
+       struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
+
+       drm_put_dev(sdev->ddev);
 
        return 0;
 }
index 4383b74a3aa46f480ac3c118e3a113812fdff9de..756f787b71439ac42af2b6a723916207165b2382 100644 (file)
@@ -94,7 +94,7 @@ static int sis_driver_open(struct drm_device *dev, struct drm_file *file)
        return 0;
 }
 
-void sis_driver_postclose(struct drm_device *dev, struct drm_file *file)
+static void sis_driver_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct sis_file_private *file_priv = file->driver_priv;
 
index 01857d836350db00261d96870af2571e2b3e356f..0573be0d293304269f6cd11eb8677002ddf217a6 100644 (file)
@@ -266,7 +266,7 @@ int sis_idle(struct drm_device *dev)
         * because its polling frequency is too low.
         */
 
-       end = jiffies + (DRM_HZ * 3);
+       end = jiffies + (HZ * 3);
 
        for (i = 0; i < 4; ++i) {
                do {
index 8961ba6a34b879246e9b90defc1b129c2ebeea0f..354ddb29231f26e67e6ac9ec3a638358b47923c4 100644 (file)
@@ -1,13 +1,12 @@
 config DRM_TEGRA
-       bool "NVIDIA Tegra DRM"
-       depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
+       tristate "NVIDIA Tegra DRM"
+       depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
        depends on DRM
-       select TEGRA_HOST1X
+       depends on RESET_CONTROLLER
        select DRM_KMS_HELPER
-       select DRM_KMS_FB_HELPER
-       select FB_SYS_FILLRECT
-       select FB_SYS_COPYAREA
-       select FB_SYS_IMAGEBLIT
+       select DRM_MIPI_DSI
+       select DRM_PANEL
+       select TEGRA_HOST1X
        help
          Choose this option if you have an NVIDIA Tegra SoC.
 
@@ -16,6 +15,18 @@ config DRM_TEGRA
 
 if DRM_TEGRA
 
+config DRM_TEGRA_FBDEV
+       bool "Enable legacy fbdev support"
+       select DRM_KMS_FB_HELPER
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       default y
+       help
+         Choose this option if you have a need for the legacy fbdev support.
+         Note that this support also provides the Linux console on top of
+         the Tegra modesetting driver.
+
 config DRM_TEGRA_DEBUG
        bool "NVIDIA Tegra DRM debug support"
        help
index edc76abd58bb3ba6c67ca6782ecb3999224db6c1..8d220afbd85f94c6599a2ec0015c38ee7c87434b 100644 (file)
@@ -9,6 +9,8 @@ tegra-drm-y := \
        output.o \
        rgb.o \
        hdmi.o \
+       mipi-phy.o \
+       dsi.o \
        gr2d.o \
        gr3d.o
 
index 565f8f7b9a4781d0f9d0b33e1b53b2ecbe2b7eda..e38e5967d77bdc4a4c709cd44744887318cb87bf 100644 (file)
@@ -46,7 +46,6 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
        struct drm_device *drm;
        int ret;
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->bus = &drm_host1x_bus;
 
        drm = drm_dev_alloc(driver, &device->dev);
index ae1cb31ead7e4256c32f6ea045395347780a25a8..386f3b4b00940660f72c889e91b8068ad34e9af4 100644 (file)
@@ -8,13 +8,17 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/debugfs.h>
+#include <linux/reset.h>
 
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
 
+struct tegra_dc_soc_info {
+       bool supports_interlacing;
+};
+
 struct tegra_plane {
        struct drm_plane base;
        unsigned int index;
@@ -658,19 +662,12 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
        /* program display mode */
        tegra_dc_set_timings(dc, mode);
 
-       value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
-       tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
-
-       value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
-       value &= ~LVS_OUTPUT_POLARITY_LOW;
-       value &= ~LHS_OUTPUT_POLARITY_LOW;
-       tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
-
-       value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
-               DISP_ORDER_RED_BLUE;
-       tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
-
-       tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
+       /* interlacing isn't supported yet, so disable it */
+       if (dc->soc->supports_interlacing) {
+               value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
+               value &= ~INTERLACE_ENABLE;
+               tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
+       }
 
        value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
        tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
@@ -712,7 +709,7 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
        unsigned long value;
 
        /* hardware initialization */
-       tegra_periph_reset_deassert(dc->clk);
+       reset_control_deassert(dc->rst);
        usleep_range(10000, 20000);
 
        if (dc->pipe)
@@ -735,10 +732,6 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
                PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
 
-       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
-       value |= DISP_CTRL_MODE_C_DISPLAY;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
-
        /* initialize timer */
        value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
                WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
@@ -1167,8 +1160,36 @@ static const struct host1x_client_ops dc_client_ops = {
        .exit = tegra_dc_exit,
 };
 
+static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
+       .supports_interlacing = false,
+};
+
+static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
+       .supports_interlacing = false,
+};
+
+static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
+       .supports_interlacing = true,
+};
+
+static const struct of_device_id tegra_dc_of_match[] = {
+       {
+               .compatible = "nvidia,tegra124-dc",
+               .data = &tegra124_dc_soc_info,
+       }, {
+               .compatible = "nvidia,tegra30-dc",
+               .data = &tegra30_dc_soc_info,
+       }, {
+               .compatible = "nvidia,tegra20-dc",
+               .data = &tegra20_dc_soc_info,
+       }, {
+               /* sentinel */
+       }
+};
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *id;
        struct resource *regs;
        struct tegra_dc *dc;
        int err;
@@ -1177,9 +1198,14 @@ static int tegra_dc_probe(struct platform_device *pdev)
        if (!dc)
                return -ENOMEM;
 
+       id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
+       if (!id)
+               return -ENODEV;
+
        spin_lock_init(&dc->lock);
        INIT_LIST_HEAD(&dc->list);
        dc->dev = &pdev->dev;
+       dc->soc = id->data;
 
        dc->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dc->clk)) {
@@ -1187,6 +1213,12 @@ static int tegra_dc_probe(struct platform_device *pdev)
                return PTR_ERR(dc->clk);
        }
 
+       dc->rst = devm_reset_control_get(&pdev->dev, "dc");
+       if (IS_ERR(dc->rst)) {
+               dev_err(&pdev->dev, "failed to get reset\n");
+               return PTR_ERR(dc->rst);
+       }
+
        err = clk_prepare_enable(dc->clk);
        if (err < 0)
                return err;
@@ -1247,12 +1279,6 @@ static int tegra_dc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_dc_of_match[] = {
-       { .compatible = "nvidia,tegra30-dc", },
-       { .compatible = "nvidia,tegra20-dc", },
-       { },
-};
-
 struct platform_driver tegra_dc_driver = {
        .driver = {
                .name = "tegra-dc",
index 91bbda291470c29ce3ba80a70b0e5d541b8c6556..3c2c0ea1cd87a84e1f3414a780788d868f676703 100644 (file)
@@ -28,6 +28,7 @@
 #define DISP_CTRL_MODE_STOP (0 << 5)
 #define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
 #define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
+#define DISP_CTRL_MODE_MASK (3 << 5)
 #define DC_CMD_SIGNAL_RAISE                    0x033
 #define DC_CMD_DISPLAY_POWER_CONTROL           0x036
 #define PW0_ENABLE (1 <<  0)
 
 #define DC_DISP_DISP_WIN_OPTIONS               0x402
 #define HDMI_ENABLE (1 << 30)
+#define DSI_ENABLE  (1 << 29)
 
 #define DC_DISP_DISP_MEM_HIGH_PRIORITY         0x403
 #define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
 #define DITHER_CONTROL_ERRDIFF (3 << 8)
 
 #define DC_DISP_SHIFT_CLOCK_OPTIONS            0x431
+#define  SC1_H_QUALIFIER_NONE  (1 << 16)
+#define  SC0_H_QUALIFIER_NONE  (1 <<  0)
 
 #define DC_DISP_DATA_ENABLE_OPTIONS            0x432
 #define DE_SELECT_ACTIVE_BLANK  (0 << 0)
 #define DC_DISP_SD_HW_K_VALUES                 0x4dd
 #define DC_DISP_SD_MAN_K_VALUES                        0x4de
 
+#define DC_DISP_INTERLACE_CONTROL              0x4e5
+#define  INTERLACE_STATUS (1 << 2)
+#define  INTERLACE_START  (1 << 1)
+#define  INTERLACE_ENABLE (1 << 0)
+
 #define DC_WIN_CSC_YOF                         0x611
 #define DC_WIN_CSC_KYRGB                       0x612
 #define DC_WIN_CSC_KUR                         0x613
index 07eba596d458d22b63bc9f0a731d6ca3befae036..88a529008ce0e59210e917422b2cfe07570a0d7d 100644 (file)
@@ -104,9 +104,11 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
 
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
+#ifdef CONFIG_TEGRA_DRM_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
 
        tegra_fbdev_restore_mode(tegra->fbdev);
+#endif
 }
 
 static struct host1x_bo *
@@ -578,7 +580,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
 #endif
 
 static struct drm_driver tegra_drm_driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
        .open = tegra_drm_open,
@@ -596,6 +598,12 @@ static struct drm_driver tegra_drm_driver = {
 
        .gem_free_object = tegra_bo_free_object,
        .gem_vm_ops = &tegra_bo_vm_ops,
+
+       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+       .gem_prime_export = tegra_gem_prime_export,
+       .gem_prime_import = tegra_gem_prime_import,
+
        .dumb_create = tegra_bo_dumb_create,
        .dumb_map_offset = tegra_bo_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,
@@ -653,8 +661,10 @@ static const struct of_device_id host1x_drm_subdevs[] = {
        { .compatible = "nvidia,tegra30-hdmi", },
        { .compatible = "nvidia,tegra30-gr2d", },
        { .compatible = "nvidia,tegra30-gr3d", },
+       { .compatible = "nvidia,tegra114-dsi", },
        { .compatible = "nvidia,tegra114-hdmi", },
        { .compatible = "nvidia,tegra114-gr3d", },
+       { .compatible = "nvidia,tegra124-dc", },
        { /* sentinel */ }
 };
 
@@ -677,10 +687,14 @@ static int __init host1x_drm_init(void)
        if (err < 0)
                goto unregister_host1x;
 
-       err = platform_driver_register(&tegra_hdmi_driver);
+       err = platform_driver_register(&tegra_dsi_driver);
        if (err < 0)
                goto unregister_dc;
 
+       err = platform_driver_register(&tegra_hdmi_driver);
+       if (err < 0)
+               goto unregister_dsi;
+
        err = platform_driver_register(&tegra_gr2d_driver);
        if (err < 0)
                goto unregister_hdmi;
@@ -695,6 +709,8 @@ unregister_gr2d:
        platform_driver_unregister(&tegra_gr2d_driver);
 unregister_hdmi:
        platform_driver_unregister(&tegra_hdmi_driver);
+unregister_dsi:
+       platform_driver_unregister(&tegra_dsi_driver);
 unregister_dc:
        platform_driver_unregister(&tegra_dc_driver);
 unregister_host1x:
@@ -708,6 +724,7 @@ static void __exit host1x_drm_exit(void)
        platform_driver_unregister(&tegra_gr3d_driver);
        platform_driver_unregister(&tegra_gr2d_driver);
        platform_driver_unregister(&tegra_hdmi_driver);
+       platform_driver_unregister(&tegra_dsi_driver);
        platform_driver_unregister(&tegra_dc_driver);
        host1x_driver_unregister(&host1x_drm_driver);
 }
index 7da0b923131f05ca5f67fb8113f2fd9754023a15..bf1cac7658f8d20333ce0cefbac8383e62f98c37 100644 (file)
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fixed.h>
 
+struct reset_control;
+
 struct tegra_fb {
        struct drm_framebuffer base;
        struct tegra_bo **planes;
        unsigned int num_planes;
 };
 
+#ifdef CONFIG_DRM_TEGRA_FBDEV
 struct tegra_fbdev {
        struct drm_fb_helper base;
        struct tegra_fb *fb;
 };
+#endif
 
 struct tegra_drm {
        struct drm_device *drm;
@@ -36,7 +40,9 @@ struct tegra_drm {
        struct mutex clients_lock;
        struct list_head clients;
 
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_fbdev *fbdev;
+#endif
 };
 
 struct tegra_drm_client;
@@ -82,6 +88,7 @@ extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
 extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 extern int tegra_drm_exit(struct tegra_drm *tegra);
 
+struct tegra_dc_soc_info;
 struct tegra_output;
 
 struct tegra_dc {
@@ -93,6 +100,7 @@ struct tegra_dc {
        int pipe;
 
        struct clk *clk;
+       struct reset_control *rst;
        void __iomem *regs;
        int irq;
 
@@ -106,6 +114,8 @@ struct tegra_dc {
 
        /* page-flip handling */
        struct drm_pending_vblank_event *event;
+
+       const struct tegra_dc_soc_info *soc;
 };
 
 static inline struct tegra_dc *
@@ -174,6 +184,7 @@ struct tegra_output_ops {
 enum tegra_output_type {
        TEGRA_OUTPUT_RGB,
        TEGRA_OUTPUT_HDMI,
+       TEGRA_OUTPUT_DSI,
 };
 
 struct tegra_output {
@@ -183,6 +194,7 @@ struct tegra_output {
        const struct tegra_output_ops *ops;
        enum tegra_output_type type;
 
+       struct drm_panel *panel;
        struct i2c_adapter *ddc;
        const struct edid *edid;
        unsigned int hpd_irq;
@@ -260,9 +272,12 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
 bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
 extern int tegra_drm_fb_init(struct drm_device *drm);
 extern void tegra_drm_fb_exit(struct drm_device *drm);
+#ifdef CONFIG_DRM_TEGRA_FBDEV
 extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
+#endif
 
 extern struct platform_driver tegra_dc_driver;
+extern struct platform_driver tegra_dsi_driver;
 extern struct platform_driver tegra_hdmi_driver;
 extern struct platform_driver tegra_gr2d_driver;
 extern struct platform_driver tegra_gr3d_driver;
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
new file mode 100644 (file)
index 0000000..d452faa
--- /dev/null
@@ -0,0 +1,971 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/host1x.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+#include "dc.h"
+#include "drm.h"
+#include "dsi.h"
+#include "mipi-phy.h"
+
+#define DSI_VIDEO_FIFO_DEPTH (1920 / 4)
+#define DSI_HOST_FIFO_DEPTH 64
+
+struct tegra_dsi {
+       struct host1x_client client;
+       struct tegra_output output;
+       struct device *dev;
+
+       void __iomem *regs;
+
+       struct reset_control *rst;
+       struct clk *clk_parent;
+       struct clk *clk_lp;
+       struct clk *clk;
+
+       struct drm_info_list *debugfs_files;
+       struct drm_minor *minor;
+       struct dentry *debugfs;
+
+       enum mipi_dsi_pixel_format format;
+       unsigned int lanes;
+
+       struct tegra_mipi_device *mipi;
+       struct mipi_dsi_host host;
+};
+
+static inline struct tegra_dsi *
+host1x_client_to_dsi(struct host1x_client *client)
+{
+       return container_of(client, struct tegra_dsi, client);
+}
+
+static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host)
+{
+       return container_of(host, struct tegra_dsi, host);
+}
+
+static inline struct tegra_dsi *to_dsi(struct tegra_output *output)
+{
+       return container_of(output, struct tegra_dsi, output);
+}
+
+static inline unsigned long tegra_dsi_readl(struct tegra_dsi *dsi,
+                                           unsigned long reg)
+{
+       return readl(dsi->regs + (reg << 2));
+}
+
+static inline void tegra_dsi_writel(struct tegra_dsi *dsi, unsigned long value,
+                                   unsigned long reg)
+{
+       writel(value, dsi->regs + (reg << 2));
+}
+
+static int tegra_dsi_show_regs(struct seq_file *s, void *data)
+{
+       struct drm_info_node *node = s->private;
+       struct tegra_dsi *dsi = node->info_ent->data;
+
+#define DUMP_REG(name)                                         \
+       seq_printf(s, "%-32s %#05x %08lx\n", #name, name,       \
+                  tegra_dsi_readl(dsi, name))
+
+       DUMP_REG(DSI_INCR_SYNCPT);
+       DUMP_REG(DSI_INCR_SYNCPT_CONTROL);
+       DUMP_REG(DSI_INCR_SYNCPT_ERROR);
+       DUMP_REG(DSI_CTXSW);
+       DUMP_REG(DSI_RD_DATA);
+       DUMP_REG(DSI_WR_DATA);
+       DUMP_REG(DSI_POWER_CONTROL);
+       DUMP_REG(DSI_INT_ENABLE);
+       DUMP_REG(DSI_INT_STATUS);
+       DUMP_REG(DSI_INT_MASK);
+       DUMP_REG(DSI_HOST_CONTROL);
+       DUMP_REG(DSI_CONTROL);
+       DUMP_REG(DSI_SOL_DELAY);
+       DUMP_REG(DSI_MAX_THRESHOLD);
+       DUMP_REG(DSI_TRIGGER);
+       DUMP_REG(DSI_TX_CRC);
+       DUMP_REG(DSI_STATUS);
+
+       DUMP_REG(DSI_INIT_SEQ_CONTROL);
+       DUMP_REG(DSI_INIT_SEQ_DATA_0);
+       DUMP_REG(DSI_INIT_SEQ_DATA_1);
+       DUMP_REG(DSI_INIT_SEQ_DATA_2);
+       DUMP_REG(DSI_INIT_SEQ_DATA_3);
+       DUMP_REG(DSI_INIT_SEQ_DATA_4);
+       DUMP_REG(DSI_INIT_SEQ_DATA_5);
+       DUMP_REG(DSI_INIT_SEQ_DATA_6);
+       DUMP_REG(DSI_INIT_SEQ_DATA_7);
+
+       DUMP_REG(DSI_PKT_SEQ_0_LO);
+       DUMP_REG(DSI_PKT_SEQ_0_HI);
+       DUMP_REG(DSI_PKT_SEQ_1_LO);
+       DUMP_REG(DSI_PKT_SEQ_1_HI);
+       DUMP_REG(DSI_PKT_SEQ_2_LO);
+       DUMP_REG(DSI_PKT_SEQ_2_HI);
+       DUMP_REG(DSI_PKT_SEQ_3_LO);
+       DUMP_REG(DSI_PKT_SEQ_3_HI);
+       DUMP_REG(DSI_PKT_SEQ_4_LO);
+       DUMP_REG(DSI_PKT_SEQ_4_HI);
+       DUMP_REG(DSI_PKT_SEQ_5_LO);
+       DUMP_REG(DSI_PKT_SEQ_5_HI);
+
+       DUMP_REG(DSI_DCS_CMDS);
+
+       DUMP_REG(DSI_PKT_LEN_0_1);
+       DUMP_REG(DSI_PKT_LEN_2_3);
+       DUMP_REG(DSI_PKT_LEN_4_5);
+       DUMP_REG(DSI_PKT_LEN_6_7);
+
+       DUMP_REG(DSI_PHY_TIMING_0);
+       DUMP_REG(DSI_PHY_TIMING_1);
+       DUMP_REG(DSI_PHY_TIMING_2);
+       DUMP_REG(DSI_BTA_TIMING);
+
+       DUMP_REG(DSI_TIMEOUT_0);
+       DUMP_REG(DSI_TIMEOUT_1);
+       DUMP_REG(DSI_TO_TALLY);
+
+       DUMP_REG(DSI_PAD_CONTROL_0);
+       DUMP_REG(DSI_PAD_CONTROL_CD);
+       DUMP_REG(DSI_PAD_CD_STATUS);
+       DUMP_REG(DSI_VIDEO_MODE_CONTROL);
+       DUMP_REG(DSI_PAD_CONTROL_1);
+       DUMP_REG(DSI_PAD_CONTROL_2);
+       DUMP_REG(DSI_PAD_CONTROL_3);
+       DUMP_REG(DSI_PAD_CONTROL_4);
+
+       DUMP_REG(DSI_GANGED_MODE_CONTROL);
+       DUMP_REG(DSI_GANGED_MODE_START);
+       DUMP_REG(DSI_GANGED_MODE_SIZE);
+
+       DUMP_REG(DSI_RAW_DATA_BYTE_COUNT);
+       DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL);
+
+       DUMP_REG(DSI_INIT_SEQ_DATA_8);
+       DUMP_REG(DSI_INIT_SEQ_DATA_9);
+       DUMP_REG(DSI_INIT_SEQ_DATA_10);
+       DUMP_REG(DSI_INIT_SEQ_DATA_11);
+       DUMP_REG(DSI_INIT_SEQ_DATA_12);
+       DUMP_REG(DSI_INIT_SEQ_DATA_13);
+       DUMP_REG(DSI_INIT_SEQ_DATA_14);
+       DUMP_REG(DSI_INIT_SEQ_DATA_15);
+
+#undef DUMP_REG
+
+       return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+       { "regs", tegra_dsi_show_regs, 0, NULL },
+};
+
+static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi,
+                                 struct drm_minor *minor)
+{
+       const char *name = dev_name(dsi->dev);
+       unsigned int i;
+       int err;
+
+       dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root);
+       if (!dsi->debugfs)
+               return -ENOMEM;
+
+       dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+                                    GFP_KERNEL);
+       if (!dsi->debugfs_files) {
+               err = -ENOMEM;
+               goto remove;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+               dsi->debugfs_files[i].data = dsi;
+
+       err = drm_debugfs_create_files(dsi->debugfs_files,
+                                      ARRAY_SIZE(debugfs_files),
+                                      dsi->debugfs, minor);
+       if (err < 0)
+               goto free;
+
+       dsi->minor = minor;
+
+       return 0;
+
+free:
+       kfree(dsi->debugfs_files);
+       dsi->debugfs_files = NULL;
+remove:
+       debugfs_remove(dsi->debugfs);
+       dsi->debugfs = NULL;
+
+       return err;
+}
+
+static int tegra_dsi_debugfs_exit(struct tegra_dsi *dsi)
+{
+       drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files),
+                                dsi->minor);
+       dsi->minor = NULL;
+
+       kfree(dsi->debugfs_files);
+       dsi->debugfs_files = NULL;
+
+       debugfs_remove(dsi->debugfs);
+       dsi->debugfs = NULL;
+
+       return 0;
+}
+
+#define PKT_ID0(id)    ((((id) & 0x3f) <<  3) | (1 <<  9))
+#define PKT_LEN0(len)  (((len) & 0x07) <<  0)
+#define PKT_ID1(id)    ((((id) & 0x3f) << 13) | (1 << 19))
+#define PKT_LEN1(len)  (((len) & 0x07) << 10)
+#define PKT_ID2(id)    ((((id) & 0x3f) << 23) | (1 << 29))
+#define PKT_LEN2(len)  (((len) & 0x07) << 20)
+
+#define PKT_LP         (1 << 30)
+#define NUM_PKT_SEQ    12
+
+/* non-burst mode with sync-end */
+static const u32 pkt_seq_vnb_syne[NUM_PKT_SEQ] = {
+       [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+              PKT_LP,
+       [ 1] = 0,
+       [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+              PKT_LP,
+       [ 3] = 0,
+       [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+              PKT_LP,
+       [ 5] = 0,
+       [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
+       [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
+              PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
+              PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
+       [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+              PKT_LP,
+       [ 9] = 0,
+       [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+              PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+              PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
+       [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
+              PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
+              PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
+};
+
+static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
+{
+       struct mipi_dphy_timing timing;
+       unsigned long value, period;
+       long rate;
+       int err;
+
+       rate = clk_get_rate(dsi->clk);
+       if (rate < 0)
+               return rate;
+
+       period = DIV_ROUND_CLOSEST(1000000000UL, rate * 2);
+
+       err = mipi_dphy_timing_get_default(&timing, period);
+       if (err < 0)
+               return err;
+
+       err = mipi_dphy_timing_validate(&timing, period);
+       if (err < 0) {
+               dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
+               return err;
+       }
+
+       /*
+        * The D-PHY timing fields below are expressed in byte-clock cycles,
+        * so multiply the period by 8.
+        */
+       period *= 8;
+
+       value = DSI_TIMING_FIELD(timing.hsexit, period, 1) << 24 |
+               DSI_TIMING_FIELD(timing.hstrail, period, 0) << 16 |
+               DSI_TIMING_FIELD(timing.hszero, period, 3) << 8 |
+               DSI_TIMING_FIELD(timing.hsprepare, period, 1);
+       tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
+
+       value = DSI_TIMING_FIELD(timing.clktrail, period, 1) << 24 |
+               DSI_TIMING_FIELD(timing.clkpost, period, 1) << 16 |
+               DSI_TIMING_FIELD(timing.clkzero, period, 1) << 8 |
+               DSI_TIMING_FIELD(timing.lpx, period, 1);
+       tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
+
+       value = DSI_TIMING_FIELD(timing.clkprepare, period, 1) << 16 |
+               DSI_TIMING_FIELD(timing.clkpre, period, 1) << 8 |
+               DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
+       tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
+
+       value = DSI_TIMING_FIELD(timing.taget, period, 1) << 16 |
+               DSI_TIMING_FIELD(timing.tasure, period, 1) << 8 |
+               DSI_TIMING_FIELD(timing.tago, period, 1);
+       tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
+
+       return 0;
+}
+
+static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
+                               unsigned int *mulp, unsigned int *divp)
+{
+       switch (format) {
+       case MIPI_DSI_FMT_RGB666_PACKED:
+       case MIPI_DSI_FMT_RGB888:
+               *mulp = 3;
+               *divp = 1;
+               break;
+
+       case MIPI_DSI_FMT_RGB565:
+               *mulp = 2;
+               *divp = 1;
+               break;
+
+       case MIPI_DSI_FMT_RGB666:
+               *mulp = 9;
+               *divp = 4;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int tegra_output_dsi_enable(struct tegra_output *output)
+{
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct drm_display_mode *mode = &dc->base.mode;
+       unsigned int hact, hsw, hbp, hfp, i, mul, div;
+       struct tegra_dsi *dsi = to_dsi(output);
+       /* FIXME: don't hardcode this */
+       const u32 *pkt_seq = pkt_seq_vnb_syne;
+       unsigned long value;
+       int err;
+
+       err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
+       if (err < 0)
+               return err;
+
+       err = clk_enable(dsi->clk);
+       if (err < 0)
+               return err;
+
+       reset_control_deassert(dsi->rst);
+
+       value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(dsi->format) |
+               DSI_CONTROL_LANES(dsi->lanes - 1) |
+               DSI_CONTROL_SOURCE(dc->pipe);
+       tegra_dsi_writel(dsi, value, DSI_CONTROL);
+
+       tegra_dsi_writel(dsi, DSI_VIDEO_FIFO_DEPTH, DSI_MAX_THRESHOLD);
+
+       value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS |
+               DSI_HOST_CONTROL_ECC;
+       tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
+
+       value = tegra_dsi_readl(dsi, DSI_CONTROL);
+       value |= DSI_CONTROL_HS_CLK_CTRL;
+       value &= ~DSI_CONTROL_TX_TRIG(3);
+       value &= ~DSI_CONTROL_DCS_ENABLE;
+       value |= DSI_CONTROL_VIDEO_ENABLE;
+       value &= ~DSI_CONTROL_HOST_ENABLE;
+       tegra_dsi_writel(dsi, value, DSI_CONTROL);
+
+       err = tegra_dsi_set_phy_timing(dsi);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < NUM_PKT_SEQ; i++)
+               tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
+
+       /* horizontal active pixels */
+       hact = mode->hdisplay * mul / div;
+
+       /* horizontal sync width */
+       hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
+       hsw -= 10;
+
+       /* horizontal back porch */
+       hbp = (mode->htotal - mode->hsync_end) * mul / div;
+       hbp -= 14;
+
+       /* horizontal front porch */
+       hfp = (mode->hsync_start  - mode->hdisplay) * mul / div;
+       hfp -= 8;
+
+       tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
+       tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
+       tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
+       tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
+
+       /* set SOL delay */
+       tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
+
+       /* enable display controller */
+       value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+       value |= DSI_ENABLE;
+       tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+       value &= ~DISP_CTRL_MODE_MASK;
+       value |= DISP_CTRL_MODE_C_DISPLAY;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+       value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+       /* enable DSI controller */
+       value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
+       value |= DSI_POWER_CONTROL_ENABLE;
+       tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
+
+       return 0;
+}
+
+static int tegra_output_dsi_disable(struct tegra_output *output)
+{
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_dsi *dsi = to_dsi(output);
+       unsigned long value;
+
+       /* disable DSI controller */
+       value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
+       value &= DSI_POWER_CONTROL_ENABLE;
+       tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
+
+       /*
+        * The following accesses registers of the display controller, so make
+        * sure it's only executed when the output is attached to one.
+        */
+       if (dc) {
+               value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+               value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                          PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
+               tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+               value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+               value &= ~DISP_CTRL_MODE_MASK;
+               tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+               value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+               value &= ~DSI_ENABLE;
+               tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+               tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+               tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+       }
+
+       clk_disable(dsi->clk);
+
+       return 0;
+}
+
+static int tegra_output_dsi_setup_clock(struct tegra_output *output,
+                                       struct clk *clk, unsigned long pclk)
+{
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct drm_display_mode *mode = &dc->base.mode;
+       unsigned int timeout, mul, div, vrefresh;
+       struct tegra_dsi *dsi = to_dsi(output);
+       unsigned long bclk, plld, value;
+       struct clk *base;
+       int err;
+
+       err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
+       if (err < 0)
+               return err;
+
+       vrefresh = drm_mode_vrefresh(mode);
+
+       pclk = mode->htotal * mode->vtotal * vrefresh;
+       bclk = (pclk * mul) / (div * dsi->lanes);
+       plld = DIV_ROUND_UP(bclk * 8, 1000000);
+       pclk = (plld * 1000000) / 2;
+
+       err = clk_set_parent(clk, dsi->clk_parent);
+       if (err < 0) {
+               dev_err(dsi->dev, "failed to set parent clock: %d\n", err);
+               return err;
+       }
+
+       base = clk_get_parent(dsi->clk_parent);
+
+       /*
+        * This assumes that the parent clock is pll_d_out0 or pll_d2_out
+        * respectively, each of which divides the base pll_d by 2.
+        */
+       err = clk_set_rate(base, pclk * 2);
+       if (err < 0) {
+               dev_err(dsi->dev, "failed to set base clock rate to %lu Hz\n",
+                       pclk * 2);
+               return err;
+       }
+
+       /*
+        * XXX: Move the below somewhere else so that we don't need to have
+        * access to the vrefresh in this function?
+        */
+
+       /* one frame high-speed transmission timeout */
+       timeout = (bclk / vrefresh) / 512;
+       value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
+       tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
+
+       /* 2 ms peripheral timeout for panel */
+       timeout = 2 * bclk / 512 * 1000;
+       value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
+       tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
+
+       value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
+       tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
+
+       return 0;
+}
+
+static int tegra_output_dsi_check_mode(struct tegra_output *output,
+                                      struct drm_display_mode *mode,
+                                      enum drm_mode_status *status)
+{
+       /*
+        * FIXME: For now, always assume that the mode is okay.
+        */
+
+       *status = MODE_OK;
+
+       return 0;
+}
+
+static const struct tegra_output_ops dsi_ops = {
+       .enable = tegra_output_dsi_enable,
+       .disable = tegra_output_dsi_disable,
+       .setup_clock = tegra_output_dsi_setup_clock,
+       .check_mode = tegra_output_dsi_check_mode,
+};
+
+static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
+{
+       unsigned long value;
+
+       value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
+       tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+
+       return 0;
+}
+
+static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
+{
+       unsigned long value;
+
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
+
+       /* start calibration */
+       tegra_dsi_pad_enable(dsi);
+
+       value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
+               DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
+               DSI_PAD_OUT_CLK(0x0);
+       tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
+
+       return tegra_mipi_calibrate(dsi->mipi);
+}
+
+static int tegra_dsi_init(struct host1x_client *client)
+{
+       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+       struct tegra_dsi *dsi = host1x_client_to_dsi(client);
+       unsigned long value, i;
+       int err;
+
+       dsi->output.type = TEGRA_OUTPUT_DSI;
+       dsi->output.dev = client->dev;
+       dsi->output.ops = &dsi_ops;
+
+       err = tegra_output_init(tegra->drm, &dsi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output setup failed: %d\n", err);
+               return err;
+       }
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_dsi_debugfs_init(dsi, tegra->drm->primary);
+               if (err < 0)
+                       dev_err(dsi->dev, "debugfs setup failed: %d\n", err);
+       }
+
+       /*
+        * enable high-speed mode, checksum generation, ECC generation and
+        * disable raw mode
+        */
+       value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
+       value |= DSI_HOST_CONTROL_ECC | DSI_HOST_CONTROL_CS |
+                DSI_HOST_CONTROL_HS;
+       value &= ~DSI_HOST_CONTROL_RAW;
+       tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
+
+       tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY);
+       tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD);
+
+       tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL);
+
+       for (i = 0; i < 8; i++) {
+               tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i);
+               tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i);
+       }
+
+       for (i = 0; i < 12; i++)
+               tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i);
+
+       tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS);
+
+       err = tegra_dsi_pad_calibrate(dsi);
+       if (err < 0) {
+               dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
+               return err;
+       }
+
+       tegra_dsi_writel(dsi, DSI_POWER_CONTROL_ENABLE, DSI_POWER_CONTROL);
+       usleep_range(300, 1000);
+
+       return 0;
+}
+
+static int tegra_dsi_exit(struct host1x_client *client)
+{
+       struct tegra_dsi *dsi = host1x_client_to_dsi(client);
+       int err;
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_dsi_debugfs_exit(dsi);
+               if (err < 0)
+                       dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err);
+       }
+
+       err = tegra_output_disable(&dsi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output failed to disable: %d\n", err);
+               return err;
+       }
+
+       err = tegra_output_exit(&dsi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output cleanup failed: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct host1x_client_ops dsi_client_ops = {
+       .init = tegra_dsi_init,
+       .exit = tegra_dsi_exit,
+};
+
+static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
+{
+       struct clk *parent;
+       int err;
+
+       parent = clk_get_parent(dsi->clk);
+       if (!parent)
+               return -EINVAL;
+
+       err = clk_set_parent(parent, dsi->clk_parent);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static void tegra_dsi_initialize(struct tegra_dsi *dsi)
+{
+       unsigned int i;
+
+       tegra_dsi_writel(dsi, 0, DSI_POWER_CONTROL);
+
+       tegra_dsi_writel(dsi, 0, DSI_INT_ENABLE);
+       tegra_dsi_writel(dsi, 0, DSI_INT_STATUS);
+       tegra_dsi_writel(dsi, 0, DSI_INT_MASK);
+
+       tegra_dsi_writel(dsi, 0, DSI_HOST_CONTROL);
+       tegra_dsi_writel(dsi, 0, DSI_CONTROL);
+
+       tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY);
+       tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD);
+
+       tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL);
+
+       for (i = 0; i < 8; i++) {
+               tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i);
+               tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i);
+       }
+
+       for (i = 0; i < 12; i++)
+               tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i);
+
+       tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS);
+
+       for (i = 0; i < 4; i++)
+               tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1 + i);
+
+       tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_0);
+       tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_1);
+       tegra_dsi_writel(dsi, 0x000000ff, DSI_PHY_TIMING_2);
+       tegra_dsi_writel(dsi, 0x00000000, DSI_BTA_TIMING);
+
+       tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_0);
+       tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_1);
+       tegra_dsi_writel(dsi, 0, DSI_TO_TALLY);
+
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_CD);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CD_STATUS);
+       tegra_dsi_writel(dsi, 0, DSI_VIDEO_MODE_CONTROL);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
+       tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
+
+       tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
+       tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
+       tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
+}
+
+static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
+                                struct mipi_dsi_device *device)
+{
+       struct tegra_dsi *dsi = host_to_tegra(host);
+       struct tegra_output *output = &dsi->output;
+
+       dsi->format = device->format;
+       dsi->lanes = device->lanes;
+
+       output->panel = of_drm_find_panel(device->dev.of_node);
+       if (output->panel) {
+               if (output->connector.dev)
+                       drm_helper_hpd_irq_event(output->connector.dev);
+       }
+
+       return 0;
+}
+
+static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
+                                struct mipi_dsi_device *device)
+{
+       struct tegra_dsi *dsi = host_to_tegra(host);
+       struct tegra_output *output = &dsi->output;
+
+       if (output->panel && &device->dev == output->panel->dev) {
+               if (output->connector.dev)
+                       drm_helper_hpd_irq_event(output->connector.dev);
+
+               output->panel = NULL;
+       }
+
+       return 0;
+}
+
+static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
+       .attach = tegra_dsi_host_attach,
+       .detach = tegra_dsi_host_detach,
+};
+
+static int tegra_dsi_probe(struct platform_device *pdev)
+{
+       struct tegra_dsi *dsi;
+       struct resource *regs;
+       int err;
+
+       dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+       if (!dsi)
+               return -ENOMEM;
+
+       dsi->output.dev = dsi->dev = &pdev->dev;
+
+       err = tegra_output_probe(&dsi->output);
+       if (err < 0)
+               return err;
+
+       /*
+        * Assume these values by default. When a DSI peripheral driver
+        * attaches to the DSI host, the parameters will be taken from
+        * the attached device.
+        */
+       dsi->format = MIPI_DSI_FMT_RGB888;
+       dsi->lanes = 4;
+
+       dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
+       if (IS_ERR(dsi->rst))
+               return PTR_ERR(dsi->rst);
+
+       dsi->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dsi->clk)) {
+               dev_err(&pdev->dev, "cannot get DSI clock\n");
+               return PTR_ERR(dsi->clk);
+       }
+
+       err = clk_prepare_enable(dsi->clk);
+       if (err < 0) {
+               dev_err(&pdev->dev, "cannot enable DSI clock\n");
+               return err;
+       }
+
+       dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
+       if (IS_ERR(dsi->clk_lp)) {
+               dev_err(&pdev->dev, "cannot get low-power clock\n");
+               return PTR_ERR(dsi->clk_lp);
+       }
+
+       err = clk_prepare_enable(dsi->clk_lp);
+       if (err < 0) {
+               dev_err(&pdev->dev, "cannot enable low-power clock\n");
+               return err;
+       }
+
+       dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
+       if (IS_ERR(dsi->clk_parent)) {
+               dev_err(&pdev->dev, "cannot get parent clock\n");
+               return PTR_ERR(dsi->clk_parent);
+       }
+
+       err = clk_prepare_enable(dsi->clk_parent);
+       if (err < 0) {
+               dev_err(&pdev->dev, "cannot enable parent clock\n");
+               return err;
+       }
+
+       err = tegra_dsi_setup_clocks(dsi);
+       if (err < 0) {
+               dev_err(&pdev->dev, "cannot setup clocks\n");
+               return err;
+       }
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
+       if (IS_ERR(dsi->regs))
+               return PTR_ERR(dsi->regs);
+
+       tegra_dsi_initialize(dsi);
+
+       dsi->mipi = tegra_mipi_request(&pdev->dev);
+       if (IS_ERR(dsi->mipi))
+               return PTR_ERR(dsi->mipi);
+
+       dsi->host.ops = &tegra_dsi_host_ops;
+       dsi->host.dev = &pdev->dev;
+
+       err = mipi_dsi_host_register(&dsi->host);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
+               return err;
+       }
+
+       INIT_LIST_HEAD(&dsi->client.list);
+       dsi->client.ops = &dsi_client_ops;
+       dsi->client.dev = &pdev->dev;
+
+       err = host1x_client_register(&dsi->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       platform_set_drvdata(pdev, dsi);
+
+       return 0;
+}
+
+static int tegra_dsi_remove(struct platform_device *pdev)
+{
+       struct tegra_dsi *dsi = platform_get_drvdata(pdev);
+       int err;
+
+       err = host1x_client_unregister(&dsi->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       mipi_dsi_host_unregister(&dsi->host);
+       tegra_mipi_free(dsi->mipi);
+
+       clk_disable_unprepare(dsi->clk_parent);
+       clk_disable_unprepare(dsi->clk_lp);
+       clk_disable_unprepare(dsi->clk);
+
+       err = tegra_output_remove(&dsi->output);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to remove output: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id tegra_dsi_of_match[] = {
+       { .compatible = "nvidia,tegra114-dsi", },
+       { },
+};
+
+struct platform_driver tegra_dsi_driver = {
+       .driver = {
+               .name = "tegra-dsi",
+               .of_match_table = tegra_dsi_of_match,
+       },
+       .probe = tegra_dsi_probe,
+       .remove = tegra_dsi_remove,
+};
diff --git a/drivers/gpu/drm/tegra/dsi.h b/drivers/gpu/drm/tegra/dsi.h
new file mode 100644 (file)
index 0000000..00e79c1
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef DRM_TEGRA_DSI_H
+#define DRM_TEGRA_DSI_H
+
+#define DSI_INCR_SYNCPT                        0x00
+#define DSI_INCR_SYNCPT_CONTROL                0x01
+#define DSI_INCR_SYNCPT_ERROR          0x02
+#define DSI_CTXSW                      0x08
+#define DSI_RD_DATA                    0x09
+#define DSI_WR_DATA                    0x0a
+#define DSI_POWER_CONTROL              0x0b
+#define DSI_POWER_CONTROL_ENABLE       (1 << 0)
+#define DSI_INT_ENABLE                 0x0c
+#define DSI_INT_STATUS                 0x0d
+#define DSI_INT_MASK                   0x0e
+#define DSI_HOST_CONTROL               0x0f
+#define DSI_HOST_CONTROL_RAW           (1 << 6)
+#define DSI_HOST_CONTROL_HS            (1 << 5)
+#define DSI_HOST_CONTROL_BTA           (1 << 2)
+#define DSI_HOST_CONTROL_CS            (1 << 1)
+#define DSI_HOST_CONTROL_ECC           (1 << 0)
+#define DSI_CONTROL                    0x10
+#define DSI_CONTROL_HS_CLK_CTRL                (1 << 20)
+#define DSI_CONTROL_CHANNEL(c)         (((c) & 0x3) << 16)
+#define DSI_CONTROL_FORMAT(f)          (((f) & 0x3) << 12)
+#define DSI_CONTROL_TX_TRIG(x)         (((x) & 0x3) <<  8)
+#define DSI_CONTROL_LANES(n)           (((n) & 0x3) <<  4)
+#define DSI_CONTROL_DCS_ENABLE         (1 << 3)
+#define DSI_CONTROL_SOURCE(s)          (((s) & 0x1) <<  2)
+#define DSI_CONTROL_VIDEO_ENABLE       (1 << 1)
+#define DSI_CONTROL_HOST_ENABLE                (1 << 0)
+#define DSI_SOL_DELAY                  0x11
+#define DSI_MAX_THRESHOLD              0x12
+#define DSI_TRIGGER                    0x13
+#define DSI_TX_CRC                     0x14
+#define DSI_STATUS                     0x15
+#define DSI_STATUS_IDLE                        (1 << 10)
+#define DSI_INIT_SEQ_CONTROL           0x1a
+#define DSI_INIT_SEQ_DATA_0            0x1b
+#define DSI_INIT_SEQ_DATA_1            0x1c
+#define DSI_INIT_SEQ_DATA_2            0x1d
+#define DSI_INIT_SEQ_DATA_3            0x1e
+#define DSI_INIT_SEQ_DATA_4            0x1f
+#define DSI_INIT_SEQ_DATA_5            0x20
+#define DSI_INIT_SEQ_DATA_6            0x21
+#define DSI_INIT_SEQ_DATA_7            0x22
+#define DSI_PKT_SEQ_0_LO               0x23
+#define DSI_PKT_SEQ_0_HI               0x24
+#define DSI_PKT_SEQ_1_LO               0x25
+#define DSI_PKT_SEQ_1_HI               0x26
+#define DSI_PKT_SEQ_2_LO               0x27
+#define DSI_PKT_SEQ_2_HI               0x28
+#define DSI_PKT_SEQ_3_LO               0x29
+#define DSI_PKT_SEQ_3_HI               0x2a
+#define DSI_PKT_SEQ_4_LO               0x2b
+#define DSI_PKT_SEQ_4_HI               0x2c
+#define DSI_PKT_SEQ_5_LO               0x2d
+#define DSI_PKT_SEQ_5_HI               0x2e
+#define DSI_DCS_CMDS                   0x33
+#define DSI_PKT_LEN_0_1                        0x34
+#define DSI_PKT_LEN_2_3                        0x35
+#define DSI_PKT_LEN_4_5                        0x36
+#define DSI_PKT_LEN_6_7                        0x37
+#define DSI_PHY_TIMING_0               0x3c
+#define DSI_PHY_TIMING_1               0x3d
+#define DSI_PHY_TIMING_2               0x3e
+#define DSI_BTA_TIMING                 0x3f
+
+#define DSI_TIMING_FIELD(value, period, hwinc) \
+       ((DIV_ROUND_CLOSEST(value, period) - (hwinc)) & 0xff)
+
+#define DSI_TIMEOUT_0                  0x44
+#define DSI_TIMEOUT_LRX(x)             (((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_HTX(x)             (((x) & 0xffff) <<  0)
+#define DSI_TIMEOUT_1                  0x45
+#define DSI_TIMEOUT_PR(x)              (((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_TA(x)              (((x) & 0xffff) <<  0)
+#define DSI_TO_TALLY                   0x46
+#define DSI_TALLY_TA(x)                        (((x) & 0xff) << 16)
+#define DSI_TALLY_LRX(x)               (((x) & 0xff) <<  8)
+#define DSI_TALLY_HTX(x)               (((x) & 0xff) <<  0)
+#define DSI_PAD_CONTROL_0              0x4b
+#define DSI_PAD_CONTROL_VS1_PDIO(x)    (((x) & 0xf) <<  0)
+#define DSI_PAD_CONTROL_VS1_PDIO_CLK   (1 <<  8)
+#define DSI_PAD_CONTROL_VS1_PULLDN(x)  (((x) & 0xf) << 16)
+#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
+#define DSI_PAD_CONTROL_CD             0x4c
+#define DSI_PAD_CD_STATUS              0x4d
+#define DSI_VIDEO_MODE_CONTROL         0x4e
+#define DSI_PAD_CONTROL_1              0x4f
+#define DSI_PAD_CONTROL_2              0x50
+#define DSI_PAD_OUT_CLK(x)             (((x) & 0x7) <<  0)
+#define DSI_PAD_LP_DN(x)               (((x) & 0x7) <<  4)
+#define DSI_PAD_LP_UP(x)               (((x) & 0x7) <<  8)
+#define DSI_PAD_SLEW_DN(x)             (((x) & 0x7) << 12)
+#define DSI_PAD_SLEW_UP(x)             (((x) & 0x7) << 16)
+#define DSI_PAD_CONTROL_3              0x51
+#define DSI_PAD_CONTROL_4              0x52
+#define DSI_GANGED_MODE_CONTROL                0x53
+#define DSI_GANGED_MODE_START          0x54
+#define DSI_GANGED_MODE_SIZE           0x55
+#define DSI_RAW_DATA_BYTE_COUNT                0x56
+#define DSI_ULTRA_LOW_POWER_CONTROL    0x57
+#define DSI_INIT_SEQ_DATA_8            0x58
+#define DSI_INIT_SEQ_DATA_9            0x59
+#define DSI_INIT_SEQ_DATA_10           0x5a
+#define DSI_INIT_SEQ_DATA_11           0x5b
+#define DSI_INIT_SEQ_DATA_12           0x5c
+#define DSI_INIT_SEQ_DATA_13           0x5d
+#define DSI_INIT_SEQ_DATA_14           0x5e
+#define DSI_INIT_SEQ_DATA_15           0x5f
+
+#endif
index a3835e7de1842b84145e52c40ef15ed21e183323..f7fca09d49211c5afebdc797590c001a88e72d6d 100644 (file)
@@ -18,10 +18,12 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
        return container_of(fb, struct tegra_fb, base);
 }
 
+#ifdef CONFIG_DRM_TEGRA_FBDEV
 static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
 {
        return container_of(helper, struct tegra_fbdev, base);
 }
+#endif
 
 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
                                    unsigned int index)
@@ -98,8 +100,10 @@ static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
                return ERR_PTR(-ENOMEM);
 
        fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
-       if (!fb->planes)
+       if (!fb->planes) {
+               kfree(fb);
                return ERR_PTR(-ENOMEM);
+       }
 
        fb->num_planes = num_planes;
 
@@ -172,6 +176,7 @@ unreference:
        return ERR_PTR(err);
 }
 
+#ifdef CONFIG_DRM_TEGRA_FBDEV
 static struct fb_ops tegra_fb_ops = {
        .owner = THIS_MODULE,
        .fb_fillrect = sys_fillrect,
@@ -339,6 +344,15 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
        kfree(fbdev);
 }
 
+void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
+{
+       if (fbdev) {
+               drm_modeset_lock_all(fbdev->base.dev);
+               drm_fb_helper_restore_fbdev_mode(&fbdev->base);
+               drm_modeset_unlock_all(fbdev->base.dev);
+       }
+}
+
 static void tegra_fb_output_poll_changed(struct drm_device *drm)
 {
        struct tegra_drm *tegra = drm->dev_private;
@@ -346,16 +360,20 @@ static void tegra_fb_output_poll_changed(struct drm_device *drm)
        if (tegra->fbdev)
                drm_fb_helper_hotplug_event(&tegra->fbdev->base);
 }
+#endif
 
 static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
        .fb_create = tegra_fb_create,
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        .output_poll_changed = tegra_fb_output_poll_changed,
+#endif
 };
 
 int tegra_drm_fb_init(struct drm_device *drm)
 {
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
-       struct tegra_fbdev *fbdev;
+#endif
 
        drm->mode_config.min_width = 0;
        drm->mode_config.min_height = 0;
@@ -365,28 +383,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
 
        drm->mode_config.funcs = &tegra_drm_mode_funcs;
 
-       fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
-                                  drm->mode_config.num_connector);
-       if (IS_ERR(fbdev))
-               return PTR_ERR(fbdev);
-
-       tegra->fbdev = fbdev;
+#ifdef CONFIG_DRM_TEGRA_FBDEV
+       tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
+                                         drm->mode_config.num_connector);
+       if (IS_ERR(tegra->fbdev))
+               return PTR_ERR(tegra->fbdev);
+#endif
 
        return 0;
 }
 
 void tegra_drm_fb_exit(struct drm_device *drm)
 {
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
 
        tegra_fbdev_free(tegra->fbdev);
-}
-
-void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
-{
-       if (fbdev) {
-               drm_modeset_lock_all(fbdev->base.dev);
-               drm_fb_helper_restore_fbdev_mode(&fbdev->base);
-               drm_modeset_unlock_all(fbdev->base.dev);
-       }
+#endif
 }
index 28a9cbc07ab95f3a5873fc9aac0f008180bffca5..ef853e558036d55ce31c7cb4acfdf2479beefb80 100644 (file)
@@ -18,6 +18,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/dma-buf.h>
 #include <drm/tegra_drm.h>
 
 #include "gem.h"
@@ -83,7 +84,7 @@ static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
        return bo;
 }
 
-const struct host1x_bo_ops tegra_bo_ops = {
+static const struct host1x_bo_ops tegra_bo_ops = {
        .get = tegra_bo_get,
        .put = tegra_bo_put,
        .pin = tegra_bo_pin,
@@ -145,7 +146,6 @@ err_dma:
        kfree(bo);
 
        return ERR_PTR(err);
-
 }
 
 struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
@@ -174,13 +174,87 @@ err:
        return ERR_PTR(ret);
 }
 
+struct tegra_bo *tegra_bo_import(struct drm_device *drm, struct dma_buf *buf)
+{
+       struct dma_buf_attachment *attach;
+       struct tegra_bo *bo;
+       ssize_t size;
+       int err;
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+       if (!bo)
+               return ERR_PTR(-ENOMEM);
+
+       host1x_bo_init(&bo->base, &tegra_bo_ops);
+       size = round_up(buf->size, PAGE_SIZE);
+
+       err = drm_gem_object_init(drm, &bo->gem, size);
+       if (err < 0)
+               goto free;
+
+       err = drm_gem_create_mmap_offset(&bo->gem);
+       if (err < 0)
+               goto release;
+
+       attach = dma_buf_attach(buf, drm->dev);
+       if (IS_ERR(attach)) {
+               err = PTR_ERR(attach);
+               goto free_mmap;
+       }
+
+       get_dma_buf(buf);
+
+       bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
+       if (!bo->sgt) {
+               err = -ENOMEM;
+               goto detach;
+       }
+
+       if (IS_ERR(bo->sgt)) {
+               err = PTR_ERR(bo->sgt);
+               goto detach;
+       }
+
+       if (bo->sgt->nents > 1) {
+               err = -EINVAL;
+               goto detach;
+       }
+
+       bo->paddr = sg_dma_address(bo->sgt->sgl);
+       bo->gem.import_attach = attach;
+
+       return bo;
+
+detach:
+       if (!IS_ERR_OR_NULL(bo->sgt))
+               dma_buf_unmap_attachment(attach, bo->sgt, DMA_TO_DEVICE);
+
+       dma_buf_detach(buf, attach);
+       dma_buf_put(buf);
+free_mmap:
+       drm_gem_free_mmap_offset(&bo->gem);
+release:
+       drm_gem_object_release(&bo->gem);
+free:
+       kfree(bo);
+
+       return ERR_PTR(err);
+}
+
 void tegra_bo_free_object(struct drm_gem_object *gem)
 {
        struct tegra_bo *bo = to_tegra_bo(gem);
 
+       if (gem->import_attach) {
+               dma_buf_unmap_attachment(gem->import_attach, bo->sgt,
+                                        DMA_TO_DEVICE);
+               drm_prime_gem_destroy(gem, NULL);
+       } else {
+               tegra_bo_destroy(gem->dev, bo);
+       }
+
        drm_gem_free_mmap_offset(gem);
        drm_gem_object_release(gem);
-       tegra_bo_destroy(gem->dev, bo);
 
        kfree(bo);
 }
@@ -256,3 +330,106 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
 
        return ret;
 }
+
+static struct sg_table *
+tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
+                           enum dma_data_direction dir)
+{
+       struct drm_gem_object *gem = attach->dmabuf->priv;
+       struct tegra_bo *bo = to_tegra_bo(gem);
+       struct sg_table *sgt;
+
+       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt)
+               return NULL;
+
+       if (sg_alloc_table(sgt, 1, GFP_KERNEL)) {
+               kfree(sgt);
+               return NULL;
+       }
+
+       sg_dma_address(sgt->sgl) = bo->paddr;
+       sg_dma_len(sgt->sgl) = gem->size;
+
+       return sgt;
+}
+
+static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
+                                         struct sg_table *sgt,
+                                         enum dma_data_direction dir)
+{
+       sg_free_table(sgt);
+       kfree(sgt);
+}
+
+static void tegra_gem_prime_release(struct dma_buf *buf)
+{
+       drm_gem_dmabuf_release(buf);
+}
+
+static void *tegra_gem_prime_kmap_atomic(struct dma_buf *buf,
+                                        unsigned long page)
+{
+       return NULL;
+}
+
+static void tegra_gem_prime_kunmap_atomic(struct dma_buf *buf,
+                                         unsigned long page,
+                                         void *addr)
+{
+}
+
+static void *tegra_gem_prime_kmap(struct dma_buf *buf, unsigned long page)
+{
+       return NULL;
+}
+
+static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page,
+                                  void *addr)
+{
+}
+
+static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
+{
+       return -EINVAL;
+}
+
+static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
+       .map_dma_buf = tegra_gem_prime_map_dma_buf,
+       .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
+       .release = tegra_gem_prime_release,
+       .kmap_atomic = tegra_gem_prime_kmap_atomic,
+       .kunmap_atomic = tegra_gem_prime_kunmap_atomic,
+       .kmap = tegra_gem_prime_kmap,
+       .kunmap = tegra_gem_prime_kunmap,
+       .mmap = tegra_gem_prime_mmap,
+};
+
+struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
+                                      struct drm_gem_object *gem,
+                                      int flags)
+{
+       return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size,
+                             flags);
+}
+
+struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
+                                             struct dma_buf *buf)
+{
+       struct tegra_bo *bo;
+
+       if (buf->ops == &tegra_gem_prime_dmabuf_ops) {
+               struct drm_gem_object *gem = buf->priv;
+
+               if (gem->dev == drm) {
+                       drm_gem_object_reference(gem);
+                       return gem;
+               }
+       }
+
+       bo = tegra_bo_import(drm, buf);
+       if (IS_ERR(bo))
+               return ERR_CAST(bo);
+
+       return &bo->gem;
+}
index 7674000bf47d6696ecec6db7507926144832c772..ffd4f792b410997630e06339a4307d087ab55f2e 100644 (file)
@@ -31,6 +31,7 @@ struct tegra_bo {
        struct drm_gem_object gem;
        struct host1x_bo base;
        unsigned long flags;
+       struct sg_table *sgt;
        dma_addr_t paddr;
        void *vaddr;
 };
@@ -40,8 +41,6 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
        return container_of(gem, struct tegra_bo, gem);
 }
 
-extern const struct host1x_bo_ops tegra_bo_ops;
-
 struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
                                 unsigned long flags);
 struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
@@ -59,4 +58,10 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
 
 extern const struct vm_operations_struct tegra_bo_vm_ops;
 
+struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
+                                      struct drm_gem_object *gem,
+                                      int flags);
+struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
+                                             struct dma_buf *buf);
+
 #endif
index 4cec8f526af7036efac83c439599b1093ee4c94c..0cbb24b1ae04feef3e3bd602936c0e469715527e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/host1x.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/tegra-powergate.h>
 
 #include "drm.h"
@@ -22,6 +23,8 @@ struct gr3d {
        struct host1x_channel *channel;
        struct clk *clk_secondary;
        struct clk *clk;
+       struct reset_control *rst_secondary;
+       struct reset_control *rst;
 
        DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
 };
@@ -255,15 +258,29 @@ static int gr3d_probe(struct platform_device *pdev)
                return PTR_ERR(gr3d->clk);
        }
 
+       gr3d->rst = devm_reset_control_get(&pdev->dev, "3d");
+       if (IS_ERR(gr3d->rst)) {
+               dev_err(&pdev->dev, "cannot get reset\n");
+               return PTR_ERR(gr3d->rst);
+       }
+
        if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) {
                gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2");
                if (IS_ERR(gr3d->clk)) {
                        dev_err(&pdev->dev, "cannot get secondary clock\n");
                        return PTR_ERR(gr3d->clk);
                }
+
+               gr3d->rst_secondary = devm_reset_control_get(&pdev->dev,
+                                                               "3d2");
+               if (IS_ERR(gr3d->rst_secondary)) {
+                       dev_err(&pdev->dev, "cannot get secondary reset\n");
+                       return PTR_ERR(gr3d->rst_secondary);
+               }
        }
 
-       err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk);
+       err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk,
+                                               gr3d->rst);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to power up 3D unit\n");
                return err;
@@ -271,7 +288,8 @@ static int gr3d_probe(struct platform_device *pdev)
 
        if (gr3d->clk_secondary) {
                err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1,
-                                                       gr3d->clk_secondary);
+                                                       gr3d->clk_secondary,
+                                                       gr3d->rst_secondary);
                if (err < 0) {
                        dev_err(&pdev->dev,
                                "failed to power up secondary 3D unit\n");
index 0cd9bc2056e8c6bfe12cd15c5722c6f18d087e78..bc9cb1ac709b197f628bd585c875ee1ba7c95dc3 100644 (file)
@@ -8,10 +8,10 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/debugfs.h>
 #include <linux/hdmi.h>
 #include <linux/regulator/consumer.h>
+#include <linux/reset.h>
 
 #include "hdmi.h"
 #include "drm.h"
@@ -40,6 +40,7 @@ struct tegra_hdmi {
        struct host1x_client client;
        struct tegra_output output;
        struct device *dev;
+       bool enabled;
 
        struct regulator *vdd;
        struct regulator *pll;
@@ -49,6 +50,7 @@ struct tegra_hdmi {
 
        struct clk *clk_parent;
        struct clk *clk;
+       struct reset_control *rst;
 
        const struct tegra_hdmi_config *config;
 
@@ -378,7 +380,7 @@ static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
 
                if (f > 96000)
                        delta = 2;
-               else if (f > 480000)
+               else if (f > 48000)
                        delta = 6;
                else
                        delta = 9;
@@ -698,6 +700,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
        int retries = 1000;
        int err;
 
+       if (hdmi->enabled)
+               return 0;
+
        hdmi->dvi = !tegra_output_is_hdmi(output);
 
        pclk = mode->clock * 1000;
@@ -731,9 +736,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
                return err;
        }
 
-       tegra_periph_reset_assert(hdmi->clk);
+       reset_control_assert(hdmi->rst);
        usleep_range(1000, 2000);
-       tegra_periph_reset_deassert(hdmi->clk);
+       reset_control_deassert(hdmi->rst);
 
        tegra_dc_writel(dc, VSYNC_H_POSITION(1),
                        DC_DISP_DISP_TIMING_OPTIONS);
@@ -838,10 +843,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
        value |= SOR_CSTM_ROTCLK(2);
        tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
 
-       tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
-
        /* start SOR */
        tegra_hdmi_writel(hdmi,
                          SOR_PWR_NORMAL_STATE_PU |
@@ -891,31 +892,67 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
                          HDMI_NV_PDISP_SOR_STATE1);
        tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
 
-       tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
-
-       value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
-               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+       value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+       value |= HDMI_ENABLE;
+       tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
 
-       value = DISP_CTRL_MODE_C_DISPLAY;
+       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+       value &= ~DISP_CTRL_MODE_MASK;
+       value |= DISP_CTRL_MODE_C_DISPLAY;
        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
 
+       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+       value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
        tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
        tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
        /* TODO: add HDCP support */
 
+       hdmi->enabled = true;
+
        return 0;
 }
 
 static int tegra_output_hdmi_disable(struct tegra_output *output)
 {
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
        struct tegra_hdmi *hdmi = to_hdmi(output);
+       unsigned long value;
+
+       if (!hdmi->enabled)
+               return 0;
+
+       /*
+        * The following accesses registers of the display controller, so make
+        * sure it's only executed when the output is attached to one.
+        */
+       if (dc) {
+               value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
+               value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                          PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
+               tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+               value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+               value &= ~DISP_CTRL_MODE_MASK;
+               tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+               value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+               value &= ~HDMI_ENABLE;
+               tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+               tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+               tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+       }
 
-       tegra_periph_reset_assert(hdmi->clk);
+       reset_control_assert(hdmi->rst);
        clk_disable(hdmi->clk);
        regulator_disable(hdmi->pll);
 
+       hdmi->enabled = false;
+
        return 0;
 }
 
@@ -959,7 +996,7 @@ static int tegra_output_hdmi_check_mode(struct tegra_output *output,
        parent = clk_get_parent(hdmi->clk_parent);
 
        err = clk_round_rate(parent, pclk * 4);
-       if (err < 0)
+       if (err <= 0)
                *status = MODE_NOCLOCK;
        else
                *status = MODE_OK;
@@ -1338,6 +1375,12 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
                return PTR_ERR(hdmi->clk);
        }
 
+       hdmi->rst = devm_reset_control_get(&pdev->dev, "hdmi");
+       if (IS_ERR(hdmi->rst)) {
+               dev_err(&pdev->dev, "failed to get reset\n");
+               return PTR_ERR(hdmi->rst);
+       }
+
        err = clk_prepare(hdmi->clk);
        if (err < 0)
                return err;
diff --git a/drivers/gpu/drm/tegra/mipi-phy.c b/drivers/gpu/drm/tegra/mipi-phy.c
new file mode 100644 (file)
index 0000000..e2c4aed
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+
+#include "mipi-phy.h"
+
+/*
+ * Default D-PHY timings based on MIPI D-PHY specification. Derived from
+ * the valid ranges specified in Section 5.9 of the D-PHY specification
+ * with minor adjustments.
+ */
+int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
+                                unsigned long period)
+{
+       timing->clkmiss = 0;
+       timing->clkpost = 70 + 52 * period;
+       timing->clkpre = 8;
+       timing->clkprepare = 65;
+       timing->clksettle = 95;
+       timing->clktermen = 0;
+       timing->clktrail = 80;
+       timing->clkzero = 260;
+       timing->dtermen = 0;
+       timing->eot = 0;
+       timing->hsexit = 120;
+       timing->hsprepare = 65 + 5 * period;
+       timing->hszero = 145 + 5 * period;
+       timing->hssettle = 85 + 6 * period;
+       timing->hsskip = 40;
+       timing->hstrail = max(8 * period, 60 + 4 * period);
+       timing->init = 100000;
+       timing->lpx = 60;
+       timing->taget = 5 * timing->lpx;
+       timing->tago = 4 * timing->lpx;
+       timing->tasure = 2 * timing->lpx;
+       timing->wakeup = 1000000;
+
+       return 0;
+}
+
+/*
+ * Validate D-PHY timing according to MIPI Alliance Specification for D-PHY,
+ * Section 5.9 "Global Operation Timing Parameters".
+ */
+int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
+                             unsigned long period)
+{
+       if (timing->clkmiss > 60)
+               return -EINVAL;
+
+       if (timing->clkpost < (60 + 52 * period))
+               return -EINVAL;
+
+       if (timing->clkpre < 8)
+               return -EINVAL;
+
+       if (timing->clkprepare < 38 || timing->clkprepare > 95)
+               return -EINVAL;
+
+       if (timing->clksettle < 95 || timing->clksettle > 300)
+               return -EINVAL;
+
+       if (timing->clktermen > 38)
+               return -EINVAL;
+
+       if (timing->clktrail < 60)
+               return -EINVAL;
+
+       if (timing->clkprepare + timing->clkzero < 300)
+               return -EINVAL;
+
+       if (timing->dtermen > 35 + 4 * period)
+               return -EINVAL;
+
+       if (timing->eot > 105 + 12 * period)
+               return -EINVAL;
+
+       if (timing->hsexit < 100)
+               return -EINVAL;
+
+       if (timing->hsprepare < 40 + 4 * period ||
+           timing->hsprepare > 85 + 6 * period)
+               return -EINVAL;
+
+       if (timing->hsprepare + timing->hszero < 145 + 10 * period)
+               return -EINVAL;
+
+       if ((timing->hssettle < 85 + 6 * period) ||
+           (timing->hssettle > 145 + 10 * period))
+               return -EINVAL;
+
+       if (timing->hsskip < 40 || timing->hsskip > 55 + 4 * period)
+               return -EINVAL;
+
+       if (timing->hstrail < max(8 * period, 60 + 4 * period))
+               return -EINVAL;
+
+       if (timing->init < 100000)
+               return -EINVAL;
+
+       if (timing->lpx < 50)
+               return -EINVAL;
+
+       if (timing->taget != 5 * timing->lpx)
+               return -EINVAL;
+
+       if (timing->tago != 4 * timing->lpx)
+               return -EINVAL;
+
+       if (timing->tasure < timing->lpx || timing->tasure > 2 * timing->lpx)
+               return -EINVAL;
+
+       if (timing->wakeup < 1000000)
+               return -EINVAL;
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/tegra/mipi-phy.h b/drivers/gpu/drm/tegra/mipi-phy.h
new file mode 100644 (file)
index 0000000..d359169
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef DRM_TEGRA_MIPI_PHY_H
+#define DRM_TEGRA_MIPI_PHY_H
+
+/*
+ * D-PHY timing parameters
+ *
+ * A detailed description of these parameters can be found in the  MIPI
+ * Alliance Specification for D-PHY, Section 5.9 "Global Operation Timing
+ * Parameters".
+ *
+ * All parameters are specified in nanoseconds.
+ */
+struct mipi_dphy_timing {
+       unsigned int clkmiss;
+       unsigned int clkpost;
+       unsigned int clkpre;
+       unsigned int clkprepare;
+       unsigned int clksettle;
+       unsigned int clktermen;
+       unsigned int clktrail;
+       unsigned int clkzero;
+       unsigned int dtermen;
+       unsigned int eot;
+       unsigned int hsexit;
+       unsigned int hsprepare;
+       unsigned int hszero;
+       unsigned int hssettle;
+       unsigned int hsskip;
+       unsigned int hstrail;
+       unsigned int init;
+       unsigned int lpx;
+       unsigned int taget;
+       unsigned int tago;
+       unsigned int tasure;
+       unsigned int wakeup;
+};
+
+int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
+                                unsigned long period);
+int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
+                             unsigned long period);
+
+#endif
index 2cb0065e0578f6d80da0532dad68a31e27a6924d..f1b5030f55e33e8c78a3f0c2c1b24528a3fd12aa 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/of_gpio.h>
 
+#include <drm/drm_panel.h>
 #include "drm.h"
 
 static int tegra_connector_get_modes(struct drm_connector *connector)
@@ -17,6 +18,12 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
        struct edid *edid = NULL;
        int err = 0;
 
+       if (output->panel) {
+               err = output->panel->funcs->get_modes(output->panel);
+               if (err > 0)
+                       return err;
+       }
+
        if (output->edid)
                edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
        else if (output->ddc)
@@ -72,6 +79,11 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
                else
                        status = connector_status_connected;
        } else {
+               if (!output->panel)
+                       status = connector_status_disconnected;
+               else
+                       status = connector_status_connected;
+
                if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
                        status = connector_status_connected;
        }
@@ -115,6 +127,16 @@ static const struct drm_encoder_funcs encoder_funcs = {
 
 static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+       struct tegra_output *output = encoder_to_output(encoder);
+       struct drm_panel *panel = output->panel;
+
+       if (mode != DRM_MODE_DPMS_ON) {
+               drm_panel_disable(panel);
+               tegra_output_disable(output);
+       } else {
+               tegra_output_enable(output);
+               drm_panel_enable(panel);
+       }
 }
 
 static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -163,14 +185,23 @@ static irqreturn_t hpd_irq(int irq, void *data)
 
 int tegra_output_probe(struct tegra_output *output)
 {
+       struct device_node *ddc, *panel;
        enum of_gpio_flags flags;
-       struct device_node *ddc;
        size_t size;
        int err;
 
        if (!output->of_node)
                output->of_node = output->dev->of_node;
 
+       panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
+       if (panel) {
+               output->panel = of_drm_find_panel(panel);
+               if (!output->panel)
+                       return -EPROBE_DEFER;
+
+               of_node_put(panel);
+       }
+
        output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
 
        ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
@@ -185,9 +216,6 @@ int tegra_output_probe(struct tegra_output *output)
                of_node_put(ddc);
        }
 
-       if (!output->edid && !output->ddc)
-               return -ENODEV;
-
        output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
                                                   "nvidia,hpd-gpio", 0,
                                                   &flags);
@@ -256,6 +284,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
                encoder = DRM_MODE_ENCODER_TMDS;
                break;
 
+       case TEGRA_OUTPUT_DSI:
+               connector = DRM_MODE_CONNECTOR_DSI;
+               encoder = DRM_MODE_ENCODER_DSI;
+               break;
+
        default:
                connector = DRM_MODE_CONNECTOR_Unknown;
                encoder = DRM_MODE_ENCODER_NONE;
@@ -267,6 +300,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
        drm_connector_helper_add(&output->connector, &connector_helper_funcs);
        output->connector.dpms = DRM_MODE_DPMS_OFF;
 
+       if (output->panel)
+               drm_panel_attach(output->panel, &output->connector);
+
        drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
        drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
 
index 3b29018913a5f2bb9da1a2ae2f57ddc89280bbe8..03885bb8dcc049bed4f25c16fceef22968a72d51 100644 (file)
@@ -87,15 +87,60 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
 static int tegra_output_rgb_enable(struct tegra_output *output)
 {
        struct tegra_rgb *rgb = to_rgb(output);
+       unsigned long value;
 
        tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
+       value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
+       tegra_dc_writel(rgb->dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
+
+       /* XXX: parameterize? */
+       value = tegra_dc_readl(rgb->dc, DC_COM_PIN_OUTPUT_POLARITY(1));
+       value &= ~LVS_OUTPUT_POLARITY_LOW;
+       value &= ~LHS_OUTPUT_POLARITY_LOW;
+       tegra_dc_writel(rgb->dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
+
+       /* XXX: parameterize? */
+       value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
+               DISP_ORDER_RED_BLUE;
+       tegra_dc_writel(rgb->dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
+
+       /* XXX: parameterize? */
+       value = SC0_H_QUALIFIER_NONE | SC1_H_QUALIFIER_NONE;
+       tegra_dc_writel(rgb->dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS);
+
+       value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND);
+       value &= ~DISP_CTRL_MODE_MASK;
+       value |= DISP_CTRL_MODE_C_DISPLAY;
+       tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND);
+
+       value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
+       value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+       tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+       tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
        return 0;
 }
 
 static int tegra_output_rgb_disable(struct tegra_output *output)
 {
        struct tegra_rgb *rgb = to_rgb(output);
+       unsigned long value;
+
+       value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
+       value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+                  PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
+       tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+       value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND);
+       value &= ~DISP_CTRL_MODE_MASK;
+       tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND);
+
+       tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
        tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
index 116da199b9429a56ba8a7b58efc953369b721344..171a8203892ce16b7767b2fb3fa11fc1995f0fad 100644 (file)
@@ -311,7 +311,7 @@ static void tilcdc_lastclose(struct drm_device *dev)
        drm_fbdev_cma_restore_mode(priv->fbdev);
 }
 
-static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
+static irqreturn_t tilcdc_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct tilcdc_drm_private *priv = dev->dev_private;
@@ -444,7 +444,7 @@ static int tilcdc_mm_show(struct seq_file *m, void *arg)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static struct drm_info_list tilcdc_debugfs_list[] = {
@@ -594,7 +594,7 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
 
 static int tilcdc_pdev_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&tilcdc_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index 07e02c4bf5a8e0def00e120a14b5ada2d1cfaa97..a066513093880a218d185624589ec07efce66b0b 100644 (file)
@@ -957,7 +957,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_mem_space);
 
-int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
+static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
                        struct ttm_placement *placement,
                        bool interruptible,
                        bool no_wait_gpu)
index 4061521523154e0fbc102623b6a9d348e03d0313..1df856f7856821b31fe96e55dac5bc74bd74ed4b 100644 (file)
@@ -187,7 +187,7 @@ void ttm_mem_io_free_vm(struct ttm_buffer_object *bo)
        }
 }
 
-int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
                        void **virtual)
 {
        struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
@@ -219,7 +219,7 @@ int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
        return 0;
 }
 
-void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+static void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
                         void *virtual)
 {
        struct ttm_mem_type_manager *man;
@@ -594,7 +594,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo,
        if (start_page > bo->num_pages)
                return -EINVAL;
 #if 0
-       if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
+       if (num_pages > 1 && !capable(CAP_SYS_ADMIN))
                return -EPERM;
 #endif
        (void) ttm_mem_io_lock(man, false);
index 6440eeac22d250844d2203018258654e54483cd3..801231c9ae483980afe0e93a0af73a7f07123864 100644 (file)
@@ -132,6 +132,15 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                return VM_FAULT_NOPAGE;
        }
 
+       /*
+        * Refuse to fault imported pages. This should be handled
+        * (if at all) by redirecting mmap to the exporter.
+        */
+       if (bo->ttm && (bo->ttm->page_flags & TTM_PAGE_FLAG_SG)) {
+               retval = VM_FAULT_SIGBUS;
+               goto out_unlock;
+       }
+
        if (bdev->driver->fault_reserve_notify) {
                ret = bdev->driver->fault_reserve_notify(bo);
                switch (ret) {
@@ -217,10 +226,17 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                        } else if (unlikely(!page)) {
                                break;
                        }
+                       page->mapping = vma->vm_file->f_mapping;
+                       page->index = drm_vma_node_start(&bo->vma_node) +
+                               page_offset;
                        pfn = page_to_pfn(page);
                }
 
-               ret = vm_insert_mixed(&cvma, address, pfn);
+               if (vma->vm_flags & VM_MIXEDMAP)
+                       ret = vm_insert_mixed(&cvma, address, pfn);
+               else
+                       ret = vm_insert_pfn(&cvma, address, pfn);
+
                /*
                 * Somebody beat us to this PTE or prefaulting to
                 * an already populated PTE, or prefaulting error.
@@ -250,6 +266,8 @@ static void ttm_bo_vm_open(struct vm_area_struct *vma)
        struct ttm_buffer_object *bo =
            (struct ttm_buffer_object *)vma->vm_private_data;
 
+       WARN_ON(bo->bdev->dev_mapping != vma->vm_file->f_mapping);
+
        (void)ttm_bo_reference(bo);
 }
 
@@ -319,7 +337,14 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
         */
 
        vma->vm_private_data = bo;
-       vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
+
+       /*
+        * PFNMAP is faster than MIXEDMAP due to reduced page
+        * administration. So use MIXEDMAP only if private VMA, where
+        * we need to support COW.
+        */
+       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        return 0;
 out_unref:
        ttm_bo_unref(&bo);
@@ -334,7 +359,8 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
 
        vma->vm_ops = &ttm_bo_vm_ops;
        vma->vm_private_data = ttm_bo_reference(bo);
-       vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_IO | VM_DONTEXPAND;
        return 0;
 }
 EXPORT_SYMBOL(ttm_fbdev_mmap);
index 3daa9a3930b810c5adaf310a3dbea89e0e73343d..6a954544727f3f13cfa8d9be0b8ff4cbf39d9367 100644 (file)
@@ -186,14 +186,6 @@ int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
 }
 EXPORT_SYMBOL(ttm_write_lock);
 
-void ttm_write_lock_downgrade(struct ttm_lock *lock)
-{
-       spin_lock(&lock->lock);
-       lock->rw = 1;
-       wake_up_all(&lock->queue);
-       spin_unlock(&lock->lock);
-}
-
 static int __ttm_vt_unlock(struct ttm_lock *lock)
 {
        int ret = 0;
index 6fe7b92a82d1f72f465a79d48dd0088337d713fe..37079859afc86e6cef120cd4d8a924388c3f6e3b 100644 (file)
@@ -68,7 +68,7 @@
 
 struct ttm_object_file {
        struct ttm_object_device *tdev;
-       rwlock_t lock;
+       spinlock_t lock;
        struct list_head ref_list;
        struct drm_open_hash ref_hash[TTM_REF_NUM];
        struct kref refcount;
@@ -118,6 +118,7 @@ struct ttm_object_device {
  */
 
 struct ttm_ref_object {
+       struct rcu_head rcu_head;
        struct drm_hash_item hash;
        struct list_head head;
        struct kref kref;
@@ -210,10 +211,9 @@ static void ttm_release_base(struct kref *kref)
         * call_rcu() or ttm_base_object_kfree().
         */
 
-       if (base->refcount_release) {
-               ttm_object_file_unref(&base->tfile);
+       ttm_object_file_unref(&base->tfile);
+       if (base->refcount_release)
                base->refcount_release(&base);
-       }
 }
 
 void ttm_base_object_unref(struct ttm_base_object **p_base)
@@ -229,32 +229,46 @@ EXPORT_SYMBOL(ttm_base_object_unref);
 struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
                                               uint32_t key)
 {
-       struct ttm_object_device *tdev = tfile->tdev;
-       struct ttm_base_object *uninitialized_var(base);
+       struct ttm_base_object *base = NULL;
        struct drm_hash_item *hash;
+       struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
        int ret;
 
        rcu_read_lock();
-       ret = drm_ht_find_item_rcu(&tdev->object_hash, key, &hash);
+       ret = drm_ht_find_item_rcu(ht, key, &hash);
 
        if (likely(ret == 0)) {
-               base = drm_hash_entry(hash, struct ttm_base_object, hash);
-               ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL;
+               base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
        }
        rcu_read_unlock();
 
-       if (unlikely(ret != 0))
-               return NULL;
+       return base;
+}
+EXPORT_SYMBOL(ttm_base_object_lookup);
 
-       if (tfile != base->tfile && !base->shareable) {
-               pr_err("Attempted access of non-shareable object\n");
-               ttm_base_object_unref(&base);
-               return NULL;
+struct ttm_base_object *
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
+{
+       struct ttm_base_object *base = NULL;
+       struct drm_hash_item *hash;
+       struct drm_open_hash *ht = &tdev->object_hash;
+       int ret;
+
+       rcu_read_lock();
+       ret = drm_ht_find_item_rcu(ht, key, &hash);
+
+       if (likely(ret == 0)) {
+               base = drm_hash_entry(hash, struct ttm_base_object, hash);
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
        }
+       rcu_read_unlock();
 
        return base;
 }
-EXPORT_SYMBOL(ttm_base_object_lookup);
+EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
 
 int ttm_ref_object_add(struct ttm_object_file *tfile,
                       struct ttm_base_object *base,
@@ -266,21 +280,25 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
        struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
        int ret = -EINVAL;
 
+       if (base->tfile != tfile && !base->shareable)
+               return -EPERM;
+
        if (existed != NULL)
                *existed = true;
 
        while (ret == -EINVAL) {
-               read_lock(&tfile->lock);
-               ret = drm_ht_find_item(ht, base->hash.key, &hash);
+               rcu_read_lock();
+               ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
 
                if (ret == 0) {
                        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
-                       kref_get(&ref->kref);
-                       read_unlock(&tfile->lock);
-                       break;
+                       if (!kref_get_unless_zero(&ref->kref)) {
+                               rcu_read_unlock();
+                               break;
+                       }
                }
 
-               read_unlock(&tfile->lock);
+               rcu_read_unlock();
                ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
                                           false, false);
                if (unlikely(ret != 0))
@@ -297,19 +315,19 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
                ref->ref_type = ref_type;
                kref_init(&ref->kref);
 
-               write_lock(&tfile->lock);
-               ret = drm_ht_insert_item(ht, &ref->hash);
+               spin_lock(&tfile->lock);
+               ret = drm_ht_insert_item_rcu(ht, &ref->hash);
 
                if (likely(ret == 0)) {
                        list_add_tail(&ref->head, &tfile->ref_list);
                        kref_get(&base->refcount);
-                       write_unlock(&tfile->lock);
+                       spin_unlock(&tfile->lock);
                        if (existed != NULL)
                                *existed = false;
                        break;
                }
 
-               write_unlock(&tfile->lock);
+               spin_unlock(&tfile->lock);
                BUG_ON(ret != -EINVAL);
 
                ttm_mem_global_free(mem_glob, sizeof(*ref));
@@ -330,17 +348,17 @@ static void ttm_ref_object_release(struct kref *kref)
        struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
 
        ht = &tfile->ref_hash[ref->ref_type];
-       (void)drm_ht_remove_item(ht, &ref->hash);
+       (void)drm_ht_remove_item_rcu(ht, &ref->hash);
        list_del(&ref->head);
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
 
        if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
                base->ref_obj_release(base, ref->ref_type);
 
        ttm_base_object_unref(&ref->obj);
        ttm_mem_global_free(mem_glob, sizeof(*ref));
-       kfree(ref);
-       write_lock(&tfile->lock);
+       kfree_rcu(ref, rcu_head);
+       spin_lock(&tfile->lock);
 }
 
 int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
@@ -351,15 +369,15 @@ int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
        struct drm_hash_item *hash;
        int ret;
 
-       write_lock(&tfile->lock);
+       spin_lock(&tfile->lock);
        ret = drm_ht_find_item(ht, key, &hash);
        if (unlikely(ret != 0)) {
-               write_unlock(&tfile->lock);
+               spin_unlock(&tfile->lock);
                return -EINVAL;
        }
        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
        kref_put(&ref->kref, ttm_ref_object_release);
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
        return 0;
 }
 EXPORT_SYMBOL(ttm_ref_object_base_unref);
@@ -372,7 +390,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
        struct ttm_object_file *tfile = *p_tfile;
 
        *p_tfile = NULL;
-       write_lock(&tfile->lock);
+       spin_lock(&tfile->lock);
 
        /*
         * Since we release the lock within the loop, we have to
@@ -388,7 +406,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
        for (i = 0; i < TTM_REF_NUM; ++i)
                drm_ht_remove(&tfile->ref_hash[i]);
 
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
        ttm_object_file_unref(&tfile);
 }
 EXPORT_SYMBOL(ttm_object_file_release);
@@ -404,7 +422,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
        if (unlikely(tfile == NULL))
                return NULL;
 
-       rwlock_init(&tfile->lock);
+       spin_lock_init(&tfile->lock);
        tfile->tdev = tdev;
        kref_init(&tfile->refcount);
        INIT_LIST_HEAD(&tfile->ref_list);
index 210d50365162d39d8b2048ba3d8c0e567ed95bf9..9af99084b344413dcb07c2a368916bff647fc119 100644 (file)
@@ -170,9 +170,8 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
                ttm_tt_unbind(ttm);
        }
 
-       if (ttm->state == tt_unbound) {
-               ttm->bdev->driver->ttm_tt_unpopulate(ttm);
-       }
+       if (ttm->state == tt_unbound)
+               ttm_tt_unpopulate(ttm);
 
        if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
            ttm->swap_storage)
@@ -362,7 +361,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                page_cache_release(to_page);
        }
 
-       ttm->bdev->driver->ttm_tt_unpopulate(ttm);
+       ttm_tt_unpopulate(ttm);
        ttm->swap_storage = swap_storage;
        ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
        if (persistent_swap_storage)
@@ -375,3 +374,23 @@ out_err:
 
        return ret;
 }
+
+static void ttm_tt_clear_mapping(struct ttm_tt *ttm)
+{
+       pgoff_t i;
+       struct page **page = ttm->pages;
+
+       for (i = 0; i < ttm->num_pages; ++i) {
+               (*page)->mapping = NULL;
+               (*page++)->index = 0;
+       }
+}
+
+void ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+       if (ttm->state == tt_unpopulated)
+               return;
+
+       ttm_tt_clear_mapping(ttm);
+       ttm->bdev->driver->ttm_tt_unpopulate(ttm);
+}
index 97e9d614700f7f6d475b55c7ecae8a513e54afb4..dbadd49e4c4a62bdd32c83473ad3751452e4033d 100644 (file)
@@ -403,15 +403,17 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
        int i;
        int ret = 0;
 
+       drm_modeset_lock_all(fb->dev);
+
        if (!ufb->active_16)
-               return 0;
+               goto unlock;
 
        if (ufb->obj->base.import_attach) {
                ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf,
                                               0, ufb->obj->base.size,
                                               DMA_FROM_DEVICE);
                if (ret)
-                       return ret;
+                       goto unlock;
        }
 
        for (i = 0; i < num_clips; i++) {
@@ -419,7 +421,7 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
                                  clips[i].x2 - clips[i].x1,
                                  clips[i].y2 - clips[i].y1);
                if (ret)
-                       break;
+                       goto unlock;
        }
 
        if (ufb->obj->base.import_attach) {
@@ -427,6 +429,10 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
                                       0, ufb->obj->base.size,
                                       DMA_FROM_DEVICE);
        }
+
+ unlock:
+       drm_modeset_unlock_all(fb->dev);
+
        return ret;
 }
 
index 652f9b43ec9dcfc1c8a6e383dcc443fa9ef2db94..a18479c6b6dae3dfdbb3d3e6e238f129dc79a3ad 100644 (file)
@@ -60,7 +60,7 @@
        dev_priv->dma_low += 8;                                 \
 }
 
-#define via_flush_write_combine() DRM_MEMORYBARRIER()
+#define via_flush_write_combine() mb()
 
 #define VIA_OUT_RING_QW(w1, w2)        do {            \
        *vb++ = (w1);                           \
@@ -234,13 +234,13 @@ static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *fil
 
        switch (init->func) {
        case VIA_INIT_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
+               if (!capable(CAP_SYS_ADMIN))
                        retcode = -EPERM;
                else
                        retcode = via_initialize(dev, dev_priv, init);
                break;
        case VIA_CLEANUP_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
+               if (!capable(CAP_SYS_ADMIN))
                        retcode = -EPERM;
                else
                        retcode = via_dma_cleanup(dev);
@@ -273,7 +273,7 @@ static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *c
        if (cmd->size > VIA_PCI_BUF_SIZE)
                return -ENOMEM;
 
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
                return -EFAULT;
 
        /*
@@ -346,7 +346,7 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device *dev,
 
        if (cmd->size > VIA_PCI_BUF_SIZE)
                return -ENOMEM;
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
                return -EFAULT;
 
        if ((ret =
@@ -543,7 +543,7 @@ static void via_cmdbuf_start(drm_via_private_t *dev_priv)
 
        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-       DRM_WRITEMEMORYBARRIER();
+       wmb();
        VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
        VIA_READ(VIA_REG_TRANSPACE);
 
index 8b0f25904e6db4edf754c9c18ab58077bfb0930e..ba33cf679180498a4ecd29260c16ee0570d2f480 100644 (file)
@@ -217,7 +217,7 @@ via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
        VIA_WRITE(VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
        VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
        VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
-       DRM_WRITEMEMORYBARRIER();
+       wmb();
        VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
        VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
 }
@@ -338,7 +338,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 
                blitq->blits[cur]->aborted = blitq->aborting;
                blitq->done_blit_handle++;
-               DRM_WAKEUP(blitq->blit_queue + cur);
+               wake_up(blitq->blit_queue + cur);
 
                cur++;
                if (cur >= VIA_NUM_BLIT_SLOTS)
@@ -363,7 +363,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 
                via_abort_dmablit(dev, engine);
                blitq->aborting = 1;
-               blitq->end = jiffies + DRM_HZ;
+               blitq->end = jiffies + HZ;
        }
 
        if (!blitq->is_active) {
@@ -372,7 +372,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
                        blitq->is_active = 1;
                        blitq->cur = cur;
                        blitq->num_outstanding--;
-                       blitq->end = jiffies + DRM_HZ;
+                       blitq->end = jiffies + HZ;
                        if (!timer_pending(&blitq->poll_timer))
                                mod_timer(&blitq->poll_timer, jiffies + 1);
                } else {
@@ -436,7 +436,7 @@ via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
        int ret = 0;
 
        if (via_dmablit_active(blitq, engine, handle, &queue)) {
-               DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, *queue, 3 * HZ,
                            !via_dmablit_active(blitq, engine, handle, NULL));
        }
        DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
@@ -521,7 +521,7 @@ via_dmablit_workqueue(struct work_struct *work)
 
                spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
 
-               DRM_WAKEUP(&blitq->busy_queue);
+               wake_up(&blitq->busy_queue);
 
                via_free_sg_info(dev->pdev, cur_sg);
                kfree(cur_sg);
@@ -561,8 +561,8 @@ via_init_dmablit(struct drm_device *dev)
                blitq->aborting = 0;
                spin_lock_init(&blitq->blit_lock);
                for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j)
-                       DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
-               DRM_INIT_WAITQUEUE(&blitq->busy_queue);
+                       init_waitqueue_head(blitq->blit_queue + j);
+               init_waitqueue_head(&blitq->busy_queue);
                INIT_WORK(&blitq->wq, via_dmablit_workqueue);
                setup_timer(&blitq->poll_timer, via_dmablit_timer,
                                (unsigned long)blitq);
@@ -688,7 +688,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
        while (blitq->num_free == 0) {
                spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
 
-               DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
+               DRM_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
                if (ret)
                        return (-EINTR == ret) ? -EAGAIN : ret;
 
@@ -713,7 +713,7 @@ via_dmablit_release_slot(drm_via_blitq_t *blitq)
        spin_lock_irqsave(&blitq->blit_lock, irqsave);
        blitq->num_free++;
        spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       DRM_WAKEUP(&blitq->busy_queue);
+       wake_up(&blitq->busy_queue);
 }
 
 /*
index 92684a9b7e3414f69cdc76f2d2ef82d286cda734..50abc2adfaee495730337a94b4fc931bcdd40f37 100644 (file)
@@ -46,7 +46,7 @@ static int via_driver_open(struct drm_device *dev, struct drm_file *file)
        return 0;
 }
 
-void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
+static void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct via_file_private *file_priv = file->driver_priv;
 
index a811ef2b505f1b25de22921a55ad8309d6a33d6a..ad0273256beb58b3bd4ff65c3c6b230427543a17 100644 (file)
@@ -138,7 +138,7 @@ extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int via_enable_vblank(struct drm_device *dev, int crtc);
 extern void via_disable_vblank(struct drm_device *dev, int crtc);
 
-extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t via_driver_irq_handler(int irq, void *arg);
 extern void via_driver_irq_preinstall(struct drm_device *dev);
 extern int via_driver_irq_postinstall(struct drm_device *dev);
 extern void via_driver_irq_uninstall(struct drm_device *dev);
index ac98964297cfffcf4939817629fbd51d17f32dd7..1319433816d3cd4743c7eadbcf073d8703c6476b 100644 (file)
@@ -104,7 +104,7 @@ u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
        return atomic_read(&dev_priv->vbl_received);
 }
 
-irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t via_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -138,7 +138,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
        for (i = 0; i < dev_priv->num_irqs; ++i) {
                if (status & cur_irq->pending_mask) {
                        atomic_inc(&cur_irq->irq_received);
-                       DRM_WAKEUP(&cur_irq->irq_queue);
+                       wake_up(&cur_irq->irq_queue);
                        handled = 1;
                        if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
                                via_dmablit_handler(dev, 0, 1);
@@ -239,12 +239,12 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence
        cur_irq = dev_priv->via_irqs + real_irq;
 
        if (masks[real_irq][2] && !force_sequence) {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
                            ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
                             masks[irq][4]));
                cur_irq_sequence = atomic_read(&cur_irq->irq_received);
        } else {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
                            (((cur_irq_sequence =
                               atomic_read(&cur_irq->irq_received)) -
                              *sequence) <= (1 << 23)));
@@ -287,7 +287,7 @@ void via_driver_irq_preinstall(struct drm_device *dev)
                        atomic_set(&cur_irq->irq_received, 0);
                        cur_irq->enable_mask = dev_priv->irq_masks[i][0];
                        cur_irq->pending_mask = dev_priv->irq_masks[i][1];
-                       DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+                       init_waitqueue_head(&cur_irq->irq_queue);
                        dev_priv->irq_enable_mask |= cur_irq->enable_mask;
                        dev_priv->irq_pending_mask |= cur_irq->pending_mask;
                        cur_irq++;
index 6569efa2ff6ea4e82f2e91649dc9fdec0964b107..a9ffbad1cfdd87fe9d4c4bf14ce8902ca07f4f50 100644 (file)
@@ -36,7 +36,7 @@ void via_init_futex(drm_via_private_t *dev_priv)
        DRM_DEBUG("\n");
 
        for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
+               init_waitqueue_head(&(dev_priv->decoder_queue[i]));
                XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
        }
 }
@@ -58,7 +58,7 @@ void via_release_futex(drm_via_private_t *dev_priv, int context)
                if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
                        if (_DRM_LOCK_IS_HELD(*lock)
                            && (*lock & _DRM_LOCK_CONT)) {
-                               DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
+                               wake_up(&(dev_priv->decoder_queue[i]));
                        }
                        *lock = 0;
                }
@@ -83,10 +83,10 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_
        switch (fx->func) {
        case VIA_FUTEX_WAIT:
                DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
-                           (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val);
+                           (fx->ms / 10) * (HZ / 100), *lock != fx->val);
                return ret;
        case VIA_FUTEX_WAKE:
-               DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock]));
+               wake_up(&(dev_priv->decoder_queue[fx->lock]));
                return 0;
        }
        return 0;
index 9f8b690bcf52c97e24db7c6a515f9be185b30321..458cdf6d81e8b91781af5d1c18d663c133c5f455 100644 (file)
@@ -6,6 +6,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
            vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
            vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
            vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
-           vmwgfx_surface.o vmwgfx_prime.o
+           vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
index d0e085ee82498679cdde540f2ce87c539fa4856b..d95335cb90bd4f30f7b7cdcf601028611986d802 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "svga_reg.h"
 
+typedef uint32 PPN;
+typedef __le64 PPN64;
 
 /*
  * 3D Hardware Version
@@ -71,6 +73,9 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
 #define SVGA3D_MAX_CONTEXT_IDS                  256
 #define SVGA3D_MAX_SURFACE_IDS                  (32 * 1024)
 
+#define SVGA3D_NUM_TEXTURE_UNITS                32
+#define SVGA3D_NUM_LIGHTS                       8
+
 /*
  * Surface formats.
  *
@@ -81,6 +86,7 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
  */
 
 typedef enum SVGA3dSurfaceFormat {
+   SVGA3D_FORMAT_MIN                   = 0,
    SVGA3D_FORMAT_INVALID               = 0,
 
    SVGA3D_X8R8G8B8                     = 1,
@@ -134,12 +140,6 @@ typedef enum SVGA3dSurfaceFormat {
    SVGA3D_RG_S10E5                     = 35,
    SVGA3D_RG_S23E8                     = 36,
 
-   /*
-    * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
-    * the most efficient format to use when creating new surfaces
-    * expressly for index or vertex data.
-    */
-
    SVGA3D_BUFFER                       = 37,
 
    SVGA3D_Z_D24X8                      = 38,
@@ -159,15 +159,114 @@ typedef enum SVGA3dSurfaceFormat {
    /* Video format with alpha */
    SVGA3D_AYUV                         = 45,
 
+   SVGA3D_R32G32B32A32_TYPELESS        = 46,
+   SVGA3D_R32G32B32A32_FLOAT           = 25,
+   SVGA3D_R32G32B32A32_UINT            = 47,
+   SVGA3D_R32G32B32A32_SINT            = 48,
+   SVGA3D_R32G32B32_TYPELESS           = 49,
+   SVGA3D_R32G32B32_FLOAT              = 50,
+   SVGA3D_R32G32B32_UINT               = 51,
+   SVGA3D_R32G32B32_SINT               = 52,
+   SVGA3D_R16G16B16A16_TYPELESS        = 53,
+   SVGA3D_R16G16B16A16_FLOAT           = 24,
+   SVGA3D_R16G16B16A16_UNORM           = 41,
+   SVGA3D_R16G16B16A16_UINT            = 54,
+   SVGA3D_R16G16B16A16_SNORM           = 55,
+   SVGA3D_R16G16B16A16_SINT            = 56,
+   SVGA3D_R32G32_TYPELESS              = 57,
+   SVGA3D_R32G32_FLOAT                 = 36,
+   SVGA3D_R32G32_UINT                  = 58,
+   SVGA3D_R32G32_SINT                  = 59,
+   SVGA3D_R32G8X24_TYPELESS            = 60,
+   SVGA3D_D32_FLOAT_S8X24_UINT         = 61,
+   SVGA3D_R32_FLOAT_X8X24_TYPELESS     = 62,
+   SVGA3D_X32_TYPELESS_G8X24_UINT      = 63,
+   SVGA3D_R10G10B10A2_TYPELESS         = 64,
+   SVGA3D_R10G10B10A2_UNORM            = 26,
+   SVGA3D_R10G10B10A2_UINT             = 65,
+   SVGA3D_R11G11B10_FLOAT              = 66,
+   SVGA3D_R8G8B8A8_TYPELESS            = 67,
+   SVGA3D_R8G8B8A8_UNORM               = 68,
+   SVGA3D_R8G8B8A8_UNORM_SRGB          = 69,
+   SVGA3D_R8G8B8A8_UINT                = 70,
+   SVGA3D_R8G8B8A8_SNORM               = 28,
+   SVGA3D_R8G8B8A8_SINT                = 71,
+   SVGA3D_R16G16_TYPELESS              = 72,
+   SVGA3D_R16G16_FLOAT                 = 35,
+   SVGA3D_R16G16_UNORM                 = 40,
+   SVGA3D_R16G16_UINT                  = 73,
+   SVGA3D_R16G16_SNORM                 = 39,
+   SVGA3D_R16G16_SINT                  = 74,
+   SVGA3D_R32_TYPELESS                 = 75,
+   SVGA3D_D32_FLOAT                    = 76,
+   SVGA3D_R32_FLOAT                    = 34,
+   SVGA3D_R32_UINT                     = 77,
+   SVGA3D_R32_SINT                     = 78,
+   SVGA3D_R24G8_TYPELESS               = 79,
+   SVGA3D_D24_UNORM_S8_UINT            = 80,
+   SVGA3D_R24_UNORM_X8_TYPELESS        = 81,
+   SVGA3D_X24_TYPELESS_G8_UINT         = 82,
+   SVGA3D_R8G8_TYPELESS                = 83,
+   SVGA3D_R8G8_UNORM                   = 84,
+   SVGA3D_R8G8_UINT                    = 85,
+   SVGA3D_R8G8_SNORM                   = 27,
+   SVGA3D_R8G8_SINT                    = 86,
+   SVGA3D_R16_TYPELESS                 = 87,
+   SVGA3D_R16_FLOAT                    = 33,
+   SVGA3D_D16_UNORM                    = 8,
+   SVGA3D_R16_UNORM                    = 88,
+   SVGA3D_R16_UINT                     = 89,
+   SVGA3D_R16_SNORM                    = 90,
+   SVGA3D_R16_SINT                     = 91,
+   SVGA3D_R8_TYPELESS                  = 92,
+   SVGA3D_R8_UNORM                     = 93,
+   SVGA3D_R8_UINT                      = 94,
+   SVGA3D_R8_SNORM                     = 95,
+   SVGA3D_R8_SINT                      = 96,
+   SVGA3D_A8_UNORM                     = 32,
+   SVGA3D_R1_UNORM                     = 97,
+   SVGA3D_R9G9B9E5_SHAREDEXP           = 98,
+   SVGA3D_R8G8_B8G8_UNORM              = 99,
+   SVGA3D_G8R8_G8B8_UNORM              = 100,
+   SVGA3D_BC1_TYPELESS                 = 101,
+   SVGA3D_BC1_UNORM                    = 15,
+   SVGA3D_BC1_UNORM_SRGB               = 102,
+   SVGA3D_BC2_TYPELESS                 = 103,
+   SVGA3D_BC2_UNORM                    = 17,
+   SVGA3D_BC2_UNORM_SRGB               = 104,
+   SVGA3D_BC3_TYPELESS                 = 105,
+   SVGA3D_BC3_UNORM                    = 19,
+   SVGA3D_BC3_UNORM_SRGB               = 106,
+   SVGA3D_BC4_TYPELESS                 = 107,
    SVGA3D_BC4_UNORM                    = 108,
+   SVGA3D_BC4_SNORM                    = 109,
+   SVGA3D_BC5_TYPELESS                 = 110,
    SVGA3D_BC5_UNORM                    = 111,
+   SVGA3D_BC5_SNORM                    = 112,
+   SVGA3D_B5G6R5_UNORM                 = 3,
+   SVGA3D_B5G5R5A1_UNORM               = 5,
+   SVGA3D_B8G8R8A8_UNORM               = 2,
+   SVGA3D_B8G8R8X8_UNORM               = 1,
+   SVGA3D_R10G10B10_XR_BIAS_A2_UNORM   = 113,
+   SVGA3D_B8G8R8A8_TYPELESS            = 114,
+   SVGA3D_B8G8R8A8_UNORM_SRGB          = 115,
+   SVGA3D_B8G8R8X8_TYPELESS            = 116,
+   SVGA3D_B8G8R8X8_UNORM_SRGB          = 117,
 
    /* Advanced D3D9 depth formats. */
    SVGA3D_Z_DF16                       = 118,
    SVGA3D_Z_DF24                       = 119,
    SVGA3D_Z_D24S8_INT                  = 120,
 
-   SVGA3D_FORMAT_MAX
+   /* Planar video formats. */
+   SVGA3D_YV12                         = 121,
+
+   /* Shader constant formats. */
+   SVGA3D_SURFACE_SHADERCONST_FLOAT    = 122,
+   SVGA3D_SURFACE_SHADERCONST_INT      = 123,
+   SVGA3D_SURFACE_SHADERCONST_BOOL     = 124,
+
+   SVGA3D_FORMAT_MAX                   = 125,
 } SVGA3dSurfaceFormat;
 
 typedef uint32 SVGA3dColor; /* a, r, g, b */
@@ -957,15 +1056,21 @@ typedef enum {
 } SVGA3dCubeFace;
 
 typedef enum {
+   SVGA3D_SHADERTYPE_INVALID                    = 0,
+   SVGA3D_SHADERTYPE_MIN                        = 1,
    SVGA3D_SHADERTYPE_VS                         = 1,
    SVGA3D_SHADERTYPE_PS                         = 2,
-   SVGA3D_SHADERTYPE_MAX
+   SVGA3D_SHADERTYPE_MAX                        = 3,
+   SVGA3D_SHADERTYPE_GS                         = 3,
 } SVGA3dShaderType;
 
+#define SVGA3D_NUM_SHADERTYPE (SVGA3D_SHADERTYPE_MAX - SVGA3D_SHADERTYPE_MIN)
+
 typedef enum {
    SVGA3D_CONST_TYPE_FLOAT                      = 0,
    SVGA3D_CONST_TYPE_INT                        = 1,
    SVGA3D_CONST_TYPE_BOOL                       = 2,
+   SVGA3D_CONST_TYPE_MAX
 } SVGA3dShaderConstType;
 
 #define SVGA3D_MAX_SURFACE_FACES                6
@@ -1056,9 +1161,74 @@ typedef enum {
 #define SVGA_3D_CMD_GENERATE_MIPMAPS       SVGA_3D_CMD_BASE + 31
 #define SVGA_3D_CMD_ACTIVATE_SURFACE       SVGA_3D_CMD_BASE + 40
 #define SVGA_3D_CMD_DEACTIVATE_SURFACE     SVGA_3D_CMD_BASE + 41
-#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 42
-
-#define SVGA_3D_CMD_FUTURE_MAX             2000
+#define SVGA_3D_CMD_SCREEN_DMA               1082
+#define SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE 1083
+#define SVGA_3D_CMD_OPEN_CONTEXT_SURFACE     1084
+
+#define SVGA_3D_CMD_LOGICOPS_BITBLT          1085
+#define SVGA_3D_CMD_LOGICOPS_TRANSBLT        1086
+#define SVGA_3D_CMD_LOGICOPS_STRETCHBLT      1087
+#define SVGA_3D_CMD_LOGICOPS_COLORFILL       1088
+#define SVGA_3D_CMD_LOGICOPS_ALPHABLEND      1089
+#define SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND  1090
+
+#define SVGA_3D_CMD_SET_OTABLE_BASE          1091
+#define SVGA_3D_CMD_READBACK_OTABLE          1092
+
+#define SVGA_3D_CMD_DEFINE_GB_MOB            1093
+#define SVGA_3D_CMD_DESTROY_GB_MOB           1094
+#define SVGA_3D_CMD_REDEFINE_GB_MOB          1095
+#define SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING    1096
+
+#define SVGA_3D_CMD_DEFINE_GB_SURFACE        1097
+#define SVGA_3D_CMD_DESTROY_GB_SURFACE       1098
+#define SVGA_3D_CMD_BIND_GB_SURFACE          1099
+#define SVGA_3D_CMD_COND_BIND_GB_SURFACE     1100
+#define SVGA_3D_CMD_UPDATE_GB_IMAGE          1101
+#define SVGA_3D_CMD_UPDATE_GB_SURFACE        1102
+#define SVGA_3D_CMD_READBACK_GB_IMAGE        1103
+#define SVGA_3D_CMD_READBACK_GB_SURFACE      1104
+#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE      1105
+#define SVGA_3D_CMD_INVALIDATE_GB_SURFACE    1106
+
+#define SVGA_3D_CMD_DEFINE_GB_CONTEXT        1107
+#define SVGA_3D_CMD_DESTROY_GB_CONTEXT       1108
+#define SVGA_3D_CMD_BIND_GB_CONTEXT          1109
+#define SVGA_3D_CMD_READBACK_GB_CONTEXT      1110
+#define SVGA_3D_CMD_INVALIDATE_GB_CONTEXT    1111
+
+#define SVGA_3D_CMD_DEFINE_GB_SHADER         1112
+#define SVGA_3D_CMD_DESTROY_GB_SHADER        1113
+#define SVGA_3D_CMD_BIND_GB_SHADER           1114
+
+#define SVGA_3D_CMD_SET_OTABLE_BASE64        1115
+
+#define SVGA_3D_CMD_BEGIN_GB_QUERY           1116
+#define SVGA_3D_CMD_END_GB_QUERY             1117
+#define SVGA_3D_CMD_WAIT_FOR_GB_QUERY        1118
+
+#define SVGA_3D_CMD_NOP                      1119
+
+#define SVGA_3D_CMD_ENABLE_GART              1120
+#define SVGA_3D_CMD_DISABLE_GART             1121
+#define SVGA_3D_CMD_MAP_MOB_INTO_GART        1122
+#define SVGA_3D_CMD_UNMAP_GART_RANGE         1123
+
+#define SVGA_3D_CMD_DEFINE_GB_SCREENTARGET   1124
+#define SVGA_3D_CMD_DESTROY_GB_SCREENTARGET  1125
+#define SVGA_3D_CMD_BIND_GB_SCREENTARGET     1126
+#define SVGA_3D_CMD_UPDATE_GB_SCREENTARGET   1127
+
+#define SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL   1128
+#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129
+
+#define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130
+
+#define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
+#define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136
+
+#define SVGA_3D_CMD_MAX                      1142
+#define SVGA_3D_CMD_FUTURE_MAX               3000
 
 /*
  * Common substructures used in multiple FIFO commands:
@@ -1749,6 +1919,495 @@ struct {
 } SVGA3dCmdGenerateMipmaps;             /* SVGA_3D_CMD_GENERATE_MIPMAPS */
 
 
+/*
+ * Guest-backed surface definitions.
+ */
+
+typedef uint32 SVGAMobId;
+
+typedef enum SVGAMobFormat {
+   SVGA3D_MOBFMT_INVALID = SVGA3D_INVALID_ID,
+   SVGA3D_MOBFMT_PTDEPTH_0 = 0,
+   SVGA3D_MOBFMT_PTDEPTH_1 = 1,
+   SVGA3D_MOBFMT_PTDEPTH_2 = 2,
+   SVGA3D_MOBFMT_RANGE     = 3,
+   SVGA3D_MOBFMT_PTDEPTH64_0 = 4,
+   SVGA3D_MOBFMT_PTDEPTH64_1 = 5,
+   SVGA3D_MOBFMT_PTDEPTH64_2 = 6,
+   SVGA3D_MOBFMT_MAX,
+} SVGAMobFormat;
+
+/*
+ * Sizes of opaque types.
+ */
+
+#define SVGA3D_OTABLE_MOB_ENTRY_SIZE 16
+#define SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE 8
+#define SVGA3D_OTABLE_SURFACE_ENTRY_SIZE 64
+#define SVGA3D_OTABLE_SHADER_ENTRY_SIZE 16
+#define SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE 64
+#define SVGA3D_CONTEXT_DATA_SIZE 16384
+
+/*
+ * SVGA3dCmdSetOTableBase --
+ *
+ * This command allows the guest to specify the base PPN of the
+ * specified object table.
+ */
+
+typedef enum {
+   SVGA_OTABLE_MOB           = 0,
+   SVGA_OTABLE_MIN           = 0,
+   SVGA_OTABLE_SURFACE       = 1,
+   SVGA_OTABLE_CONTEXT       = 2,
+   SVGA_OTABLE_SHADER        = 3,
+   SVGA_OTABLE_SCREEN_TARGET = 4,
+   SVGA_OTABLE_DX9_MAX       = 5,
+   SVGA_OTABLE_MAX           = 8
+} SVGAOTableType;
+
+typedef
+struct {
+   SVGAOTableType type;
+   PPN baseAddress;
+   uint32 sizeInBytes;
+   uint32 validSizeInBytes;
+   SVGAMobFormat ptDepth;
+}
+__attribute__((__packed__))
+SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */
+
+typedef
+struct {
+   SVGAOTableType type;
+   PPN64 baseAddress;
+   uint32 sizeInBytes;
+   uint32 validSizeInBytes;
+   SVGAMobFormat ptDepth;
+}
+__attribute__((__packed__))
+SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
+
+typedef
+struct {
+   SVGAOTableType type;
+}
+__attribute__((__packed__))
+SVGA3dCmdReadbackOTable;  /* SVGA_3D_CMD_READBACK_OTABLE */
+
+/*
+ * Define a memory object (Mob) in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBMob {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
+
+
+/*
+ * Destroys an object in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBMob {
+   SVGAMobId mobid;
+}
+__attribute__((__packed__))
+SVGA3dCmdDestroyGBMob;   /* SVGA_3D_CMD_DESTROY_GB_MOB */
+
+/*
+ * Redefine an object in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdRedefineGBMob {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */
+
+/*
+ * Define a memory object (Mob) in the OTable with a PPN64 base.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBMob64 {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN64 base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
+
+/*
+ * Redefine an object in the OTable with PPN64 base.
+ */
+
+typedef
+struct SVGA3dCmdRedefineGBMob64 {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN64 base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
+
+/*
+ * Notification that the page tables have been modified.
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBMobMapping {
+   SVGAMobId mobid;
+}
+__attribute__((__packed__))
+SVGA3dCmdUpdateGBMobMapping;   /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
+
+/*
+ * Define a guest-backed surface.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBSurface {
+   uint32 sid;
+   SVGA3dSurfaceFlags surfaceFlags;
+   SVGA3dSurfaceFormat format;
+   uint32 numMipLevels;
+   uint32 multisampleCount;
+   SVGA3dTextureFilter autogenFilter;
+   SVGA3dSize size;
+} SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
+
+/*
+ * Destroy a guest-backed surface.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBSurface {
+   uint32 sid;
+} SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
+
+/*
+ * Bind a guest-backed surface to an object.
+ */
+
+typedef
+struct SVGA3dCmdBindGBSurface {
+   uint32 sid;
+   SVGAMobId mobid;
+} SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
+
+/*
+ * Conditionally bind a mob to a guest backed surface if testMobid
+ * matches the currently bound mob.  Optionally issue a readback on
+ * the surface while it is still bound to the old mobid if the mobid
+ * is changed by this command.
+ */
+
+#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_READBACK (1 << 0)
+
+typedef
+struct{
+   uint32 sid;
+   SVGAMobId testMobid;
+   SVGAMobId mobid;
+   uint32 flags;
+}
+SVGA3dCmdCondBindGBSurface;          /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
+
+/*
+ * Update an image in a guest-backed surface.
+ * (Inform the device that the guest-contents have been updated.)
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBImage {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+} SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
+
+/*
+ * Update an entire guest-backed surface.
+ * (Inform the device that the guest-contents have been updated.)
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBSurface {
+   uint32 sid;
+} SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
+
+/*
+ * Readback an image in a guest-backed surface.
+ * (Request the device to flush the dirty contents into the guest.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBImage {
+   SVGA3dSurfaceImageId image;
+} SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
+
+/*
+ * Readback an entire guest-backed surface.
+ * (Request the device to flush the dirty contents into the guest.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBSurface {
+   uint32 sid;
+} SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
+
+/*
+ * Readback a sub rect of an image in a guest-backed surface.  After
+ * issuing this command the driver is required to issue an update call
+ * of the same region before issuing any other commands that reference
+ * this surface or rendering is not guaranteed.
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBImagePartial {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+   uint32 invertBox;
+}
+SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
+
+/*
+ * Invalidate an image in a guest-backed surface.
+ * (Notify the device that the contents can be lost.)
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBImage {
+   SVGA3dSurfaceImageId image;
+} SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
+
+/*
+ * Invalidate an entire guest-backed surface.
+ * (Notify the device that the contents if all images can be lost.)
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBSurface {
+   uint32 sid;
+} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
+
+/*
+ * Invalidate a sub rect of an image in a guest-backed surface.  After
+ * issuing this command the driver is required to issue an update call
+ * of the same region before issuing any other commands that reference
+ * this surface or rendering is not guaranteed.
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBImagePartial {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+   uint32 invertBox;
+}
+SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
+
+/*
+ * Define a guest-backed context.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBContext {
+   uint32 cid;
+} SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
+
+/*
+ * Destroy a guest-backed context.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBContext {
+   uint32 cid;
+} SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
+
+/*
+ * Bind a guest-backed context.
+ *
+ * validContents should be set to 0 for new contexts,
+ * and 1 if this is an old context which is getting paged
+ * back on to the device.
+ *
+ * For new contexts, it is recommended that the driver
+ * issue commands to initialize all interesting state
+ * prior to rendering.
+ */
+
+typedef
+struct SVGA3dCmdBindGBContext {
+   uint32 cid;
+   SVGAMobId mobid;
+   uint32 validContents;
+} SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
+
+/*
+ * Readback a guest-backed context.
+ * (Request that the device flush the contents back into guest memory.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBContext {
+   uint32 cid;
+} SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
+
+/*
+ * Invalidate a guest-backed context.
+ */
+typedef
+struct SVGA3dCmdInvalidateGBContext {
+   uint32 cid;
+} SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
+
+/*
+ * Define a guest-backed shader.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBShader {
+   uint32 shid;
+   SVGA3dShaderType type;
+   uint32 sizeInBytes;
+} SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
+
+/*
+ * Bind a guest-backed shader.
+ */
+
+typedef struct SVGA3dCmdBindGBShader {
+   uint32 shid;
+   SVGAMobId mobid;
+   uint32 offsetInBytes;
+} SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
+
+/*
+ * Destroy a guest-backed shader.
+ */
+
+typedef struct SVGA3dCmdDestroyGBShader {
+   uint32 shid;
+} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
+
+typedef
+struct {
+   uint32                  cid;
+   uint32                  regStart;
+   SVGA3dShaderType        shaderType;
+   SVGA3dShaderConstType   constType;
+
+   /*
+    * Followed by a variable number of shader constants.
+    *
+    * Note that FLOAT and INT constants are 4-dwords in length, while
+    * BOOL constants are 1-dword in length.
+    */
+} SVGA3dCmdSetGBShaderConstInline;
+/* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+} SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAMobId mobid;
+   uint32 offset;
+} SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
+
+
+/*
+ * SVGA_3D_CMD_WAIT_FOR_GB_QUERY --
+ *
+ *    The semantics of this command are identical to the
+ *    SVGA_3D_CMD_WAIT_FOR_QUERY except that the results are written
+ *    to a Mob instead of a GMR.
+ */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAMobId mobid;
+   uint32 offset;
+} SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
+
+typedef
+struct {
+   SVGAMobId mobid;
+   uint32 fbOffset;
+   uint32 initalized;
+}
+SVGA3dCmdEnableGart;              /* SVGA_3D_CMD_ENABLE_GART */
+
+typedef
+struct {
+   SVGAMobId mobid;
+   uint32 gartOffset;
+}
+SVGA3dCmdMapMobIntoGart;          /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
+
+
+typedef
+struct {
+   uint32 gartOffset;
+   uint32 numPages;
+}
+SVGA3dCmdUnmapGartRange;          /* SVGA_3D_CMD_UNMAP_GART_RANGE */
+
+
+/*
+ * Screen Targets
+ */
+#define SVGA_STFLAG_PRIMARY (1 << 0)
+
+typedef
+struct {
+   uint32 stid;
+   uint32 width;
+   uint32 height;
+   int32 xRoot;
+   int32 yRoot;
+   uint32 flags;
+}
+SVGA3dCmdDefineGBScreenTarget;    /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+}
+SVGA3dCmdDestroyGBScreenTarget;  /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+   SVGA3dSurfaceImageId image;
+}
+SVGA3dCmdBindGBScreenTarget;  /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+   SVGA3dBox box;
+}
+SVGA3dCmdUpdateGBScreenTarget;  /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
+
 /*
  * Capability query index.
  *
@@ -1879,10 +2538,41 @@ typedef enum {
    SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM              = 83,
 
    /*
-    * Don't add new caps into the previous section; the values in this
-    * enumeration must not change. You can put new values right before
-    * SVGA3D_DEVCAP_MAX.
+    * Deprecated.
     */
+   SVGA3D_DEVCAP_VGPU10                            = 84,
+
+   /*
+    * This contains several SVGA_3D_CAPS_VIDEO_DECODE elements
+    * ored together, one for every type of video decoding supported.
+    */
+   SVGA3D_DEVCAP_VIDEO_DECODE                      = 85,
+
+   /*
+    * This contains several SVGA_3D_CAPS_VIDEO_PROCESS elements
+    * ored together, one for every type of video processing supported.
+    */
+   SVGA3D_DEVCAP_VIDEO_PROCESS                     = 86,
+
+   SVGA3D_DEVCAP_LINE_AA                           = 87,  /* boolean */
+   SVGA3D_DEVCAP_LINE_STIPPLE                      = 88,  /* boolean */
+   SVGA3D_DEVCAP_MAX_LINE_WIDTH                    = 89,  /* float */
+   SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH                 = 90,  /* float */
+
+   SVGA3D_DEVCAP_SURFACEFMT_YV12                   = 91,
+
+   /*
+    * Does the host support the SVGA logic ops commands?
+    */
+   SVGA3D_DEVCAP_LOGICOPS                          = 92,
+
+   /*
+    * What support does the host have for screen targets?
+    *
+    * See the SVGA3D_SCREENTARGET_CAP bits below.
+    */
+   SVGA3D_DEVCAP_SCREENTARGETS                     = 93,
+
    SVGA3D_DEVCAP_MAX                                  /* This must be the last index. */
 } SVGA3dDevCapIndex;
 
index 01f63cb49678f6971e5c704bbb67c77cc51df4ed..71defa4d2d7528a247b8e985a7b14cd1197e2a58 100644 (file)
@@ -169,7 +169,10 @@ enum {
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
    SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
    SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
-   SVGA_REG_TOP = 48,               /* Must be 1 more than the last register */
+   SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,   /* Max primary memory */
+   SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */
+   SVGA_REG_DEV_CAP = 52,           /* Write dev cap index, read value */
+   SVGA_REG_TOP = 53,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
@@ -431,7 +434,10 @@ struct SVGASignedPoint {
 #define SVGA_CAP_TRACES             0x00200000
 #define SVGA_CAP_GMR2               0x00400000
 #define SVGA_CAP_SCREEN_OBJECT_2    0x00800000
-
+#define SVGA_CAP_COMMAND_BUFFERS    0x01000000
+#define SVGA_CAP_DEAD1              0x02000000
+#define SVGA_CAP_CMD_BUFFERS_2      0x04000000
+#define SVGA_CAP_GBOBJECTS          0x08000000
 
 /*
  * FIFO register indices.
index 0489c61524826f2e2b673628783393639f0c591e..6327cfc36805f46364402a004ce76cd9bb19ecd5 100644 (file)
@@ -40,6 +40,10 @@ static uint32_t vram_ne_placement_flags = TTM_PL_FLAG_VRAM |
 static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM |
        TTM_PL_FLAG_CACHED;
 
+static uint32_t sys_ne_placement_flags = TTM_PL_FLAG_SYSTEM |
+       TTM_PL_FLAG_CACHED |
+       TTM_PL_FLAG_NO_EVICT;
+
 static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR |
        TTM_PL_FLAG_CACHED;
 
@@ -47,6 +51,9 @@ static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
        TTM_PL_FLAG_CACHED |
        TTM_PL_FLAG_NO_EVICT;
 
+static uint32_t mob_placement_flags = VMW_PL_FLAG_MOB |
+       TTM_PL_FLAG_CACHED;
+
 struct ttm_placement vmw_vram_placement = {
        .fpfn = 0,
        .lpfn = 0,
@@ -116,16 +123,26 @@ struct ttm_placement vmw_sys_placement = {
        .busy_placement = &sys_placement_flags
 };
 
+struct ttm_placement vmw_sys_ne_placement = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .num_placement = 1,
+       .placement = &sys_ne_placement_flags,
+       .num_busy_placement = 1,
+       .busy_placement = &sys_ne_placement_flags
+};
+
 static uint32_t evictable_placement_flags[] = {
        TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
        TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
-       VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+       VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
+       VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
 };
 
 struct ttm_placement vmw_evictable_placement = {
        .fpfn = 0,
        .lpfn = 0,
-       .num_placement = 3,
+       .num_placement = 4,
        .placement = evictable_placement_flags,
        .num_busy_placement = 1,
        .busy_placement = &sys_placement_flags
@@ -140,10 +157,21 @@ struct ttm_placement vmw_srf_placement = {
        .busy_placement = gmr_vram_placement_flags
 };
 
+struct ttm_placement vmw_mob_placement = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .num_placement = 1,
+       .num_busy_placement = 1,
+       .placement = &mob_placement_flags,
+       .busy_placement = &mob_placement_flags
+};
+
 struct vmw_ttm_tt {
        struct ttm_dma_tt dma_ttm;
        struct vmw_private *dev_priv;
        int gmr_id;
+       struct vmw_mob *mob;
+       int mem_type;
        struct sg_table sgt;
        struct vmw_sg_table vsgt;
        uint64_t sg_alloc_size;
@@ -244,6 +272,7 @@ void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt,
                viter->dma_address = &__vmw_piter_dma_addr;
                viter->page = &__vmw_piter_non_sg_page;
                viter->addrs = vsgt->addrs;
+               viter->pages = vsgt->pages;
                break;
        case vmw_dma_map_populate:
        case vmw_dma_map_bind:
@@ -424,6 +453,63 @@ static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt)
        vmw_tt->mapped = false;
 }
 
+
+/**
+ * vmw_bo_map_dma - Make sure buffer object pages are visible to the device
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer
+ * instead of a pointer to a struct vmw_ttm_backend as argument.
+ * Note that the buffer object must be either pinned or reserved before
+ * calling this function.
+ */
+int vmw_bo_map_dma(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       return vmw_ttm_map_dma(vmw_tt);
+}
+
+
+/**
+ * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer
+ * instead of a pointer to a struct vmw_ttm_backend as argument.
+ */
+void vmw_bo_unmap_dma(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       vmw_ttm_unmap_dma(vmw_tt);
+}
+
+
+/**
+ * vmw_bo_sg_table - Return a struct vmw_sg_table object for a
+ * TTM buffer object
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Returns a pointer to a struct vmw_sg_table object. The object should
+ * not be freed after use.
+ * Note that for the device addresses to be valid, the buffer object must
+ * either be reserved or pinned.
+ */
+const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       return &vmw_tt->vsgt;
+}
+
+
 static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
 {
        struct vmw_ttm_tt *vmw_be =
@@ -435,9 +521,27 @@ static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
                return ret;
 
        vmw_be->gmr_id = bo_mem->start;
+       vmw_be->mem_type = bo_mem->mem_type;
+
+       switch (bo_mem->mem_type) {
+       case VMW_PL_GMR:
+               return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
+                                   ttm->num_pages, vmw_be->gmr_id);
+       case VMW_PL_MOB:
+               if (unlikely(vmw_be->mob == NULL)) {
+                       vmw_be->mob =
+                               vmw_mob_create(ttm->num_pages);
+                       if (unlikely(vmw_be->mob == NULL))
+                               return -ENOMEM;
+               }
 
-       return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
-                           ttm->num_pages, vmw_be->gmr_id);
+               return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob,
+                                   &vmw_be->vsgt, ttm->num_pages,
+                                   vmw_be->gmr_id);
+       default:
+               BUG();
+       }
+       return 0;
 }
 
 static int vmw_ttm_unbind(struct ttm_tt *ttm)
@@ -445,7 +549,16 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
        struct vmw_ttm_tt *vmw_be =
                container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
 
-       vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
+       switch (vmw_be->mem_type) {
+       case VMW_PL_GMR:
+               vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
+               break;
+       case VMW_PL_MOB:
+               vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob);
+               break;
+       default:
+               BUG();
+       }
 
        if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind)
                vmw_ttm_unmap_dma(vmw_be);
@@ -453,6 +566,7 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
        return 0;
 }
 
+
 static void vmw_ttm_destroy(struct ttm_tt *ttm)
 {
        struct vmw_ttm_tt *vmw_be =
@@ -463,9 +577,14 @@ static void vmw_ttm_destroy(struct ttm_tt *ttm)
                ttm_dma_tt_fini(&vmw_be->dma_ttm);
        else
                ttm_tt_fini(ttm);
+
+       if (vmw_be->mob)
+               vmw_mob_destroy(vmw_be->mob);
+
        kfree(vmw_be);
 }
 
+
 static int vmw_ttm_populate(struct ttm_tt *ttm)
 {
        struct vmw_ttm_tt *vmw_tt =
@@ -500,6 +619,12 @@ static void vmw_ttm_unpopulate(struct ttm_tt *ttm)
        struct vmw_private *dev_priv = vmw_tt->dev_priv;
        struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
 
+
+       if (vmw_tt->mob) {
+               vmw_mob_destroy(vmw_tt->mob);
+               vmw_tt->mob = NULL;
+       }
+
        vmw_ttm_unmap_dma(vmw_tt);
        if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
                size_t size =
@@ -517,7 +642,7 @@ static struct ttm_backend_func vmw_ttm_func = {
        .destroy = vmw_ttm_destroy,
 };
 
-struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
@@ -530,6 +655,7 @@ struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
 
        vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
        vmw_be->dev_priv = container_of(bdev, struct vmw_private, bdev);
+       vmw_be->mob = NULL;
 
        if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
                ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bdev, size, page_flags,
@@ -546,12 +672,12 @@ out_no_init:
        return NULL;
 }
 
-int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+static int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
 {
        return 0;
 }
 
-int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                      struct ttm_mem_type_manager *man)
 {
        switch (type) {
@@ -571,6 +697,7 @@ int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                man->default_caching = TTM_PL_FLAG_CACHED;
                break;
        case VMW_PL_GMR:
+       case VMW_PL_MOB:
                /*
                 * "Guest Memory Regions" is an aperture like feature with
                 *  one slot per bo. There is an upper limit of the number of
@@ -589,7 +716,7 @@ int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
        return 0;
 }
 
-void vmw_evict_flags(struct ttm_buffer_object *bo,
+static void vmw_evict_flags(struct ttm_buffer_object *bo,
                     struct ttm_placement *placement)
 {
        *placement = vmw_sys_placement;
@@ -618,6 +745,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg
        switch (mem->mem_type) {
        case TTM_PL_SYSTEM:
        case VMW_PL_GMR:
+       case VMW_PL_MOB:
                return 0;
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
@@ -677,6 +805,38 @@ static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
                                  VMW_FENCE_WAIT_TIMEOUT);
 }
 
+/**
+ * vmw_move_notify - TTM move_notify_callback
+ *
+ * @bo:             The TTM buffer object about to move.
+ * @mem:            The truct ttm_mem_reg indicating to what memory
+ *                  region the move is taking place.
+ *
+ * Calls move_notify for all subsystems needing it.
+ * (currently only resources).
+ */
+static void vmw_move_notify(struct ttm_buffer_object *bo,
+                           struct ttm_mem_reg *mem)
+{
+       vmw_resource_move_notify(bo, mem);
+}
+
+
+/**
+ * vmw_swap_notify - TTM move_notify_callback
+ *
+ * @bo:             The TTM buffer object about to be swapped out.
+ */
+static void vmw_swap_notify(struct ttm_buffer_object *bo)
+{
+       struct ttm_bo_device *bdev = bo->bdev;
+
+       spin_lock(&bdev->fence_lock);
+       ttm_bo_wait(bo, false, false, false);
+       spin_unlock(&bdev->fence_lock);
+}
+
+
 struct ttm_bo_driver vmw_bo_driver = {
        .ttm_tt_create = &vmw_ttm_tt_create,
        .ttm_tt_populate = &vmw_ttm_populate,
@@ -691,8 +851,8 @@ struct ttm_bo_driver vmw_bo_driver = {
        .sync_obj_flush = vmw_sync_obj_flush,
        .sync_obj_unref = vmw_sync_obj_unref,
        .sync_obj_ref = vmw_sync_obj_ref,
-       .move_notify = NULL,
-       .swap_notify = NULL,
+       .move_notify = vmw_move_notify,
+       .swap_notify = vmw_swap_notify,
        .fault_reserve_notify = &vmw_ttm_fault_reserve_notify,
        .io_mem_reserve = &vmw_ttm_io_mem_reserve,
        .io_mem_free = &vmw_ttm_io_mem_free,
index 00ae0925aca87e17994288743e079852c0b14dc2..82c41daebc0e35be6fb3629b602a083a6520f6a3 100644 (file)
 struct vmw_user_context {
        struct ttm_base_object base;
        struct vmw_resource res;
+       struct vmw_ctx_binding_state cbs;
 };
 
+
+
+typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *);
+
 static void vmw_user_context_free(struct vmw_resource *res);
 static struct vmw_resource *
 vmw_user_context_base_to_res(struct ttm_base_object *base);
 
+static int vmw_gb_context_create(struct vmw_resource *res);
+static int vmw_gb_context_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_context_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_context_destroy(struct vmw_resource *res);
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi);
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi);
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi);
+static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
 static uint64_t vmw_user_context_size;
 
 static const struct vmw_user_resource_conv user_context_conv = {
@@ -62,6 +78,23 @@ static const struct vmw_res_func vmw_legacy_context_func = {
        .unbind = NULL
 };
 
+static const struct vmw_res_func vmw_gb_context_func = {
+       .res_type = vmw_res_context,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed contexts",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_context_create,
+       .destroy = vmw_gb_context_destroy,
+       .bind = vmw_gb_context_bind,
+       .unbind = vmw_gb_context_unbind
+};
+
+static const vmw_scrub_func vmw_scrub_funcs[vmw_ctx_binding_max] = {
+       [vmw_ctx_binding_shader] = vmw_context_scrub_shader,
+       [vmw_ctx_binding_rt] = vmw_context_scrub_render_target,
+       [vmw_ctx_binding_tex] = vmw_context_scrub_texture };
+
 /**
  * Context management:
  */
@@ -76,6 +109,16 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
        } *cmd;
 
 
+       if (res->func->destroy == vmw_gb_context_destroy) {
+               mutex_lock(&dev_priv->cmdbuf_mutex);
+               (void) vmw_gb_context_destroy(res);
+               if (dev_priv->pinned_bo != NULL &&
+                   !dev_priv->query_cid_valid)
+                       __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
+               mutex_unlock(&dev_priv->cmdbuf_mutex);
+               return;
+       }
+
        vmw_execbuf_release_pinned_bo(dev_priv);
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
        if (unlikely(cmd == NULL)) {
@@ -92,6 +135,33 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
        vmw_3d_resource_dec(dev_priv, false);
 }
 
+static int vmw_gb_context_init(struct vmw_private *dev_priv,
+                              struct vmw_resource *res,
+                              void (*res_free) (struct vmw_resource *res))
+{
+       int ret;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       ret = vmw_resource_init(dev_priv, res, true,
+                               res_free, &vmw_gb_context_func);
+       res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
+
+       if (unlikely(ret != 0)) {
+               if (res_free)
+                       res_free(res);
+               else
+                       kfree(res);
+               return ret;
+       }
+
+       memset(&uctx->cbs, 0, sizeof(uctx->cbs));
+       INIT_LIST_HEAD(&uctx->cbs.list);
+
+       vmw_resource_activate(res, vmw_hw_context_destroy);
+       return 0;
+}
+
 static int vmw_context_init(struct vmw_private *dev_priv,
                            struct vmw_resource *res,
                            void (*res_free) (struct vmw_resource *res))
@@ -103,6 +173,9 @@ static int vmw_context_init(struct vmw_private *dev_priv,
                SVGA3dCmdDefineContext body;
        } *cmd;
 
+       if (dev_priv->has_mob)
+               return vmw_gb_context_init(dev_priv, res, res_free);
+
        ret = vmw_resource_init(dev_priv, res, false,
                                res_free, &vmw_legacy_context_func);
 
@@ -154,6 +227,184 @@ struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
        return (ret == 0) ? res : NULL;
 }
 
+
+static int vmw_gb_context_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBContext body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a context id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       return ret;
+}
+
+static int vmw_gb_context_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBContext body;
+       } *cmd;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.validContents = res->backup_dirty;
+       res->backup_dirty = false;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+static int vmw_gb_context_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct ttm_buffer_object *bo = val_buf->bo;
+       struct vmw_fence_obj *fence;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBContext body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBContext body;
+       } *cmd2;
+       uint32_t submit_size;
+       uint8_t *cmd;
+
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_state_kill(&uctx->cbs);
+
+       submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
+
+       cmd = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "unbinding.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd2 = (void *) cmd;
+       if (readback) {
+               cmd1 = (void *) cmd;
+               cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
+               cmd1->header.size = sizeof(cmd1->body);
+               cmd1->body.cid = res->id;
+               cmd2 = (void *) (&cmd1[1]);
+       }
+       cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
+       cmd2->header.size = sizeof(cmd2->body);
+       cmd2->body.cid = res->id;
+       cmd2->body.mobid = SVGA3D_INVALID_ID;
+
+       vmw_fifo_commit(dev_priv, submit_size);
+       mutex_unlock(&dev_priv->binding_mutex);
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_context_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBContext body;
+       } *cmd;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       BUG_ON(!list_empty(&uctx->cbs.list));
+
+       if (likely(res->id == -1))
+               return 0;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "destruction.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (dev_priv->query_cid == res->id)
+               dev_priv->query_cid_valid = false;
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
 /**
  * User-space context management:
  */
@@ -272,3 +523,283 @@ out_unlock:
        return ret;
 
 }
+
+/**
+ * vmw_context_scrub_shader - scrub a shader binding from a context.
+ *
+ * @bi: single binding information.
+ */
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetShader body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_SET_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = bi->ctx->id;
+       cmd->body.type = bi->i1.shader_type;
+       cmd->body.shid = SVGA3D_INVALID_ID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_scrub_render_target - scrub a render target binding
+ * from a context.
+ *
+ * @bi: single binding information.
+ */
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetRenderTarget body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for render target "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = bi->ctx->id;
+       cmd->body.type = bi->i1.rt_type;
+       cmd->body.target.sid = SVGA3D_INVALID_ID;
+       cmd->body.target.face = 0;
+       cmd->body.target.mipmap = 0;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_scrub_texture - scrub a texture binding from a context.
+ *
+ * @bi: single binding information.
+ *
+ * TODO: Possibly complement this function with a function that takes
+ * a list of texture bindings and combines them to a single command.
+ */
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               struct {
+                       SVGA3dCmdSetTextureState c;
+                       SVGA3dTextureState s1;
+               } body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for texture "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+
+       cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.c.cid = bi->ctx->id;
+       cmd->body.s1.stage = bi->i1.texture_stage;
+       cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
+       cmd->body.s1.value = (uint32) SVGA3D_INVALID_ID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_binding_drop: Stop tracking a context binding
+ *
+ * @cb: Pointer to binding tracker storage.
+ *
+ * Stops tracking a context binding, and re-initializes its storage.
+ * Typically used when the context binding is replaced with a binding to
+ * another (or the same, for that matter) resource.
+ */
+static void vmw_context_binding_drop(struct vmw_ctx_binding *cb)
+{
+       list_del(&cb->ctx_list);
+       if (!list_empty(&cb->res_list))
+               list_del(&cb->res_list);
+       cb->bi.ctx = NULL;
+}
+
+/**
+ * vmw_context_binding_add: Start tracking a context binding
+ *
+ * @cbs: Pointer to the context binding state tracker.
+ * @bi: Information about the binding to track.
+ *
+ * Performs basic checks on the binding to make sure arguments are within
+ * bounds and then starts tracking the binding in the context binding
+ * state structure @cbs.
+ */
+int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
+                           const struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_ctx_binding *loc;
+
+       switch (bi->bt) {
+       case vmw_ctx_binding_rt:
+               if (unlikely((unsigned)bi->i1.rt_type >= SVGA3D_RT_MAX)) {
+                       DRM_ERROR("Illegal render target type %u.\n",
+                                 (unsigned) bi->i1.rt_type);
+                       return -EINVAL;
+               }
+               loc = &cbs->render_targets[bi->i1.rt_type];
+               break;
+       case vmw_ctx_binding_tex:
+               if (unlikely((unsigned)bi->i1.texture_stage >=
+                            SVGA3D_NUM_TEXTURE_UNITS)) {
+                       DRM_ERROR("Illegal texture/sampler unit %u.\n",
+                                 (unsigned) bi->i1.texture_stage);
+                       return -EINVAL;
+               }
+               loc = &cbs->texture_units[bi->i1.texture_stage];
+               break;
+       case vmw_ctx_binding_shader:
+               if (unlikely((unsigned)bi->i1.shader_type >=
+                            SVGA3D_SHADERTYPE_MAX)) {
+                       DRM_ERROR("Illegal shader type %u.\n",
+                                 (unsigned) bi->i1.shader_type);
+                       return -EINVAL;
+               }
+               loc = &cbs->shaders[bi->i1.shader_type];
+               break;
+       default:
+               BUG();
+       }
+
+       if (loc->bi.ctx != NULL)
+               vmw_context_binding_drop(loc);
+
+       loc->bi = *bi;
+       list_add_tail(&loc->ctx_list, &cbs->list);
+       INIT_LIST_HEAD(&loc->res_list);
+
+       return 0;
+}
+
+/**
+ * vmw_context_binding_transfer: Transfer a context binding tracking entry.
+ *
+ * @cbs: Pointer to the persistent context binding state tracker.
+ * @bi: Information about the binding to track.
+ *
+ */
+static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
+                                        const struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_ctx_binding *loc;
+
+       switch (bi->bt) {
+       case vmw_ctx_binding_rt:
+               loc = &cbs->render_targets[bi->i1.rt_type];
+               break;
+       case vmw_ctx_binding_tex:
+               loc = &cbs->texture_units[bi->i1.texture_stage];
+               break;
+       case vmw_ctx_binding_shader:
+               loc = &cbs->shaders[bi->i1.shader_type];
+               break;
+       default:
+               BUG();
+       }
+
+       if (loc->bi.ctx != NULL)
+               vmw_context_binding_drop(loc);
+
+       loc->bi = *bi;
+       list_add_tail(&loc->ctx_list, &cbs->list);
+       if (bi->res != NULL)
+               list_add_tail(&loc->res_list, &bi->res->binding_head);
+       else
+               INIT_LIST_HEAD(&loc->res_list);
+}
+
+/**
+ * vmw_context_binding_kill - Kill a binding on the device
+ * and stop tracking it.
+ *
+ * @cb: Pointer to binding tracker storage.
+ *
+ * Emits FIFO commands to scrub a binding represented by @cb.
+ * Then stops tracking the binding and re-initializes its storage.
+ */
+static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
+{
+       (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi);
+       vmw_context_binding_drop(cb);
+}
+
+/**
+ * vmw_context_binding_state_kill - Kill all bindings associated with a
+ * struct vmw_ctx_binding state structure, and re-initialize the structure.
+ *
+ * @cbs: Pointer to the context binding state tracker.
+ *
+ * Emits commands to scrub all bindings associated with the
+ * context binding state tracker. Then re-initializes the whole structure.
+ */
+static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
+{
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
+               vmw_context_binding_kill(entry);
+}
+
+/**
+ * vmw_context_binding_res_list_kill - Kill all bindings on a
+ * resource binding list
+ *
+ * @head: list head of resource binding list
+ *
+ * Kills all bindings associated with a specific resource. Typically
+ * called before the resource is destroyed.
+ */
+void vmw_context_binding_res_list_kill(struct list_head *head)
+{
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, head, res_list)
+               vmw_context_binding_kill(entry);
+}
+
+/**
+ * vmw_context_binding_state_transfer - Commit staged binding info
+ *
+ * @ctx: Pointer to context to commit the staged binding info to.
+ * @from: Staged binding info built during execbuf.
+ *
+ * Transfers binding info from a temporary structure to the persistent
+ * structure in the context. This can be done once commands
+ */
+void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
+                                       struct vmw_ctx_binding_state *from)
+{
+       struct vmw_user_context *uctx =
+               container_of(ctx, struct vmw_user_context, res);
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &from->list, ctx_list)
+               vmw_context_binding_transfer(&uctx->cbs, &entry->bi);
+}
index d4e54fcc0acd3e778bd74d1488f898798c740c73..a75840211b3c9682da3be63df8a54385de238824 100644 (file)
@@ -290,8 +290,7 @@ void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
 /**
  * vmw_bo_pin - Pin or unpin a buffer object without moving it.
  *
- * @bo: The buffer object. Must be reserved, and present either in VRAM
- * or GMR memory.
+ * @bo: The buffer object. Must be reserved.
  * @pin: Whether to pin or unpin.
  *
  */
@@ -303,10 +302,9 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
        int ret;
 
        lockdep_assert_held(&bo->resv->lock.base);
-       BUG_ON(old_mem_type != TTM_PL_VRAM &&
-              old_mem_type != VMW_PL_GMR);
 
-       pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
+       pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB
+               | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED;
        if (pin)
                pl_flags |= TTM_PL_FLAG_NO_EVICT;
 
index c7a549694e59fb2614562627dcb7f167680babcd..9893328f8fdc04750ec78538c4cdb2ba89ddae30 100644 (file)
 #define DRM_IOCTL_VMW_UPDATE_LAYOUT                            \
        DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,       \
                 struct drm_vmw_update_layout_arg)
+#define DRM_IOCTL_VMW_CREATE_SHADER                            \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_SHADER,      \
+                struct drm_vmw_shader_create_arg)
+#define DRM_IOCTL_VMW_UNREF_SHADER                             \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_SHADER,        \
+                struct drm_vmw_shader_arg)
+#define DRM_IOCTL_VMW_GB_SURFACE_CREATE                                \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_CREATE,  \
+                union drm_vmw_gb_surface_create_arg)
+#define DRM_IOCTL_VMW_GB_SURFACE_REF                           \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF,     \
+                union drm_vmw_gb_surface_reference_arg)
+#define DRM_IOCTL_VMW_SYNCCPU                                  \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_SYNCCPU,             \
+                struct drm_vmw_synccpu_arg)
 
 /**
  * The core DRM version of this macro doesn't account for
@@ -177,6 +192,21 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
                      vmw_kms_update_layout_ioctl,
                      DRM_MASTER | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_CREATE_SHADER,
+                     vmw_shader_define_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_UNREF_SHADER,
+                     vmw_shader_destroy_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
+                     vmw_gb_surface_define_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
+                     vmw_gb_surface_reference_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_SYNCCPU,
+                     vmw_user_dmabuf_synccpu_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -189,6 +219,7 @@ static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
 static int vmw_force_iommu;
 static int vmw_restrict_iommu;
 static int vmw_force_coherent;
+static int vmw_restrict_dma_mask;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -203,6 +234,8 @@ MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
 module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
 MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
 module_param_named(force_coherent, vmw_force_coherent, int, 0600);
+MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
+module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
 
 
 static void vmw_print_capabilities(uint32_t capabilities)
@@ -240,38 +273,52 @@ static void vmw_print_capabilities(uint32_t capabilities)
                DRM_INFO("  GMR2.\n");
        if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
                DRM_INFO("  Screen Object 2.\n");
+       if (capabilities & SVGA_CAP_COMMAND_BUFFERS)
+               DRM_INFO("  Command Buffers.\n");
+       if (capabilities & SVGA_CAP_CMD_BUFFERS_2)
+               DRM_INFO("  Command Buffers 2.\n");
+       if (capabilities & SVGA_CAP_GBOBJECTS)
+               DRM_INFO("  Guest Backed Resources.\n");
 }
 
-
 /**
- * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at
- * the start of a buffer object.
+ * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
  *
- * @dev_priv: The device private structure.
+ * @dev_priv: A device private structure.
  *
- * This function will idle the buffer using an uninterruptible wait, then
- * map the first page and initialize a pending occlusion query result structure,
- * Finally it will unmap the buffer.
+ * This function creates a small buffer object that holds the query
+ * result for dummy queries emitted as query barriers.
+ * The function will then map the first page and initialize a pending
+ * occlusion query result structure, Finally it will unmap the buffer.
+ * No interruptible waits are done within this function.
  *
- * TODO: Since we're only mapping a single page, we should optimize the map
- * to use kmap_atomic / iomap_atomic.
+ * Returns an error if bo creation or initialization fails.
  */
-static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
+static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
 {
+       int ret;
+       struct ttm_buffer_object *bo;
        struct ttm_bo_kmap_obj map;
        volatile SVGA3dQueryResult *result;
        bool dummy;
-       int ret;
-       struct ttm_bo_device *bdev = &dev_priv->bdev;
-       struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
 
-       ttm_bo_reserve(bo, false, false, false, 0);
-       spin_lock(&bdev->fence_lock);
-       ret = ttm_bo_wait(bo, false, false, false);
-       spin_unlock(&bdev->fence_lock);
+       /*
+        * Create the bo as pinned, so that a tryreserve will
+        * immediately succeed. This is because we're the only
+        * user of the bo currently.
+        */
+       ret = ttm_bo_create(&dev_priv->bdev,
+                           PAGE_SIZE,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL,
+                           &bo);
+
        if (unlikely(ret != 0))
-               (void) vmw_fallback_wait(dev_priv, false, true, 0, false,
-                                        10*HZ);
+               return ret;
+
+       ret = ttm_bo_reserve(bo, false, true, false, 0);
+       BUG_ON(ret != 0);
 
        ret = ttm_bo_kmap(bo, 0, 1, &map);
        if (likely(ret == 0)) {
@@ -280,34 +327,19 @@ static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
                result->state = SVGA3D_QUERYSTATE_PENDING;
                result->result32 = 0xff;
                ttm_bo_kunmap(&map);
-       } else
-               DRM_ERROR("Dummy query buffer map failed.\n");
+       }
+       vmw_bo_pin(bo, false);
        ttm_bo_unreserve(bo);
-}
 
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Dummy query buffer map failed.\n");
+               ttm_bo_unref(&bo);
+       } else
+               dev_priv->dummy_query_bo = bo;
 
-/**
- * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
- *
- * @dev_priv: A device private structure.
- *
- * This function creates a small buffer object that holds the query
- * result for dummy queries emitted as query barriers.
- * No interruptible waits are done within this function.
- *
- * Returns an error if bo creation fails.
- */
-static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
-{
-       return ttm_bo_create(&dev_priv->bdev,
-                            PAGE_SIZE,
-                            ttm_bo_type_device,
-                            &vmw_vram_sys_placement,
-                            0, false, NULL,
-                            &dev_priv->dummy_query_bo);
+       return ret;
 }
 
-
 static int vmw_request_device(struct vmw_private *dev_priv)
 {
        int ret;
@@ -318,14 +350,24 @@ static int vmw_request_device(struct vmw_private *dev_priv)
                return ret;
        }
        vmw_fence_fifo_up(dev_priv->fman);
+       if (dev_priv->has_mob) {
+               ret = vmw_otables_setup(dev_priv);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Unable to initialize "
+                                 "guest Memory OBjects.\n");
+                       goto out_no_mob;
+               }
+       }
        ret = vmw_dummy_query_bo_create(dev_priv);
        if (unlikely(ret != 0))
                goto out_no_query_bo;
-       vmw_dummy_query_bo_prepare(dev_priv);
 
        return 0;
 
 out_no_query_bo:
+       if (dev_priv->has_mob)
+               vmw_otables_takedown(dev_priv);
+out_no_mob:
        vmw_fence_fifo_down(dev_priv->fman);
        vmw_fifo_release(dev_priv, &dev_priv->fifo);
        return ret;
@@ -341,10 +383,13 @@ static void vmw_release_device(struct vmw_private *dev_priv)
        BUG_ON(dev_priv->pinned_bo != NULL);
 
        ttm_bo_unref(&dev_priv->dummy_query_bo);
+       if (dev_priv->has_mob)
+               vmw_otables_takedown(dev_priv);
        vmw_fence_fifo_down(dev_priv->fman);
        vmw_fifo_release(dev_priv, &dev_priv->fifo);
 }
 
+
 /**
  * Increase the 3d resource refcount.
  * If the count was prevously zero, initialize the fifo, switching to svga
@@ -510,6 +555,33 @@ out_fixup:
        return 0;
 }
 
+/**
+ * vmw_dma_masks - set required page- and dma masks
+ *
+ * @dev: Pointer to struct drm-device
+ *
+ * With 32-bit we can only handle 32 bit PFNs. Optionally set that
+ * restriction also for 64-bit systems.
+ */
+#ifdef CONFIG_INTEL_IOMMU
+static int vmw_dma_masks(struct vmw_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+
+       if (intel_iommu_enabled &&
+           (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
+               DRM_INFO("Restricting DMA addresses to 44 bits.\n");
+               return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+       }
+       return 0;
+}
+#else
+static int vmw_dma_masks(struct vmw_private *dev_priv)
+{
+       return 0;
+}
+#endif
+
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        struct vmw_private *dev_priv;
@@ -532,6 +604,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        mutex_init(&dev_priv->hw_mutex);
        mutex_init(&dev_priv->cmdbuf_mutex);
        mutex_init(&dev_priv->release_mutex);
+       mutex_init(&dev_priv->binding_mutex);
        rwlock_init(&dev_priv->resource_lock);
 
        for (i = vmw_res_context; i < vmw_res_max; ++i) {
@@ -578,14 +651,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
        vmw_get_initial_size(dev_priv);
 
-       if (dev_priv->capabilities & SVGA_CAP_GMR) {
-               dev_priv->max_gmr_descriptors =
-                       vmw_read(dev_priv,
-                                SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
+       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                dev_priv->max_gmr_ids =
                        vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
-       }
-       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                dev_priv->max_gmr_pages =
                        vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES);
                dev_priv->memory_size =
@@ -598,23 +666,42 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                 */
                dev_priv->memory_size = 512*1024*1024;
        }
+       dev_priv->max_mob_pages = 0;
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               uint64_t mem_size =
+                       vmw_read(dev_priv,
+                                SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
+
+               dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
+               dev_priv->prim_bb_mem =
+                       vmw_read(dev_priv,
+                                SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+       } else
+               dev_priv->prim_bb_mem = dev_priv->vram_size;
+
+       ret = vmw_dma_masks(dev_priv);
+       if (unlikely(ret != 0)) {
+               mutex_unlock(&dev_priv->hw_mutex);
+               goto out_err0;
+       }
+
+       if (unlikely(dev_priv->prim_bb_mem < dev_priv->vram_size))
+               dev_priv->prim_bb_mem = dev_priv->vram_size;
 
        mutex_unlock(&dev_priv->hw_mutex);
 
        vmw_print_capabilities(dev_priv->capabilities);
 
-       if (dev_priv->capabilities & SVGA_CAP_GMR) {
+       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                DRM_INFO("Max GMR ids is %u\n",
                         (unsigned)dev_priv->max_gmr_ids);
-               DRM_INFO("Max GMR descriptors is %u\n",
-                        (unsigned)dev_priv->max_gmr_descriptors);
-       }
-       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                DRM_INFO("Max number of GMR pages is %u\n",
                         (unsigned)dev_priv->max_gmr_pages);
                DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
                         (unsigned)dev_priv->memory_size / 1024);
        }
+       DRM_INFO("Maximum display memory size is %u kiB\n",
+                dev_priv->prim_bb_mem / 1024);
        DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
                 dev_priv->vram_start, dev_priv->vram_size / 1024);
        DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
@@ -649,12 +736,22 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->has_gmr = true;
        if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
            refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR,
-                                        dev_priv->max_gmr_ids) != 0) {
+                                        VMW_PL_GMR) != 0) {
                DRM_INFO("No GMR memory available. "
                         "Graphics memory resources are very limited.\n");
                dev_priv->has_gmr = false;
        }
 
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               dev_priv->has_mob = true;
+               if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB,
+                                  VMW_PL_MOB) != 0) {
+                       DRM_INFO("No MOB memory available. "
+                                "3D will be disabled.\n");
+                       dev_priv->has_mob = false;
+               }
+       }
+
        dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
                                               dev_priv->mmio_size);
 
@@ -757,6 +854,8 @@ out_err4:
        iounmap(dev_priv->mmio_virt);
 out_err3:
        arch_phys_wc_del(dev_priv->mmio_mtrr);
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
        if (dev_priv->has_gmr)
                (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
        (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
@@ -801,6 +900,8 @@ static int vmw_driver_unload(struct drm_device *dev)
        ttm_object_device_release(&dev_priv->tdev);
        iounmap(dev_priv->mmio_virt);
        arch_phys_wc_del(dev_priv->mmio_mtrr);
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
        if (dev_priv->has_gmr)
                (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
        (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
index 20890ad8408bb5ef377c4ff54c80397c3105efaf..554e7fa330824cc7a2f1d728f4299c19c8ab8fb5 100644 (file)
@@ -40,9 +40,9 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20120209"
+#define VMWGFX_DRIVER_DATE "20121114"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 4
+#define VMWGFX_DRIVER_MINOR 5
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_VALIDATIONS 2048
 #define VMWGFX_MAX_DISPLAYS 16
 #define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
+#define VMWGFX_ENABLE_SCREEN_TARGET_OTABLE 0
+
+/*
+ * Perhaps we should have sysfs entries for these.
+ */
+#define VMWGFX_NUM_GB_CONTEXT 256
+#define VMWGFX_NUM_GB_SHADER 20000
+#define VMWGFX_NUM_GB_SURFACE 32768
+#define VMWGFX_NUM_GB_SCREEN_TARGET VMWGFX_MAX_DISPLAYS
+#define VMWGFX_NUM_MOB (VMWGFX_NUM_GB_CONTEXT +\
+                       VMWGFX_NUM_GB_SHADER +\
+                       VMWGFX_NUM_GB_SURFACE +\
+                       VMWGFX_NUM_GB_SCREEN_TARGET)
 
 #define VMW_PL_GMR TTM_PL_PRIV0
 #define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
+#define VMW_PL_MOB TTM_PL_PRIV1
+#define VMW_PL_FLAG_MOB TTM_PL_FLAG_PRIV1
 
 #define VMW_RES_CONTEXT ttm_driver_type0
 #define VMW_RES_SURFACE ttm_driver_type1
 #define VMW_RES_STREAM ttm_driver_type2
 #define VMW_RES_FENCE ttm_driver_type3
+#define VMW_RES_SHADER ttm_driver_type4
 
 struct vmw_fpriv {
        struct drm_master *locked_master;
@@ -82,6 +98,7 @@ struct vmw_dma_buffer {
 struct vmw_validate_buffer {
        struct ttm_validate_buffer base;
        struct drm_hash_item hash;
+       bool validate_as_mob;
 };
 
 struct vmw_res_func;
@@ -98,6 +115,7 @@ struct vmw_resource {
        const struct vmw_res_func *func;
        struct list_head lru_head; /* Protected by the resource lock */
        struct list_head mob_head; /* Protected by @backup reserved */
+       struct list_head binding_head; /* Protected by binding_mutex */
        void (*res_free) (struct vmw_resource *res);
        void (*hw_destroy) (struct vmw_resource *res);
 };
@@ -106,6 +124,7 @@ enum vmw_res_type {
        vmw_res_context,
        vmw_res_surface,
        vmw_res_stream,
+       vmw_res_shader,
        vmw_res_max
 };
 
@@ -154,6 +173,7 @@ struct vmw_fifo_state {
 };
 
 struct vmw_relocation {
+       SVGAMobId *mob_loc;
        SVGAGuestPtr *location;
        uint32_t index;
 };
@@ -229,6 +249,71 @@ struct vmw_piter {
        struct page *(*page)(struct vmw_piter *);
 };
 
+/*
+ * enum vmw_ctx_binding_type - abstract resource to context binding types
+ */
+enum vmw_ctx_binding_type {
+       vmw_ctx_binding_shader,
+       vmw_ctx_binding_rt,
+       vmw_ctx_binding_tex,
+       vmw_ctx_binding_max
+};
+
+/**
+ * struct vmw_ctx_bindinfo - structure representing a single context binding
+ *
+ * @ctx: Pointer to the context structure. NULL means the binding is not
+ * active.
+ * @res: Non ref-counted pointer to the bound resource.
+ * @bt: The binding type.
+ * @i1: Union of information needed to unbind.
+ */
+struct vmw_ctx_bindinfo {
+       struct vmw_resource *ctx;
+       struct vmw_resource *res;
+       enum vmw_ctx_binding_type bt;
+       union {
+               SVGA3dShaderType shader_type;
+               SVGA3dRenderTargetType rt_type;
+               uint32 texture_stage;
+       } i1;
+};
+
+/**
+ * struct vmw_ctx_binding - structure representing a single context binding
+ *                        - suitable for tracking in a context
+ *
+ * @ctx_list: List head for context.
+ * @res_list: List head for bound resource.
+ * @bi: Binding info
+ */
+struct vmw_ctx_binding {
+       struct list_head ctx_list;
+       struct list_head res_list;
+       struct vmw_ctx_bindinfo bi;
+};
+
+
+/**
+ * struct vmw_ctx_binding_state - context binding state
+ *
+ * @list: linked list of individual bindings.
+ * @render_targets: Render target bindings.
+ * @texture_units: Texture units/samplers bindings.
+ * @shaders: Shader bindings.
+ *
+ * Note that this structure also provides storage space for the individual
+ * struct vmw_ctx_binding objects, so that no dynamic allocation is needed
+ * for individual bindings.
+ *
+ */
+struct vmw_ctx_binding_state {
+       struct list_head list;
+       struct vmw_ctx_binding render_targets[SVGA3D_RT_MAX];
+       struct vmw_ctx_binding texture_units[SVGA3D_NUM_TEXTURE_UNITS];
+       struct vmw_ctx_binding shaders[SVGA3D_SHADERTYPE_MAX];
+};
+
 struct vmw_sw_context{
        struct drm_open_hash res_ht;
        bool res_ht_initialized;
@@ -250,6 +335,7 @@ struct vmw_sw_context{
        struct vmw_resource *last_query_ctx;
        bool needs_post_query_barrier;
        struct vmw_resource *error_resource;
+       struct vmw_ctx_binding_state staged_bindings;
 };
 
 struct vmw_legacy_display;
@@ -281,6 +367,7 @@ struct vmw_private {
        unsigned int io_start;
        uint32_t vram_start;
        uint32_t vram_size;
+       uint32_t prim_bb_mem;
        uint32_t mmio_start;
        uint32_t mmio_size;
        uint32_t fb_max_width;
@@ -290,11 +377,12 @@ struct vmw_private {
        __le32 __iomem *mmio_virt;
        int mmio_mtrr;
        uint32_t capabilities;
-       uint32_t max_gmr_descriptors;
        uint32_t max_gmr_ids;
        uint32_t max_gmr_pages;
+       uint32_t max_mob_pages;
        uint32_t memory_size;
        bool has_gmr;
+       bool has_mob;
        struct mutex hw_mutex;
 
        /*
@@ -370,6 +458,7 @@ struct vmw_private {
 
        struct vmw_sw_context ctx;
        struct mutex cmdbuf_mutex;
+       struct mutex binding_mutex;
 
        /**
         * Operating mode.
@@ -415,6 +504,12 @@ struct vmw_private {
         * DMA mapping stuff.
         */
        enum vmw_dma_map_mode map_mode;
+
+       /*
+        * Guest Backed stuff
+        */
+       struct ttm_buffer_object *otable_bo;
+       struct vmw_otable *otables;
 };
 
 static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
@@ -471,23 +566,12 @@ extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
  * Resource utilities - vmwgfx_resource.c
  */
 struct vmw_user_resource_conv;
-extern const struct vmw_user_resource_conv *user_surface_converter;
-extern const struct vmw_user_resource_conv *user_context_converter;
 
-extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
 extern void vmw_resource_unreference(struct vmw_resource **p_res);
 extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
 extern int vmw_resource_validate(struct vmw_resource *res);
 extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
 extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
-extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
-                                    struct drm_file *file_priv);
-extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern int vmw_context_check(struct vmw_private *dev_priv,
-                            struct ttm_object_file *tfile,
-                            int id,
-                            struct vmw_resource **p_res);
 extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
                                  struct ttm_object_file *tfile,
                                  uint32_t handle,
@@ -499,18 +583,6 @@ extern int vmw_user_resource_lookup_handle(
        uint32_t handle,
        const struct vmw_user_resource_conv *converter,
        struct vmw_resource **p_res);
-extern void vmw_surface_res_free(struct vmw_resource *res);
-extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
-                                    struct drm_file *file_priv);
-extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
-                                      struct drm_file *file_priv);
-extern int vmw_surface_check(struct vmw_private *dev_priv,
-                            struct ttm_object_file *tfile,
-                            uint32_t handle, int *id);
-extern int vmw_surface_validate(struct vmw_private *dev_priv,
-                               struct vmw_surface *srf);
 extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
 extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
                           struct vmw_dma_buffer *vmw_bo,
@@ -519,10 +591,21 @@ extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
                           void (*bo_free) (struct ttm_buffer_object *bo));
 extern int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
                                  struct ttm_object_file *tfile);
+extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
+                                struct ttm_object_file *tfile,
+                                uint32_t size,
+                                bool shareable,
+                                uint32_t *handle,
+                                struct vmw_dma_buffer **p_dma_buf);
+extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
+                                    struct vmw_dma_buffer *dma_buf,
+                                    uint32_t *handle);
 extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
+extern int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
+                                        struct drm_file *file_priv);
 extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
                                         uint32_t cur_validate_node);
 extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
@@ -622,10 +705,16 @@ extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_vram_gmr_placement;
 extern struct ttm_placement vmw_vram_gmr_ne_placement;
 extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_placement vmw_sys_ne_placement;
 extern struct ttm_placement vmw_evictable_placement;
 extern struct ttm_placement vmw_srf_placement;
+extern struct ttm_placement vmw_mob_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
+extern int vmw_bo_map_dma(struct ttm_buffer_object *bo);
+extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo);
+extern const struct vmw_sg_table *
+vmw_bo_sg_table(struct ttm_buffer_object *bo);
 extern void vmw_piter_start(struct vmw_piter *viter,
                            const struct vmw_sg_table *vsgt,
                            unsigned long p_offs);
@@ -701,7 +790,7 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
  * IRQs and wating - vmwgfx_irq.c
  */
 
-extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t vmw_irq_handler(int irq, void *arg);
 extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy,
                             uint32_t seqno, bool interruptible,
                             unsigned long timeout);
@@ -832,6 +921,76 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
                                  uint32_t handle, uint32_t flags,
                                  int *prime_fd);
 
+/*
+ * MemoryOBject management -  vmwgfx_mob.c
+ */
+struct vmw_mob;
+extern int vmw_mob_bind(struct vmw_private *dev_priv, struct vmw_mob *mob,
+                       const struct vmw_sg_table *vsgt,
+                       unsigned long num_data_pages, int32_t mob_id);
+extern void vmw_mob_unbind(struct vmw_private *dev_priv,
+                          struct vmw_mob *mob);
+extern void vmw_mob_destroy(struct vmw_mob *mob);
+extern struct vmw_mob *vmw_mob_create(unsigned long data_pages);
+extern int vmw_otables_setup(struct vmw_private *dev_priv);
+extern void vmw_otables_takedown(struct vmw_private *dev_priv);
+
+/*
+ * Context management - vmwgfx_context.c
+ */
+
+extern const struct vmw_user_resource_conv *user_context_converter;
+
+extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
+
+extern int vmw_context_check(struct vmw_private *dev_priv,
+                            struct ttm_object_file *tfile,
+                            int id,
+                            struct vmw_resource **p_res);
+extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
+                                  const struct vmw_ctx_bindinfo *ci);
+extern void
+vmw_context_binding_state_transfer(struct vmw_resource *res,
+                                  struct vmw_ctx_binding_state *cbs);
+extern void vmw_context_binding_res_list_kill(struct list_head *head);
+
+/*
+ * Surface management - vmwgfx_surface.c
+ */
+
+extern const struct vmw_user_resource_conv *user_surface_converter;
+
+extern void vmw_surface_res_free(struct vmw_resource *res);
+extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                         struct drm_file *file_priv);
+extern int vmw_surface_check(struct vmw_private *dev_priv,
+                            struct ttm_object_file *tfile,
+                            uint32_t handle, int *id);
+extern int vmw_surface_validate(struct vmw_private *dev_priv,
+                               struct vmw_surface *srf);
+
+/*
+ * Shader management - vmwgfx_shader.c
+ */
+
+extern const struct vmw_user_resource_conv *user_shader_converter;
+
+extern int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
+extern int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
 
 /**
  * Inline helper functions
index 599f6469a1ebb00c10b3d8047c44882aebd779d8..7a5f1eb55c5a0ad09adf8aa02c92367908c49c24 100644 (file)
@@ -54,6 +54,8 @@ struct vmw_resource_relocation {
  * @res: Ref-counted pointer to the resource.
  * @switch_backup: Boolean whether to switch backup buffer on unreserve.
  * @new_backup: Refcounted pointer to the new backup buffer.
+ * @staged_bindings: If @res is a context, tracks bindings set up during
+ * the command batch. Otherwise NULL.
  * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
  * @first_usage: Set to true the first time the resource is referenced in
  * the command stream.
@@ -65,11 +67,31 @@ struct vmw_resource_val_node {
        struct drm_hash_item hash;
        struct vmw_resource *res;
        struct vmw_dma_buffer *new_backup;
+       struct vmw_ctx_binding_state *staged_bindings;
        unsigned long new_backup_offset;
        bool first_usage;
        bool no_buffer_needed;
 };
 
+/**
+ * struct vmw_cmd_entry - Describe a command for the verifier
+ *
+ * @user_allow: Whether allowed from the execbuf ioctl.
+ * @gb_disable: Whether disabled if guest-backed objects are available.
+ * @gb_enable: Whether enabled iff guest-backed objects are available.
+ */
+struct vmw_cmd_entry {
+       int (*func) (struct vmw_private *, struct vmw_sw_context *,
+                    SVGA3dCmdHeader *);
+       bool user_allow;
+       bool gb_disable;
+       bool gb_enable;
+};
+
+#define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable) \
+       [(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\
+                                      (_gb_disable), (_gb_enable)}
+
 /**
  * vmw_resource_unreserve - unreserve resources previously reserved for
  * command submission.
@@ -87,6 +109,16 @@ static void vmw_resource_list_unreserve(struct list_head *list,
                struct vmw_dma_buffer *new_backup =
                        backoff ? NULL : val->new_backup;
 
+               /*
+                * Transfer staged context bindings to the
+                * persistent context binding tracker.
+                */
+               if (unlikely(val->staged_bindings)) {
+                       vmw_context_binding_state_transfer
+                               (val->res, val->staged_bindings);
+                       kfree(val->staged_bindings);
+                       val->staged_bindings = NULL;
+               }
                vmw_resource_unreserve(res, new_backup,
                        val->new_backup_offset);
                vmw_dmabuf_unreference(&val->new_backup);
@@ -224,6 +256,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
  *
  * @sw_context: The software context used for this command submission batch.
  * @bo: The buffer object to add.
+ * @validate_as_mob: Validate this buffer as a MOB.
  * @p_val_node: If non-NULL Will be updated with the validate node number
  * on return.
  *
@@ -232,6 +265,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
  */
 static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                                   struct ttm_buffer_object *bo,
+                                  bool validate_as_mob,
                                   uint32_t *p_val_node)
 {
        uint32_t val_node;
@@ -244,6 +278,10 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                                    &hash) == 0)) {
                vval_buf = container_of(hash, struct vmw_validate_buffer,
                                        hash);
+               if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) {
+                       DRM_ERROR("Inconsistent buffer usage.\n");
+                       return -EINVAL;
+               }
                val_buf = &vval_buf->base;
                val_node = vval_buf - sw_context->val_bufs;
        } else {
@@ -266,6 +304,7 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                val_buf->bo = ttm_bo_reference(bo);
                val_buf->reserved = false;
                list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+               vval_buf->validate_as_mob = validate_as_mob;
        }
 
        sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC;
@@ -302,7 +341,8 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
                        struct ttm_buffer_object *bo = &res->backup->base;
 
                        ret = vmw_bo_to_validate_list
-                               (sw_context, bo, NULL);
+                               (sw_context, bo,
+                                vmw_resource_needs_backup(res), NULL);
 
                        if (unlikely(ret != 0))
                                return ret;
@@ -362,8 +402,15 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        struct vmw_resource_val_node *node;
        int ret;
 
-       if (*id == SVGA3D_INVALID_ID)
+       if (*id == SVGA3D_INVALID_ID) {
+               if (p_val)
+                       *p_val = NULL;
+               if (res_type == vmw_res_context) {
+                       DRM_ERROR("Illegal context invalid id.\n");
+                       return -EINVAL;
+               }
                return 0;
+       }
 
        /*
         * Fastpath in case of repeated commands referencing the same
@@ -411,6 +458,18 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        rcache->node = node;
        if (p_val)
                *p_val = node;
+
+       if (node->first_usage && res_type == vmw_res_context) {
+               node->staged_bindings =
+                       kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
+               if (node->staged_bindings == NULL) {
+                       DRM_ERROR("Failed to allocate context binding "
+                                 "information.\n");
+                       goto out_no_reloc;
+               }
+               INIT_LIST_HEAD(&node->staged_bindings->list);
+       }
+
        vmw_resource_unreference(&res);
        return 0;
 
@@ -453,17 +512,35 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
                SVGA3dCmdHeader header;
                SVGA3dCmdSetRenderTarget body;
        } *cmd;
+       struct vmw_resource_val_node *ctx_node;
+       struct vmw_resource_val_node *res_node;
        int ret;
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       cmd = container_of(header, struct vmw_sid_cmd, header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
-       cmd = container_of(header, struct vmw_sid_cmd, header);
        ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                user_surface_converter,
-                               &cmd->body.target.sid, NULL);
-       return ret;
+                               &cmd->body.target.sid, &res_node);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (dev_priv->has_mob) {
+               struct vmw_ctx_bindinfo bi;
+
+               bi.ctx = ctx_node->res;
+               bi.res = res_node ? res_node->res : NULL;
+               bi.bt = vmw_ctx_binding_rt;
+               bi.i1.rt_type = cmd->body.type;
+               return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
+       }
+
+       return 0;
 }
 
 static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
@@ -519,11 +596,6 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
 
-       if (unlikely(!sw_context->kernel)) {
-               DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
-               return -EPERM;
-       }
-
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                 user_surface_converter,
                                 &cmd->body.srcImage.sid, NULL);
@@ -541,11 +613,6 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
 
-       if (unlikely(!sw_context->kernel)) {
-               DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
-               return -EPERM;
-       }
-
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                 user_surface_converter, &cmd->body.sid,
                                 NULL);
@@ -586,7 +653,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
                        sw_context->needs_post_query_barrier = true;
                        ret = vmw_bo_to_validate_list(sw_context,
                                                      sw_context->cur_query_bo,
-                                                     NULL);
+                                                     dev_priv->has_mob, NULL);
                        if (unlikely(ret != 0))
                                return ret;
                }
@@ -594,7 +661,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
 
                ret = vmw_bo_to_validate_list(sw_context,
                                              dev_priv->dummy_query_bo,
-                                             NULL);
+                                             dev_priv->has_mob, NULL);
                if (unlikely(ret != 0))
                        return ret;
 
@@ -671,6 +738,66 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
        }
 }
 
+/**
+ * vmw_translate_mob_pointer - Prepare to translate a user-space buffer
+ * handle to a MOB id.
+ *
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: The software context used for this command batch validation.
+ * @id: Pointer to the user-space handle to be translated.
+ * @vmw_bo_p: Points to a location that, on successful return will carry
+ * a reference-counted pointer to the DMA buffer identified by the
+ * user-space handle in @id.
+ *
+ * This function saves information needed to translate a user-space buffer
+ * handle to a MOB id. The translation does not take place immediately, but
+ * during a call to vmw_apply_relocations(). This function builds a relocation
+ * list and a list of buffers to validate. The former needs to be freed using
+ * either vmw_apply_relocations() or vmw_free_relocations(). The latter
+ * needs to be freed using vmw_clear_validations.
+ */
+static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                SVGAMobId *id,
+                                struct vmw_dma_buffer **vmw_bo_p)
+{
+       struct vmw_dma_buffer *vmw_bo = NULL;
+       struct ttm_buffer_object *bo;
+       uint32_t handle = *id;
+       struct vmw_relocation *reloc;
+       int ret;
+
+       ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not find or use MOB buffer.\n");
+               return -EINVAL;
+       }
+       bo = &vmw_bo->base;
+
+       if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
+               DRM_ERROR("Max number relocations per submission"
+                         " exceeded\n");
+               ret = -EINVAL;
+               goto out_no_reloc;
+       }
+
+       reloc = &sw_context->relocs[sw_context->cur_reloc++];
+       reloc->mob_loc = id;
+       reloc->location = NULL;
+
+       ret = vmw_bo_to_validate_list(sw_context, bo, true, &reloc->index);
+       if (unlikely(ret != 0))
+               goto out_no_reloc;
+
+       *vmw_bo_p = vmw_bo;
+       return 0;
+
+out_no_reloc:
+       vmw_dmabuf_unreference(&vmw_bo);
+       vmw_bo_p = NULL;
+       return ret;
+}
+
 /**
  * vmw_translate_guest_pointer - Prepare to translate a user-space buffer
  * handle to a valid SVGAGuestPtr
@@ -718,7 +845,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
        reloc = &sw_context->relocs[sw_context->cur_reloc++];
        reloc->location = ptr;
 
-       ret = vmw_bo_to_validate_list(sw_context, bo, &reloc->index);
+       ret = vmw_bo_to_validate_list(sw_context, bo, false, &reloc->index);
        if (unlikely(ret != 0))
                goto out_no_reloc;
 
@@ -731,6 +858,30 @@ out_no_reloc:
        return ret;
 }
 
+/**
+ * vmw_cmd_begin_gb_query - validate a  SVGA_3D_CMD_BEGIN_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv,
+                                 struct vmw_sw_context *sw_context,
+                                 SVGA3dCmdHeader *header)
+{
+       struct vmw_begin_gb_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBeginGBQuery q;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_begin_gb_query_cmd,
+                          header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                                user_context_converter, &cmd->q.cid,
+                                NULL);
+}
+
 /**
  * vmw_cmd_begin_query - validate a  SVGA_3D_CMD_BEGIN_QUERY command.
  *
@@ -750,11 +901,63 @@ static int vmw_cmd_begin_query(struct vmw_private *dev_priv,
        cmd = container_of(header, struct vmw_begin_query_cmd,
                           header);
 
+       if (unlikely(dev_priv->has_mob)) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdBeginGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_begin_gb_query(dev_priv, sw_context, header);
+       }
+
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
                                 user_context_converter, &cmd->q.cid,
                                 NULL);
 }
 
+/**
+ * vmw_cmd_end_gb_query - validate a  SVGA_3D_CMD_END_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv,
+                               struct vmw_sw_context *sw_context,
+                               SVGA3dCmdHeader *header)
+{
+       struct vmw_dma_buffer *vmw_bo;
+       struct vmw_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdEndGBQuery q;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_query_cmd, header);
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context,
+                                   &cmd->q.mobid,
+                                   &vmw_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
+
+       vmw_dmabuf_unreference(&vmw_bo);
+       return ret;
+}
+
 /**
  * vmw_cmd_end_query - validate a  SVGA_3D_CMD_END_QUERY command.
  *
@@ -774,6 +977,25 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_query_cmd, header);
+       if (dev_priv->has_mob) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdEndGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+               gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
+               gb_cmd.q.offset = cmd->q.guestResult.offset;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_end_gb_query(dev_priv, sw_context, header);
+       }
+
        ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
                return ret;
@@ -790,7 +1012,40 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
        return ret;
 }
 
-/*
+/**
+ * vmw_cmd_wait_gb_query - validate a  SVGA_3D_CMD_WAIT_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                SVGA3dCmdHeader *header)
+{
+       struct vmw_dma_buffer *vmw_bo;
+       struct vmw_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdWaitForGBQuery q;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_query_cmd, header);
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context,
+                                   &cmd->q.mobid,
+                                   &vmw_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       vmw_dmabuf_unreference(&vmw_bo);
+       return 0;
+}
+
+/**
  * vmw_cmd_wait_query - validate a  SVGA_3D_CMD_WAIT_QUERY command.
  *
  * @dev_priv: Pointer to a device private struct.
@@ -809,6 +1064,25 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_query_cmd, header);
+       if (dev_priv->has_mob) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdWaitForGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+               gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
+               gb_cmd.q.offset = cmd->q.guestResult.offset;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_wait_gb_query(dev_priv, sw_context, header);
+       }
+
        ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
                return ret;
@@ -921,15 +1195,22 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
        struct vmw_tex_state_cmd {
                SVGA3dCmdHeader header;
                SVGA3dCmdSetTextureState state;
-       };
+       } *cmd;
 
        SVGA3dTextureState *last_state = (SVGA3dTextureState *)
          ((unsigned long) header + header->size + sizeof(header));
        SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
                ((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
+       struct vmw_resource_val_node *ctx_node;
+       struct vmw_resource_val_node *res_node;
        int ret;
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       cmd = container_of(header, struct vmw_tex_state_cmd,
+                          header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->state.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
@@ -939,9 +1220,20 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
 
                ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                        user_surface_converter,
-                                       &cur_state->value, NULL);
+                                       &cur_state->value, &res_node);
                if (unlikely(ret != 0))
                        return ret;
+
+               if (dev_priv->has_mob) {
+                       struct vmw_ctx_bindinfo bi;
+
+                       bi.ctx = ctx_node->res;
+                       bi.res = res_node ? res_node->res : NULL;
+                       bi.bt = vmw_ctx_binding_tex;
+                       bi.i1.texture_stage = cur_state->stage;
+                       vmw_context_binding_add(ctx_node->staged_bindings,
+                                               &bi);
+               }
        }
 
        return 0;
@@ -970,6 +1262,222 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
        return ret;
 }
 
+/**
+ * vmw_cmd_switch_backup - Utility function to handle backup buffer switching
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @res_type: The resource type.
+ * @converter: Information about user-space binding for this resource type.
+ * @res_id: Pointer to the user-space resource handle in the command stream.
+ * @buf_id: Pointer to the user-space backup buffer handle in the command
+ * stream.
+ * @backup_offset: Offset of backup into MOB.
+ *
+ * This function prepares for registering a switch of backup buffers
+ * in the resource metadata just prior to unreserving.
+ */
+static int vmw_cmd_switch_backup(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                enum vmw_res_type res_type,
+                                const struct vmw_user_resource_conv
+                                *converter,
+                                uint32_t *res_id,
+                                uint32_t *buf_id,
+                                unsigned long backup_offset)
+{
+       int ret;
+       struct vmw_dma_buffer *dma_buf;
+       struct vmw_resource_val_node *val_node;
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, res_type,
+                               converter, res_id, &val_node);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (val_node->first_usage)
+               val_node->no_buffer_needed = true;
+
+       vmw_dmabuf_unreference(&val_node->new_backup);
+       val_node->new_backup = dma_buf;
+       val_node->new_backup_offset = backup_offset;
+
+       return 0;
+}
+
+/**
+ * vmw_cmd_bind_gb_surface - Validate an SVGA_3D_CMD_BIND_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv,
+                                  struct vmw_sw_context *sw_context,
+                                  SVGA3dCmdHeader *header)
+{
+       struct vmw_bind_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_bind_gb_surface_cmd, header);
+
+       return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface,
+                                    user_surface_converter,
+                                    &cmd->body.sid, &cmd->body.mobid,
+                                    0);
+}
+
+/**
+ * vmw_cmd_update_gb_image - Validate an SVGA_3D_CMD_UPDATE_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_update_gb_image(struct vmw_private *dev_priv,
+                                  struct vmw_sw_context *sw_context,
+                                  SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_update_gb_surface - Validate an SVGA_3D_CMD_UPDATE_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv,
+                                    struct vmw_sw_context *sw_context,
+                                    SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
+/**
+ * vmw_cmd_readback_gb_image - Validate an SVGA_3D_CMD_READBACK_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv,
+                                    struct vmw_sw_context *sw_context,
+                                    SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_readback_gb_surface - Validate an SVGA_3D_CMD_READBACK_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv,
+                                      struct vmw_sw_context *sw_context,
+                                      SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
+/**
+ * vmw_cmd_invalidate_gb_image - Validate an SVGA_3D_CMD_INVALIDATE_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv,
+                                      struct vmw_sw_context *sw_context,
+                                      SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_invalidate_gb_surface - Validate an
+ * SVGA_3D_CMD_INVALIDATE_GB_SURFACE command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv,
+                                        struct vmw_sw_context *sw_context,
+                                        SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
 /**
  * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
  * command
@@ -986,18 +1494,64 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
                SVGA3dCmdHeader header;
                SVGA3dCmdSetShader body;
        } *cmd;
+       struct vmw_resource_val_node *ctx_node;
        int ret;
 
        cmd = container_of(header, struct vmw_set_shader_cmd,
                           header);
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
+       if (dev_priv->has_mob) {
+               struct vmw_ctx_bindinfo bi;
+               struct vmw_resource_val_node *res_node;
+
+               ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader,
+                                       user_shader_converter,
+                                       &cmd->body.shid, &res_node);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               bi.ctx = ctx_node->res;
+               bi.res = res_node ? res_node->res : NULL;
+               bi.bt = vmw_ctx_binding_shader;
+               bi.i1.shader_type = cmd->body.type;
+               return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
+       }
+
        return 0;
 }
 
+/**
+ * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv,
+                                 struct vmw_sw_context *sw_context,
+                                 SVGA3dCmdHeader *header)
+{
+       struct vmw_bind_gb_shader_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_bind_gb_shader_cmd,
+                          header);
+
+       return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader,
+                                    user_shader_converter,
+                                    &cmd->body.shid, &cmd->body.mobid,
+                                    cmd->body.offsetInBytes);
+}
+
 static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
                                struct vmw_sw_context *sw_context,
                                void *buf, uint32_t *size)
@@ -1041,50 +1595,173 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
        return 0;
 }
 
-typedef int (*vmw_cmd_func) (struct vmw_private *,
-                            struct vmw_sw_context *,
-                            SVGA3dCmdHeader *);
-
-#define VMW_CMD_DEF(cmd, func) \
-       [cmd - SVGA_3D_CMD_BASE] = func
-
-static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma),
-       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
+static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
-                   &vmw_cmd_set_render_target_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader),
-       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
+                   &vmw_cmd_set_render_target_check, true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
-                   &vmw_cmd_blt_surf_screen_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid),
+                   &vmw_cmd_blt_surf_screen_check, false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_OPEN_CONTEXT_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_BITBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_TRANSBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_STRETCHBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_COLORFILL, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_ALPHABLEND, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE,
+                   &vmw_cmd_update_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE,
+                   &vmw_cmd_readback_gb_image, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE,
+                   &vmw_cmd_readback_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
+                   &vmw_cmd_invalidate_gb_image, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE,
+                   &vmw_cmd_invalidate_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check,
+                   true, false, true)
 };
 
 static int vmw_cmd_check(struct vmw_private *dev_priv,
@@ -1095,6 +1772,8 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
        uint32_t size_remaining = *size;
        SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
        int ret;
+       const struct vmw_cmd_entry *entry;
+       bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS;
 
        cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
        /* Handle any none 3D commands */
@@ -1107,18 +1786,40 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
 
        cmd_id -= SVGA_3D_CMD_BASE;
        if (unlikely(*size > size_remaining))
-               goto out_err;
+               goto out_invalid;
 
        if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
-               goto out_err;
+               goto out_invalid;
+
+       entry = &vmw_cmd_entries[cmd_id];
+       if (unlikely(!entry->user_allow && !sw_context->kernel))
+               goto out_privileged;
 
-       ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header);
+       if (unlikely(entry->gb_disable && gb))
+               goto out_old;
+
+       if (unlikely(entry->gb_enable && !gb))
+               goto out_new;
+
+       ret = entry->func(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
-               goto out_err;
+               goto out_invalid;
 
        return 0;
-out_err:
-       DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n",
+out_invalid:
+       DRM_ERROR("Invalid SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EINVAL;
+out_privileged:
+       DRM_ERROR("Privileged SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EPERM;
+out_old:
+       DRM_ERROR("Deprecated (disallowed) SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EINVAL;
+out_new:
+       DRM_ERROR("SVGA3D command: %d not supported by virtual hardware.\n",
                  cmd_id + SVGA_3D_CMD_BASE);
        return -EINVAL;
 }
@@ -1174,6 +1875,9 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
                case VMW_PL_GMR:
                        reloc->location->gmrId = bo->mem.start;
                        break;
+               case VMW_PL_MOB:
+                       *reloc->mob_loc = bo->mem.start;
+                       break;
                default:
                        BUG();
                }
@@ -1198,6 +1902,8 @@ static void vmw_resource_list_unreference(struct list_head *list)
        list_for_each_entry_safe(val, val_next, list, head) {
                list_del_init(&val->head);
                vmw_resource_unreference(&val->res);
+               if (unlikely(val->staged_bindings))
+                       kfree(val->staged_bindings);
                kfree(val);
        }
 }
@@ -1224,7 +1930,8 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context)
 }
 
 static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
-                                     struct ttm_buffer_object *bo)
+                                     struct ttm_buffer_object *bo,
+                                     bool validate_as_mob)
 {
        int ret;
 
@@ -1238,6 +1945,9 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
             dev_priv->dummy_query_bo_pinned))
                return 0;
 
+       if (validate_as_mob)
+               return ttm_bo_validate(bo, &vmw_mob_placement, true, false);
+
        /**
         * Put BO in VRAM if there is space, otherwise as a GMR.
         * If there is no space in VRAM and GMR ids are all used up,
@@ -1259,7 +1969,6 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
        return ret;
 }
 
-
 static int vmw_validate_buffers(struct vmw_private *dev_priv,
                                struct vmw_sw_context *sw_context)
 {
@@ -1267,7 +1976,8 @@ static int vmw_validate_buffers(struct vmw_private *dev_priv,
        int ret;
 
        list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
-               ret = vmw_validate_single_buffer(dev_priv, entry->base.bo);
+               ret = vmw_validate_single_buffer(dev_priv, entry->base.bo,
+                                                entry->validate_as_mob);
                if (unlikely(ret != 0))
                        return ret;
        }
@@ -1509,11 +2219,17 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                        goto out_err;
        }
 
+       ret = mutex_lock_interruptible(&dev_priv->binding_mutex);
+       if (unlikely(ret != 0)) {
+               ret = -ERESTARTSYS;
+               goto out_err;
+       }
+
        cmd = vmw_fifo_reserve(dev_priv, command_size);
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving fifo space for commands.\n");
                ret = -ENOMEM;
-               goto out_err;
+               goto out_unlock_binding;
        }
 
        vmw_apply_relocations(sw_context);
@@ -1538,6 +2254,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                DRM_ERROR("Fence submission error. Syncing.\n");
 
        vmw_resource_list_unreserve(&sw_context->resource_list, false);
+       mutex_unlock(&dev_priv->binding_mutex);
+
        ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
                                    (void *) fence);
 
@@ -1568,6 +2286,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 
        return 0;
 
+out_unlock_binding:
+       mutex_unlock(&dev_priv->binding_mutex);
 out_err:
        vmw_resource_relocations_free(&sw_context->res_relocations);
        vmw_free_relocations(sw_context);
index c62d20e8a6f169cce1173c849b42f160c55a4f39..436b013b42316a06296dd62cb0dda23f5095c075 100644 (file)
@@ -271,7 +271,7 @@ void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
        spin_unlock_irq(&fman->lock);
 }
 
-void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
+static void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
                                struct list_head *list)
 {
        struct vmw_fence_action *action, *next_action;
@@ -897,7 +897,7 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
  * Note that the action callbacks may be executed before this function
  * returns.
  */
-void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
+static void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
                              struct vmw_fence_action *action)
 {
        struct vmw_fence_manager *fman = fence->fman;
@@ -993,7 +993,7 @@ struct vmw_event_fence_pending {
        struct drm_vmw_event_fence event;
 };
 
-int vmw_event_fence_action_create(struct drm_file *file_priv,
+static int vmw_event_fence_action_create(struct drm_file *file_priv,
                                  struct vmw_fence_obj *fence,
                                  uint32_t flags,
                                  uint64_t user_data,
@@ -1080,7 +1080,8 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
         */
        if (arg->handle) {
                struct ttm_base_object *base =
-                       ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
+                       ttm_base_object_lookup_for_ref(dev_priv->tdev,
+                                                      arg->handle);
 
                if (unlikely(base == NULL)) {
                        DRM_ERROR("Fence event invalid fence object handle "
index 3eb148667d6382f003969757db0b9dd26555f909..6ccd993e26bf4ead66d0e8d1f1b4b592856d7599 100644 (file)
@@ -35,6 +35,23 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        uint32_t fifo_min, hwversion;
        const struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
+       if (!(dev_priv->capabilities & SVGA_CAP_3D))
+               return false;
+
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               uint32_t result;
+
+               if (!dev_priv->has_mob)
+                       return false;
+
+               mutex_lock(&dev_priv->hw_mutex);
+               vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D);
+               result = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+               mutex_unlock(&dev_priv->hw_mutex);
+
+               return (result != 0);
+       }
+
        if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
                return false;
 
@@ -511,24 +528,16 @@ out_err:
 }
 
 /**
- * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
+ * vmw_fifo_emit_dummy_legacy_query - emits a dummy query to the fifo using
+ * legacy query commands.
  *
  * @dev_priv: The device private structure.
  * @cid: The hardware context id used for the query.
  *
- * This function is used to emit a dummy occlusion query with
- * no primitives rendered between query begin and query end.
- * It's used to provide a query barrier, in order to know that when
- * this query is finished, all preceding queries are also finished.
- *
- * A Query results structure should have been initialized at the start
- * of the dev_priv->dummy_query_bo buffer object. And that buffer object
- * must also be either reserved or pinned when this function is called.
- *
- * Returns -ENOMEM on failure to reserve fifo space.
+ * See the vmw_fifo_emit_dummy_query documentation.
  */
-int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
-                             uint32_t cid)
+static int vmw_fifo_emit_dummy_legacy_query(struct vmw_private *dev_priv,
+                                           uint32_t cid)
 {
        /*
         * A query wait without a preceding query end will
@@ -566,3 +575,75 @@ int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
 
        return 0;
 }
+
+/**
+ * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
+ * guest-backed resource query commands.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * See the vmw_fifo_emit_dummy_query documentation.
+ */
+static int vmw_fifo_emit_dummy_gb_query(struct vmw_private *dev_priv,
+                                       uint32_t cid)
+{
+       /*
+        * A query wait without a preceding query end will
+        * actually finish all queries for this cid
+        * without writing to the query result structure.
+        */
+
+       struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdWaitForGBQuery body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Out of fifo space for dummy query.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = cid;
+       cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.offset = 0;
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+
+/**
+ * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
+ * appropriate resource query commands.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * This function is used to emit a dummy occlusion query with
+ * no primitives rendered between query begin and query end.
+ * It's used to provide a query barrier, in order to know that when
+ * this query is finished, all preceding queries are also finished.
+ *
+ * A Query results structure should have been initialized at the start
+ * of the dev_priv->dummy_query_bo buffer object. And that buffer object
+ * must also be either reserved or pinned when this function is called.
+ *
+ * Returns -ENOMEM on failure to reserve fifo space.
+ */
+int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+                             uint32_t cid)
+{
+       if (dev_priv->has_mob)
+               return vmw_fifo_emit_dummy_gb_query(dev_priv, cid);
+
+       return vmw_fifo_emit_dummy_legacy_query(dev_priv, cid);
+}
index 6ef0b035becbc5959f78ecf7b978629f90ae98e2..61d8d803199fc97085ef7e7ada07e7cbbd89bb5f 100644 (file)
@@ -125,181 +125,27 @@ static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
 }
 
 
-static void vmw_gmr_free_descriptors(struct device *dev, dma_addr_t desc_dma,
-                                    struct list_head *desc_pages)
-{
-       struct page *page, *next;
-       struct svga_guest_mem_descriptor *page_virtual;
-       unsigned int desc_per_page = PAGE_SIZE /
-               sizeof(struct svga_guest_mem_descriptor) - 1;
-
-       if (list_empty(desc_pages))
-               return;
-
-       list_for_each_entry_safe(page, next, desc_pages, lru) {
-               list_del_init(&page->lru);
-
-               if (likely(desc_dma != DMA_ADDR_INVALID)) {
-                       dma_unmap_page(dev, desc_dma, PAGE_SIZE,
-                                      DMA_TO_DEVICE);
-               }
-
-               page_virtual = kmap_atomic(page);
-               desc_dma = (dma_addr_t)
-                       le32_to_cpu(page_virtual[desc_per_page].ppn) <<
-                       PAGE_SHIFT;
-               kunmap_atomic(page_virtual);
-
-               __free_page(page);
-       }
-}
-
-/**
- * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
- * the number of used descriptors.
- *
- */
-
-static int vmw_gmr_build_descriptors(struct device *dev,
-                                    struct list_head *desc_pages,
-                                    struct vmw_piter *iter,
-                                    unsigned long num_pages,
-                                    dma_addr_t *first_dma)
-{
-       struct page *page;
-       struct svga_guest_mem_descriptor *page_virtual = NULL;
-       struct svga_guest_mem_descriptor *desc_virtual = NULL;
-       unsigned int desc_per_page;
-       unsigned long prev_pfn;
-       unsigned long pfn;
-       int ret;
-       dma_addr_t desc_dma;
-
-       desc_per_page = PAGE_SIZE /
-           sizeof(struct svga_guest_mem_descriptor) - 1;
-
-       while (likely(num_pages != 0)) {
-               page = alloc_page(__GFP_HIGHMEM);
-               if (unlikely(page == NULL)) {
-                       ret = -ENOMEM;
-                       goto out_err;
-               }
-
-               list_add_tail(&page->lru, desc_pages);
-               page_virtual = kmap_atomic(page);
-               desc_virtual = page_virtual - 1;
-               prev_pfn = ~(0UL);
-
-               while (likely(num_pages != 0)) {
-                       pfn = vmw_piter_dma_addr(iter) >> PAGE_SHIFT;
-
-                       if (pfn != prev_pfn + 1) {
-
-                               if (desc_virtual - page_virtual ==
-                                   desc_per_page - 1)
-                                       break;
-
-                               (++desc_virtual)->ppn = cpu_to_le32(pfn);
-                               desc_virtual->num_pages = cpu_to_le32(1);
-                       } else {
-                               uint32_t tmp =
-                                   le32_to_cpu(desc_virtual->num_pages);
-                               desc_virtual->num_pages = cpu_to_le32(tmp + 1);
-                       }
-                       prev_pfn = pfn;
-                       --num_pages;
-                       vmw_piter_next(iter);
-               }
-
-               (++desc_virtual)->ppn = DMA_PAGE_INVALID;
-               desc_virtual->num_pages = cpu_to_le32(0);
-               kunmap_atomic(page_virtual);
-       }
-
-       desc_dma = 0;
-       list_for_each_entry_reverse(page, desc_pages, lru) {
-               page_virtual = kmap_atomic(page);
-               page_virtual[desc_per_page].ppn = cpu_to_le32
-                       (desc_dma >> PAGE_SHIFT);
-               kunmap_atomic(page_virtual);
-               desc_dma = dma_map_page(dev, page, 0, PAGE_SIZE,
-                                       DMA_TO_DEVICE);
-
-               if (unlikely(dma_mapping_error(dev, desc_dma)))
-                       goto out_err;
-       }
-       *first_dma = desc_dma;
-
-       return 0;
-out_err:
-       vmw_gmr_free_descriptors(dev, DMA_ADDR_INVALID, desc_pages);
-       return ret;
-}
-
-static void vmw_gmr_fire_descriptors(struct vmw_private *dev_priv,
-                                    int gmr_id, dma_addr_t desc_dma)
-{
-       mutex_lock(&dev_priv->hw_mutex);
-
-       vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
-       wmb();
-       vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, desc_dma >> PAGE_SHIFT);
-       mb();
-
-       mutex_unlock(&dev_priv->hw_mutex);
-
-}
-
 int vmw_gmr_bind(struct vmw_private *dev_priv,
                 const struct vmw_sg_table *vsgt,
                 unsigned long num_pages,
                 int gmr_id)
 {
-       struct list_head desc_pages;
-       dma_addr_t desc_dma = 0;
-       struct device *dev = dev_priv->dev->dev;
        struct vmw_piter data_iter;
-       int ret;
 
        vmw_piter_start(&data_iter, vsgt, 0);
 
        if (unlikely(!vmw_piter_next(&data_iter)))
                return 0;
 
-       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
-               return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
-
-       if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR)))
-               return -EINVAL;
-
-       if (vsgt->num_regions > dev_priv->max_gmr_descriptors)
+       if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2)))
                return -EINVAL;
 
-       INIT_LIST_HEAD(&desc_pages);
-
-       ret = vmw_gmr_build_descriptors(dev, &desc_pages, &data_iter,
-                                       num_pages, &desc_dma);
-       if (unlikely(ret != 0))
-               return ret;
-
-       vmw_gmr_fire_descriptors(dev_priv, gmr_id, desc_dma);
-       vmw_gmr_free_descriptors(dev, desc_dma, &desc_pages);
-
-       return 0;
+       return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
 }
 
 
 void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
 {
-       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
+       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
                vmw_gmr2_unbind(dev_priv, gmr_id);
-               return;
-       }
-
-       mutex_lock(&dev_priv->hw_mutex);
-       vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
-       wmb();
-       vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0);
-       mb();
-       mutex_unlock(&dev_priv->hw_mutex);
 }
index c5c054ae9056aaea2479eb6a9018013098708ce2..b1273e8e9a6903e2d15d3b153177e9a99c806859 100644 (file)
@@ -125,10 +125,21 @@ static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
                return -ENOMEM;
 
        spin_lock_init(&gman->lock);
-       gman->max_gmr_pages = dev_priv->max_gmr_pages;
        gman->used_gmr_pages = 0;
        ida_init(&gman->gmr_ida);
-       gman->max_gmr_ids = p_size;
+
+       switch (p_size) {
+       case VMW_PL_GMR:
+               gman->max_gmr_ids = dev_priv->max_gmr_ids;
+               gman->max_gmr_pages = dev_priv->max_gmr_pages;
+               break;
+       case VMW_PL_MOB:
+               gman->max_gmr_ids = VMWGFX_NUM_MOB;
+               gman->max_gmr_pages = dev_priv->max_mob_pages;
+               break;
+       default:
+               BUG();
+       }
        man->priv = (void *) gman;
        return 0;
 }
index 45d5b5ab6ca9d8788fe80f0fbfd9f164203c026a..116c49736763ee81a4b4d664bfba2ab0a5e3d5cd 100644 (file)
@@ -53,7 +53,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                param->value = dev_priv->fifo.capabilities;
                break;
        case DRM_VMW_PARAM_MAX_FB_SIZE:
-               param->value = dev_priv->vram_size;
+               param->value = dev_priv->prim_bb_mem;
                break;
        case DRM_VMW_PARAM_FIFO_HW_VERSION:
        {
@@ -71,6 +71,17 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
        case DRM_VMW_PARAM_MAX_SURF_MEMORY:
                param->value = dev_priv->memory_size;
                break;
+       case DRM_VMW_PARAM_3D_CAPS_SIZE:
+               if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
+                       param->value = SVGA3D_DEVCAP_MAX;
+               else
+                       param->value = (SVGA_FIFO_3D_CAPS_LAST -
+                                       SVGA_FIFO_3D_CAPS + 1);
+               param->value *= sizeof(uint32_t);
+               break;
+       case DRM_VMW_PARAM_MAX_MOB_MEMORY:
+               param->value = dev_priv->max_mob_pages * PAGE_SIZE;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
@@ -92,13 +103,19 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
        void *bounce;
        int ret;
+       bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
 
        if (unlikely(arg->pad64 != 0)) {
                DRM_ERROR("Illegal GET_3D_CAP argument.\n");
                return -EINVAL;
        }
 
-       size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) << 2;
+       if (gb_objects)
+               size = SVGA3D_DEVCAP_MAX;
+       else
+               size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1);
+
+       size *= sizeof(uint32_t);
 
        if (arg->max_size < size)
                size = arg->max_size;
@@ -109,8 +126,22 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
                return -ENOMEM;
        }
 
-       fifo_mem = dev_priv->mmio_virt;
-       memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+       if (gb_objects) {
+               int i;
+               uint32_t *bounce32 = (uint32_t *) bounce;
+
+               mutex_lock(&dev_priv->hw_mutex);
+               for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) {
+                       vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
+                       *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+               }
+               mutex_unlock(&dev_priv->hw_mutex);
+
+       } else {
+
+               fifo_mem = dev_priv->mmio_virt;
+               memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+       }
 
        ret = copy_to_user(buffer, bounce, size);
        if (ret)
index 4640adbcaf91b9609643895432d858313e56e2e4..0c423766c44119ca923825e879e3d05b7058cc90 100644 (file)
@@ -30,7 +30,7 @@
 
 #define VMW_FENCE_WRAP (1 << 24)
 
-irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t vmw_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *)arg;
        struct vmw_private *dev_priv = vmw_priv(dev);
index 03f1c203863193621d9941af3051169ea2f79afb..8a650413dea57c8e50212b41f8be00abba3ee8af 100644 (file)
@@ -40,7 +40,7 @@ struct vmw_clip_rect {
  * Clip @num_rects number of @rects against @clip storing the
  * results in @out_rects and the number of passed rects in @out_num.
  */
-void vmw_clip_cliprects(struct drm_clip_rect *rects,
+static void vmw_clip_cliprects(struct drm_clip_rect *rects,
                        int num_rects,
                        struct vmw_clip_rect clip,
                        SVGASignedRect *out_rects,
@@ -423,7 +423,7 @@ struct vmw_framebuffer_surface {
        struct drm_master *master;
 };
 
-void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
+static void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
 {
        struct vmw_framebuffer_surface *vfbs =
                vmw_framebuffer_to_vfbs(framebuffer);
@@ -589,7 +589,7 @@ out_free_tmp:
        return ret;
 }
 
-int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
+static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                  struct drm_file *file_priv,
                                  unsigned flags, unsigned color,
                                  struct drm_clip_rect *clips,
@@ -609,9 +609,13 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
        if (!dev_priv->sou_priv)
                return -EINVAL;
 
+       drm_modeset_lock_all(dev_priv->dev);
+
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
+               drm_modeset_unlock_all(dev_priv->dev);
                return ret;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -629,6 +633,9 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                   clips, num_clips, inc, NULL);
 
        ttm_read_unlock(&vmaster->lock);
+
+       drm_modeset_unlock_all(dev_priv->dev);
+
        return 0;
 }
 
@@ -665,9 +672,9 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 
        if (unlikely(surface->mip_levels[0] != 1 ||
                     surface->num_sizes != 1 ||
-                    surface->sizes[0].width < mode_cmd->width ||
-                    surface->sizes[0].height < mode_cmd->height ||
-                    surface->sizes[0].depth != 1)) {
+                    surface->base_size.width < mode_cmd->width ||
+                    surface->base_size.height < mode_cmd->height ||
+                    surface->base_size.depth != 1)) {
                DRM_ERROR("Incompatible surface dimensions "
                          "for requested mode.\n");
                return -EINVAL;
@@ -754,7 +761,7 @@ struct vmw_framebuffer_dmabuf {
        struct vmw_dma_buffer *buffer;
 };
 
-void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
+static void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
 {
        struct vmw_framebuffer_dmabuf *vfbd =
                vmw_framebuffer_to_vfbd(framebuffer);
@@ -940,7 +947,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
        return ret;
 }
 
-int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
                                 struct drm_file *file_priv,
                                 unsigned flags, unsigned color,
                                 struct drm_clip_rect *clips,
@@ -953,9 +960,13 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
        struct drm_clip_rect norect;
        int ret, increment = 1;
 
+       drm_modeset_lock_all(dev_priv->dev);
+
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
+               drm_modeset_unlock_all(dev_priv->dev);
                return ret;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -979,6 +990,9 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
        }
 
        ttm_read_unlock(&vmaster->lock);
+
+       drm_modeset_unlock_all(dev_priv->dev);
+
        return ret;
 }
 
@@ -1631,7 +1645,7 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
                                uint32_t pitch,
                                uint32_t height)
 {
-       return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+       return ((u64) pitch * (u64) height) < (u64) dev_priv->prim_bb_mem;
 }
 
 
@@ -1663,7 +1677,7 @@ void vmw_disable_vblank(struct drm_device *dev, int crtc)
  * Small shared kms functions.
  */
 
-int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
                         struct drm_vmw_rect *rects)
 {
        struct drm_device *dev = dev_priv->dev;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
new file mode 100644 (file)
index 0000000..4910e7b
--- /dev/null
@@ -0,0 +1,652 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2012 VMware, Inc., Palo Alto, CA., USA
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+
+/*
+ * If we set up the screen target otable, screen objects stop working.
+ */
+
+#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) ? 0 : 1)
+
+#ifdef CONFIG_64BIT
+#define VMW_PPN_SIZE 8
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH64_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH64_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH64_2
+#else
+#define VMW_PPN_SIZE 4
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH_2
+#endif
+
+/*
+ * struct vmw_mob - Structure containing page table and metadata for a
+ * Guest Memory OBject.
+ *
+ * @num_pages       Number of pages that make up the page table.
+ * @pt_level        The indirection level of the page table. 0-2.
+ * @pt_root_page    DMA address of the level 0 page of the page table.
+ */
+struct vmw_mob {
+       struct ttm_buffer_object *pt_bo;
+       unsigned long num_pages;
+       unsigned pt_level;
+       dma_addr_t pt_root_page;
+       uint32_t id;
+};
+
+/*
+ * struct vmw_otable - Guest Memory OBject table metadata
+ *
+ * @size:           Size of the table (page-aligned).
+ * @page_table:     Pointer to a struct vmw_mob holding the page table.
+ */
+struct vmw_otable {
+       unsigned long size;
+       struct vmw_mob *page_table;
+};
+
+static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
+                              struct vmw_mob *mob);
+static void vmw_mob_pt_setup(struct vmw_mob *mob,
+                            struct vmw_piter data_iter,
+                            unsigned long num_data_pages);
+
+/*
+ * vmw_setup_otable_base - Issue an object table base setup command to
+ * the device
+ *
+ * @dev_priv:       Pointer to a device private structure
+ * @type:           Type of object table base
+ * @offset          Start of table offset into dev_priv::otable_bo
+ * @otable          Pointer to otable metadata;
+ *
+ * This function returns -ENOMEM if it fails to reserve fifo space,
+ * and may block waiting for fifo space.
+ */
+static int vmw_setup_otable_base(struct vmw_private *dev_priv,
+                                SVGAOTableType type,
+                                unsigned long offset,
+                                struct vmw_otable *otable)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetOTableBase64 body;
+       } *cmd;
+       struct vmw_mob *mob;
+       const struct vmw_sg_table *vsgt;
+       struct vmw_piter iter;
+       int ret;
+
+       BUG_ON(otable->page_table != NULL);
+
+       vsgt = vmw_bo_sg_table(dev_priv->otable_bo);
+       vmw_piter_start(&iter, vsgt, offset >> PAGE_SHIFT);
+       WARN_ON(!vmw_piter_next(&iter));
+
+       mob = vmw_mob_create(otable->size >> PAGE_SHIFT);
+       if (unlikely(mob == NULL)) {
+               DRM_ERROR("Failed creating OTable page table.\n");
+               return -ENOMEM;
+       }
+
+       if (otable->size <= PAGE_SIZE) {
+               mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
+               mob->pt_root_page = vmw_piter_dma_addr(&iter);
+       } else if (vsgt->num_regions == 1) {
+               mob->pt_level = SVGA3D_MOBFMT_RANGE;
+               mob->pt_root_page = vmw_piter_dma_addr(&iter);
+       } else {
+               ret = vmw_mob_pt_populate(dev_priv, mob);
+               if (unlikely(ret != 0))
+                       goto out_no_populate;
+
+               vmw_mob_pt_setup(mob, iter, otable->size >> PAGE_SHIFT);
+               mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
+               goto out_no_fifo;
+       }
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE64;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.type = type;
+       cmd->body.baseAddress = cpu_to_le64(mob->pt_root_page >> PAGE_SHIFT);
+       cmd->body.sizeInBytes = otable->size;
+       cmd->body.validSizeInBytes = 0;
+       cmd->body.ptDepth = mob->pt_level;
+
+       /*
+        * The device doesn't support this, But the otable size is
+        * determined at compile-time, so this BUG shouldn't trigger
+        * randomly.
+        */
+       BUG_ON(mob->pt_level == VMW_MOBFMT_PTDEPTH_2);
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       otable->page_table = mob;
+
+       return 0;
+
+out_no_fifo:
+out_no_populate:
+       vmw_mob_destroy(mob);
+       return ret;
+}
+
+/*
+ * vmw_takedown_otable_base - Issue an object table base takedown command
+ * to the device
+ *
+ * @dev_priv:       Pointer to a device private structure
+ * @type:           Type of object table base
+ *
+ */
+static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
+                                    SVGAOTableType type,
+                                    struct vmw_otable *otable)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetOTableBase body;
+       } *cmd;
+       struct ttm_buffer_object *bo;
+
+       if (otable->page_table == NULL)
+               return;
+
+       bo = otable->page_table->pt_bo;
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL))
+               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.type = type;
+       cmd->body.baseAddress = 0;
+       cmd->body.sizeInBytes = 0;
+       cmd->body.validSizeInBytes = 0;
+       cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       if (bo) {
+               int ret;
+
+               ret = ttm_bo_reserve(bo, false, true, false, NULL);
+               BUG_ON(ret != 0);
+
+               vmw_fence_single_bo(bo, NULL);
+               ttm_bo_unreserve(bo);
+       }
+
+       vmw_mob_destroy(otable->page_table);
+       otable->page_table = NULL;
+}
+
+/*
+ * vmw_otables_setup - Set up guest backed memory object tables
+ *
+ * @dev_priv:       Pointer to a device private structure
+ *
+ * Takes care of the device guest backed surface
+ * initialization, by setting up the guest backed memory object tables.
+ * Returns 0 on success and various error codes on failure. A succesful return
+ * means the object tables can be taken down using the vmw_otables_takedown
+ * function.
+ */
+int vmw_otables_setup(struct vmw_private *dev_priv)
+{
+       unsigned long offset;
+       unsigned long bo_size;
+       struct vmw_otable *otables;
+       SVGAOTableType i;
+       int ret;
+
+       otables = kzalloc(SVGA_OTABLE_DX9_MAX * sizeof(*otables),
+                         GFP_KERNEL);
+       if (unlikely(otables == NULL)) {
+               DRM_ERROR("Failed to allocate space for otable "
+                         "metadata.\n");
+               return -ENOMEM;
+       }
+
+       otables[SVGA_OTABLE_MOB].size =
+               VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SURFACE].size =
+               VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE;
+       otables[SVGA_OTABLE_CONTEXT].size =
+               VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SHADER].size =
+               VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SCREEN_TARGET].size =
+               VMWGFX_NUM_GB_SCREEN_TARGET *
+               SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE;
+
+       bo_size = 0;
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX; ++i) {
+               otables[i].size =
+                       (otables[i].size + PAGE_SIZE - 1) & PAGE_MASK;
+               bo_size += otables[i].size;
+       }
+
+       ret = ttm_bo_create(&dev_priv->bdev, bo_size,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL,
+                           &dev_priv->otable_bo);
+
+       if (unlikely(ret != 0))
+               goto out_no_bo;
+
+       ret = ttm_bo_reserve(dev_priv->otable_bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+       ret = vmw_bo_driver.ttm_tt_populate(dev_priv->otable_bo->ttm);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+       ret = vmw_bo_map_dma(dev_priv->otable_bo);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+
+       ttm_bo_unreserve(dev_priv->otable_bo);
+
+       offset = 0;
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i) {
+               ret = vmw_setup_otable_base(dev_priv, i, offset,
+                                           &otables[i]);
+               if (unlikely(ret != 0))
+                       goto out_no_setup;
+               offset += otables[i].size;
+       }
+
+       dev_priv->otables = otables;
+       return 0;
+
+out_unreserve:
+       ttm_bo_unreserve(dev_priv->otable_bo);
+out_no_setup:
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
+               vmw_takedown_otable_base(dev_priv, i, &otables[i]);
+
+       ttm_bo_unref(&dev_priv->otable_bo);
+out_no_bo:
+       kfree(otables);
+       return ret;
+}
+
+
+/*
+ * vmw_otables_takedown - Take down guest backed memory object tables
+ *
+ * @dev_priv:       Pointer to a device private structure
+ *
+ * Take down the Guest Memory Object tables.
+ */
+void vmw_otables_takedown(struct vmw_private *dev_priv)
+{
+       SVGAOTableType i;
+       struct ttm_buffer_object *bo = dev_priv->otable_bo;
+       int ret;
+
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
+               vmw_takedown_otable_base(dev_priv, i,
+                                        &dev_priv->otables[i]);
+
+       ret = ttm_bo_reserve(bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+
+       vmw_fence_single_bo(bo, NULL);
+       ttm_bo_unreserve(bo);
+
+       ttm_bo_unref(&dev_priv->otable_bo);
+       kfree(dev_priv->otables);
+       dev_priv->otables = NULL;
+}
+
+
+/*
+ * vmw_mob_calculate_pt_pages - Calculate the number of page table pages
+ * needed for a guest backed memory object.
+ *
+ * @data_pages:  Number of data pages in the memory object buffer.
+ */
+static unsigned long vmw_mob_calculate_pt_pages(unsigned long data_pages)
+{
+       unsigned long data_size = data_pages * PAGE_SIZE;
+       unsigned long tot_size = 0;
+
+       while (likely(data_size > PAGE_SIZE)) {
+               data_size = DIV_ROUND_UP(data_size, PAGE_SIZE);
+               data_size *= VMW_PPN_SIZE;
+               tot_size += (data_size + PAGE_SIZE - 1) & PAGE_MASK;
+       }
+
+       return tot_size >> PAGE_SHIFT;
+}
+
+/*
+ * vmw_mob_create - Create a mob, but don't populate it.
+ *
+ * @data_pages:  Number of data pages of the underlying buffer object.
+ */
+struct vmw_mob *vmw_mob_create(unsigned long data_pages)
+{
+       struct vmw_mob *mob = kzalloc(sizeof(*mob), GFP_KERNEL);
+
+       if (unlikely(mob == NULL))
+               return NULL;
+
+       mob->num_pages = vmw_mob_calculate_pt_pages(data_pages);
+
+       return mob;
+}
+
+/*
+ * vmw_mob_pt_populate - Populate the mob pagetable
+ *
+ * @mob:         Pointer to the mob the pagetable of which we want to
+ *               populate.
+ *
+ * This function allocates memory to be used for the pagetable, and
+ * adjusts TTM memory accounting accordingly. Returns ENOMEM if
+ * memory resources aren't sufficient and may cause TTM buffer objects
+ * to be swapped out by using the TTM memory accounting function.
+ */
+static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
+                              struct vmw_mob *mob)
+{
+       int ret;
+       BUG_ON(mob->pt_bo != NULL);
+
+       ret = ttm_bo_create(&dev_priv->bdev, mob->num_pages * PAGE_SIZE,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL, &mob->pt_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_bo_reserve(mob->pt_bo, false, true, false, NULL);
+
+       BUG_ON(ret != 0);
+       ret = vmw_bo_driver.ttm_tt_populate(mob->pt_bo->ttm);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+       ret = vmw_bo_map_dma(mob->pt_bo);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+
+       ttm_bo_unreserve(mob->pt_bo);
+       
+       return 0;
+
+out_unreserve:
+       ttm_bo_unreserve(mob->pt_bo);
+       ttm_bo_unref(&mob->pt_bo);
+
+       return ret;
+}
+
+/**
+ * vmw_mob_assign_ppn - Assign a value to a page table entry
+ *
+ * @addr: Pointer to pointer to page table entry.
+ * @val: The page table entry
+ *
+ * Assigns a value to a page table entry pointed to by *@addr and increments
+ * *@addr according to the page table entry size.
+ */
+#if (VMW_PPN_SIZE == 8)
+static void vmw_mob_assign_ppn(__le32 **addr, dma_addr_t val)
+{
+       *((__le64 *) *addr) = cpu_to_le64(val >> PAGE_SHIFT);
+       *addr += 2;
+}
+#else
+static void vmw_mob_assign_ppn(__le32 **addr, dma_addr_t val)
+{
+       *(*addr)++ = cpu_to_le32(val >> PAGE_SHIFT);
+}
+#endif
+
+/*
+ * vmw_mob_build_pt - Build a pagetable
+ *
+ * @data_addr:      Array of DMA addresses to the underlying buffer
+ *                  object's data pages.
+ * @num_data_pages: Number of buffer object data pages.
+ * @pt_pages:       Array of page pointers to the page table pages.
+ *
+ * Returns the number of page table pages actually used.
+ * Uses atomic kmaps of highmem pages to avoid TLB thrashing.
+ */
+static unsigned long vmw_mob_build_pt(struct vmw_piter *data_iter,
+                                     unsigned long num_data_pages,
+                                     struct vmw_piter *pt_iter)
+{
+       unsigned long pt_size = num_data_pages * VMW_PPN_SIZE;
+       unsigned long num_pt_pages = DIV_ROUND_UP(pt_size, PAGE_SIZE);
+       unsigned long pt_page;
+       __le32 *addr, *save_addr;
+       unsigned long i;
+       struct page *page;
+
+       for (pt_page = 0; pt_page < num_pt_pages; ++pt_page) {
+               page = vmw_piter_page(pt_iter);
+
+               save_addr = addr = kmap_atomic(page);
+
+               for (i = 0; i < PAGE_SIZE / VMW_PPN_SIZE; ++i) {
+                       vmw_mob_assign_ppn(&addr,
+                                          vmw_piter_dma_addr(data_iter));
+                       if (unlikely(--num_data_pages == 0))
+                               break;
+                       WARN_ON(!vmw_piter_next(data_iter));
+               }
+               kunmap_atomic(save_addr);
+               vmw_piter_next(pt_iter);
+       }
+
+       return num_pt_pages;
+}
+
+/*
+ * vmw_mob_build_pt - Set up a multilevel mob pagetable
+ *
+ * @mob:            Pointer to a mob whose page table needs setting up.
+ * @data_addr       Array of DMA addresses to the buffer object's data
+ *                  pages.
+ * @num_data_pages: Number of buffer object data pages.
+ *
+ * Uses tail recursion to set up a multilevel mob page table.
+ */
+static void vmw_mob_pt_setup(struct vmw_mob *mob,
+                            struct vmw_piter data_iter,
+                            unsigned long num_data_pages)
+{
+       unsigned long num_pt_pages = 0;
+       struct ttm_buffer_object *bo = mob->pt_bo;
+       struct vmw_piter save_pt_iter;
+       struct vmw_piter pt_iter;
+       const struct vmw_sg_table *vsgt;
+       int ret;
+
+       ret = ttm_bo_reserve(bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+
+       vsgt = vmw_bo_sg_table(bo);
+       vmw_piter_start(&pt_iter, vsgt, 0);
+       BUG_ON(!vmw_piter_next(&pt_iter));
+       mob->pt_level = 0;
+       while (likely(num_data_pages > 1)) {
+               ++mob->pt_level;
+               BUG_ON(mob->pt_level > 2);
+               save_pt_iter = pt_iter;
+               num_pt_pages = vmw_mob_build_pt(&data_iter, num_data_pages,
+                                               &pt_iter);
+               data_iter = save_pt_iter;
+               num_data_pages = num_pt_pages;
+       }
+
+       mob->pt_root_page = vmw_piter_dma_addr(&save_pt_iter);
+       ttm_bo_unreserve(bo);
+}
+
+/*
+ * vmw_mob_destroy - Destroy a mob, unpopulating first if necessary.
+ *
+ * @mob:            Pointer to a mob to destroy.
+ */
+void vmw_mob_destroy(struct vmw_mob *mob)
+{
+       if (mob->pt_bo)
+               ttm_bo_unref(&mob->pt_bo);
+       kfree(mob);
+}
+
+/*
+ * vmw_mob_unbind - Hide a mob from the device.
+ *
+ * @dev_priv:       Pointer to a device private.
+ * @mob_id:         Device id of the mob to unbind.
+ */
+void vmw_mob_unbind(struct vmw_private *dev_priv,
+                   struct vmw_mob *mob)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBMob body;
+       } *cmd;
+       int ret;
+       struct ttm_buffer_object *bo = mob->pt_bo;
+
+       if (bo) {
+               ret = ttm_bo_reserve(bo, false, true, false, NULL);
+               /*
+                * Noone else should be using this buffer.
+                */
+               BUG_ON(ret != 0);
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for Memory "
+                         "Object unbinding.\n");
+       }
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.mobid = mob->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (bo) {
+               vmw_fence_single_bo(bo, NULL);
+               ttm_bo_unreserve(bo);
+       }
+       vmw_3d_resource_dec(dev_priv, false);
+}
+
+/*
+ * vmw_mob_bind - Make a mob visible to the device after first
+ *                populating it if necessary.
+ *
+ * @dev_priv:       Pointer to a device private.
+ * @mob:            Pointer to the mob we're making visible.
+ * @data_addr:      Array of DMA addresses to the data pages of the underlying
+ *                  buffer object.
+ * @num_data_pages: Number of data pages of the underlying buffer
+ *                  object.
+ * @mob_id:         Device id of the mob to bind
+ *
+ * This function is intended to be interfaced with the ttm_tt backend
+ * code.
+ */
+int vmw_mob_bind(struct vmw_private *dev_priv,
+                struct vmw_mob *mob,
+                const struct vmw_sg_table *vsgt,
+                unsigned long num_data_pages,
+                int32_t mob_id)
+{
+       int ret;
+       bool pt_set_up = false;
+       struct vmw_piter data_iter;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBMob64 body;
+       } *cmd;
+
+       mob->id = mob_id;
+       vmw_piter_start(&data_iter, vsgt, 0);
+       if (unlikely(!vmw_piter_next(&data_iter)))
+               return 0;
+
+       if (likely(num_data_pages == 1)) {
+               mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
+               mob->pt_root_page = vmw_piter_dma_addr(&data_iter);
+       } else if (vsgt->num_regions == 1) {
+               mob->pt_level = SVGA3D_MOBFMT_RANGE;
+               mob->pt_root_page = vmw_piter_dma_addr(&data_iter);
+       } else if (unlikely(mob->pt_bo == NULL)) {
+               ret = vmw_mob_pt_populate(dev_priv, mob);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               vmw_mob_pt_setup(mob, data_iter, num_data_pages);
+               pt_set_up = true;
+               mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+       }
+
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for Memory "
+                         "Object binding.\n");
+               goto out_no_cmd_space;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_MOB64;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.mobid = mob_id;
+       cmd->body.ptDepth = mob->pt_level;
+       cmd->body.base = cpu_to_le64(mob->pt_root_page >> PAGE_SHIFT);
+       cmd->body.sizeInBytes = num_data_pages * PAGE_SIZE;
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+
+out_no_cmd_space:
+       vmw_3d_resource_dec(dev_priv, false);
+       if (pt_set_up)
+               ttm_bo_unref(&mob->pt_bo);
+
+       return -ENOMEM;
+}
index 9b5ea2ac7ddff21562aa7ef52a2f96872c623116..6fdd82d42f6549d2af208516ad22b26d45785e28 100644 (file)
@@ -215,6 +215,7 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
        res->func = func;
        INIT_LIST_HEAD(&res->lru_head);
        INIT_LIST_HEAD(&res->mob_head);
+       INIT_LIST_HEAD(&res->binding_head);
        res->id = -1;
        res->backup = NULL;
        res->backup_offset = 0;
@@ -441,6 +442,21 @@ static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
        ttm_bo_unref(&bo);
 }
 
+static void vmw_user_dmabuf_ref_obj_release(struct ttm_base_object *base,
+                                           enum ttm_ref_type ref_type)
+{
+       struct vmw_user_dma_buffer *user_bo;
+       user_bo = container_of(base, struct vmw_user_dma_buffer, prime.base);
+
+       switch (ref_type) {
+       case TTM_REF_SYNCCPU_WRITE:
+               ttm_bo_synccpu_write_release(&user_bo->dma.base);
+               break;
+       default:
+               BUG();
+       }
+}
+
 /**
  * vmw_user_dmabuf_alloc - Allocate a user dma buffer
  *
@@ -471,6 +487,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
        }
 
        ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
+                             (dev_priv->has_mob) ?
+                             &vmw_sys_placement :
                              &vmw_vram_sys_placement, true,
                              &vmw_user_dmabuf_destroy);
        if (unlikely(ret != 0))
@@ -482,7 +500,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
                                    &user_bo->prime,
                                    shareable,
                                    ttm_buffer_type,
-                                   &vmw_user_dmabuf_release, NULL);
+                                   &vmw_user_dmabuf_release,
+                                   &vmw_user_dmabuf_ref_obj_release);
        if (unlikely(ret != 0)) {
                ttm_bo_unref(&tmp);
                goto out_no_base_object;
@@ -515,6 +534,130 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
                vmw_user_bo->prime.base.shareable) ? 0 : -EPERM;
 }
 
+/**
+ * vmw_user_dmabuf_synccpu_grab - Grab a struct vmw_user_dma_buffer for cpu
+ * access, idling previous GPU operations on the buffer and optionally
+ * blocking it for further command submissions.
+ *
+ * @user_bo: Pointer to the buffer object being grabbed for CPU access
+ * @tfile: Identifying the caller.
+ * @flags: Flags indicating how the grab should be performed.
+ *
+ * A blocking grab will be automatically released when @tfile is closed.
+ */
+static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
+                                       struct ttm_object_file *tfile,
+                                       uint32_t flags)
+{
+       struct ttm_buffer_object *bo = &user_bo->dma.base;
+       bool existed;
+       int ret;
+
+       if (flags & drm_vmw_synccpu_allow_cs) {
+               struct ttm_bo_device *bdev = bo->bdev;
+
+               spin_lock(&bdev->fence_lock);
+               ret = ttm_bo_wait(bo, false, true,
+                                 !!(flags & drm_vmw_synccpu_dontblock));
+               spin_unlock(&bdev->fence_lock);
+               return ret;
+       }
+
+       ret = ttm_bo_synccpu_write_grab
+               (bo, !!(flags & drm_vmw_synccpu_dontblock));
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_ref_object_add(tfile, &user_bo->prime.base,
+                                TTM_REF_SYNCCPU_WRITE, &existed);
+       if (ret != 0 || existed)
+               ttm_bo_synccpu_write_release(&user_bo->dma.base);
+
+       return ret;
+}
+
+/**
+ * vmw_user_dmabuf_synccpu_release - Release a previous grab for CPU access,
+ * and unblock command submission on the buffer if blocked.
+ *
+ * @handle: Handle identifying the buffer object.
+ * @tfile: Identifying the caller.
+ * @flags: Flags indicating the type of release.
+ */
+static int vmw_user_dmabuf_synccpu_release(uint32_t handle,
+                                          struct ttm_object_file *tfile,
+                                          uint32_t flags)
+{
+       if (!(flags & drm_vmw_synccpu_allow_cs))
+               return ttm_ref_object_base_unref(tfile, handle,
+                                                TTM_REF_SYNCCPU_WRITE);
+
+       return 0;
+}
+
+/**
+ * vmw_user_dmabuf_synccpu_release - ioctl function implementing the synccpu
+ * functionality.
+ *
+ * @dev: Identifies the drm device.
+ * @data: Pointer to the ioctl argument.
+ * @file_priv: Identifies the caller.
+ *
+ * This function checks the ioctl arguments for validity and calls the
+ * relevant synccpu functions.
+ */
+int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv)
+{
+       struct drm_vmw_synccpu_arg *arg =
+               (struct drm_vmw_synccpu_arg *) data;
+       struct vmw_dma_buffer *dma_buf;
+       struct vmw_user_dma_buffer *user_bo;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret;
+
+       if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0
+           || (arg->flags & ~(drm_vmw_synccpu_read | drm_vmw_synccpu_write |
+                              drm_vmw_synccpu_dontblock |
+                              drm_vmw_synccpu_allow_cs)) != 0) {
+               DRM_ERROR("Illegal synccpu flags.\n");
+               return -EINVAL;
+       }
+
+       switch (arg->op) {
+       case drm_vmw_synccpu_grab:
+               ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               user_bo = container_of(dma_buf, struct vmw_user_dma_buffer,
+                                      dma);
+               ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags);
+               vmw_dmabuf_unreference(&dma_buf);
+               if (unlikely(ret != 0 && ret != -ERESTARTSYS &&
+                            ret != -EBUSY)) {
+                       DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n",
+                                 (unsigned int) arg->handle);
+                       return ret;
+               }
+               break;
+       case drm_vmw_synccpu_release:
+               ret = vmw_user_dmabuf_synccpu_release(arg->handle, tfile,
+                                                     arg->flags);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Failed synccpu release on handle 0x%08x.\n",
+                                 (unsigned int) arg->handle);
+                       return ret;
+               }
+               break;
+       default:
+               DRM_ERROR("Invalid synccpu operation.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                           struct drm_file *file_priv)
 {
@@ -591,7 +734,8 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 }
 
 int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
-                             struct vmw_dma_buffer *dma_buf)
+                             struct vmw_dma_buffer *dma_buf,
+                             uint32_t *handle)
 {
        struct vmw_user_dma_buffer *user_bo;
 
@@ -599,6 +743,8 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
                return -EINVAL;
 
        user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma);
+
+       *handle = user_bo->prime.base.hash.key;
        return ttm_ref_object_add(tfile, &user_bo->prime.base,
                                  TTM_REF_USAGE, NULL);
 }
@@ -1291,11 +1437,54 @@ void vmw_fence_single_bo(struct ttm_buffer_object *bo,
  * @mem:            The truct ttm_mem_reg indicating to what memory
  *                  region the move is taking place.
  *
- * For now does nothing.
+ * Evicts the Guest Backed hardware resource if the backup
+ * buffer is being moved out of MOB memory.
+ * Note that this function should not race with the resource
+ * validation code as long as it accesses only members of struct
+ * resource that remain static while bo::res is !NULL and
+ * while we have @bo reserved. struct resource::backup is *not* a
+ * static member. The resource validation code will take care
+ * to set @bo::res to NULL, while having @bo reserved when the
+ * buffer is no longer bound to the resource, so @bo:res can be
+ * used to determine whether there is a need to unbind and whether
+ * it is safe to unbind.
  */
 void vmw_resource_move_notify(struct ttm_buffer_object *bo,
                              struct ttm_mem_reg *mem)
 {
+       struct vmw_dma_buffer *dma_buf;
+
+       if (mem == NULL)
+               return;
+
+       if (bo->destroy != vmw_dmabuf_bo_free &&
+           bo->destroy != vmw_user_dmabuf_destroy)
+               return;
+
+       dma_buf = container_of(bo, struct vmw_dma_buffer, base);
+
+       if (mem->mem_type != VMW_PL_MOB) {
+               struct vmw_resource *res, *n;
+               struct ttm_bo_device *bdev = bo->bdev;
+               struct ttm_validate_buffer val_buf;
+
+               val_buf.bo = bo;
+
+               list_for_each_entry_safe(res, n, &dma_buf->res_list, mob_head) {
+
+                       if (unlikely(res->func->unbind == NULL))
+                               continue;
+
+                       (void) res->func->unbind(res, true, &val_buf);
+                       res->backup_dirty = true;
+                       res->res_dirty = false;
+                       list_del_init(&res->mob_head);
+               }
+
+               spin_lock(&bdev->fence_lock);
+               (void) ttm_bo_wait(bo, false, false, false);
+               spin_unlock(&bdev->fence_lock);
+       }
 }
 
 /**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
new file mode 100644 (file)
index 0000000..1457ec4
--- /dev/null
@@ -0,0 +1,441 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2009-2012 VMware, Inc., Palo Alto, CA., USA
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_resource_priv.h"
+#include "ttm/ttm_placement.h"
+
+struct vmw_shader {
+       struct vmw_resource res;
+       SVGA3dShaderType type;
+       uint32_t size;
+};
+
+struct vmw_user_shader {
+       struct ttm_base_object base;
+       struct vmw_shader shader;
+};
+
+static void vmw_user_shader_free(struct vmw_resource *res);
+static struct vmw_resource *
+vmw_user_shader_base_to_res(struct ttm_base_object *base);
+
+static int vmw_gb_shader_create(struct vmw_resource *res);
+static int vmw_gb_shader_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_shader_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_shader_destroy(struct vmw_resource *res);
+
+static uint64_t vmw_user_shader_size;
+
+static const struct vmw_user_resource_conv user_shader_conv = {
+       .object_type = VMW_RES_SHADER,
+       .base_obj_to_res = vmw_user_shader_base_to_res,
+       .res_free = vmw_user_shader_free
+};
+
+const struct vmw_user_resource_conv *user_shader_converter =
+       &user_shader_conv;
+
+
+static const struct vmw_res_func vmw_gb_shader_func = {
+       .res_type = vmw_res_shader,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed shaders",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_shader_create,
+       .destroy = vmw_gb_shader_destroy,
+       .bind = vmw_gb_shader_bind,
+       .unbind = vmw_gb_shader_unbind
+};
+
+/**
+ * Shader management:
+ */
+
+static inline struct vmw_shader *
+vmw_res_to_shader(struct vmw_resource *res)
+{
+       return container_of(res, struct vmw_shader, res);
+}
+
+static void vmw_hw_shader_destroy(struct vmw_resource *res)
+{
+       (void) vmw_gb_shader_destroy(res);
+}
+
+static int vmw_gb_shader_init(struct vmw_private *dev_priv,
+                             struct vmw_resource *res,
+                             uint32_t size,
+                             uint64_t offset,
+                             SVGA3dShaderType type,
+                             struct vmw_dma_buffer *byte_code,
+                             void (*res_free) (struct vmw_resource *res))
+{
+       struct vmw_shader *shader = vmw_res_to_shader(res);
+       int ret;
+
+       ret = vmw_resource_init(dev_priv, res, true,
+                               res_free, &vmw_gb_shader_func);
+
+
+       if (unlikely(ret != 0)) {
+               if (res_free)
+                       res_free(res);
+               else
+                       kfree(res);
+               return ret;
+       }
+
+       res->backup_size = size;
+       if (byte_code) {
+               res->backup = vmw_dmabuf_reference(byte_code);
+               res->backup_offset = offset;
+       }
+       shader->size = size;
+       shader->type = type;
+
+       vmw_resource_activate(res, vmw_hw_shader_destroy);
+       return 0;
+}
+
+static int vmw_gb_shader_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct vmw_shader *shader = vmw_res_to_shader(res);
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBShader body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a shader id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.type = shader->type;
+       cmd->body.sizeInBytes = shader->size;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       return ret;
+}
+
+static int vmw_gb_shader_bind(struct vmw_resource *res,
+                             struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.offsetInBytes = 0;
+       res->backup_dirty = false;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+static int vmw_gb_shader_unbind(struct vmw_resource *res,
+                               bool readback,
+                               struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+       struct vmw_fence_obj *fence;
+
+       BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.mobid = SVGA3D_INVALID_ID;
+       cmd->body.offsetInBytes = 0;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(val_buf->bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_shader_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBShader body;
+       } *cmd;
+
+       if (likely(res->id == -1))
+               return 0;
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_res_list_kill(&res->binding_head);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "destruction.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       mutex_unlock(&dev_priv->binding_mutex);
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
+/**
+ * User-space shader management:
+ */
+
+static struct vmw_resource *
+vmw_user_shader_base_to_res(struct ttm_base_object *base)
+{
+       return &(container_of(base, struct vmw_user_shader, base)->
+                shader.res);
+}
+
+static void vmw_user_shader_free(struct vmw_resource *res)
+{
+       struct vmw_user_shader *ushader =
+               container_of(res, struct vmw_user_shader, shader.res);
+       struct vmw_private *dev_priv = res->dev_priv;
+
+       ttm_base_object_kfree(ushader, base);
+       ttm_mem_global_free(vmw_mem_glob(dev_priv),
+                           vmw_user_shader_size);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
+{
+       struct ttm_base_object *base = *p_base;
+       struct vmw_resource *res = vmw_user_shader_base_to_res(base);
+
+       *p_base = NULL;
+       vmw_resource_unreference(&res);
+}
+
+int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+
+       return ttm_ref_object_base_unref(tfile, arg->handle,
+                                        TTM_REF_USAGE);
+}
+
+int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_user_shader *ushader;
+       struct vmw_resource *res;
+       struct vmw_resource *tmp;
+       struct drm_vmw_shader_create_arg *arg =
+               (struct drm_vmw_shader_create_arg *)data;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       struct vmw_dma_buffer *buffer = NULL;
+       SVGA3dShaderType shader_type;
+       int ret;
+
+       if (arg->buffer_handle != SVGA3D_INVALID_ID) {
+               ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle,
+                                            &buffer);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Could not find buffer for shader "
+                                 "creation.\n");
+                       return ret;
+               }
+
+               if ((u64)buffer->base.num_pages * PAGE_SIZE <
+                   (u64)arg->size + (u64)arg->offset) {
+                       DRM_ERROR("Illegal buffer- or shader size.\n");
+                       ret = -EINVAL;
+                       goto out_bad_arg;
+               }
+       }
+
+       switch (arg->shader_type) {
+       case drm_vmw_shader_type_vs:
+               shader_type = SVGA3D_SHADERTYPE_VS;
+               break;
+       case drm_vmw_shader_type_ps:
+               shader_type = SVGA3D_SHADERTYPE_PS;
+               break;
+       case drm_vmw_shader_type_gs:
+               shader_type = SVGA3D_SHADERTYPE_GS;
+               break;
+       default:
+               DRM_ERROR("Illegal shader type.\n");
+               ret = -EINVAL;
+               goto out_bad_arg;
+       }
+
+       /*
+        * Approximate idr memory usage with 128 bytes. It will be limited
+        * by maximum number_of shaders anyway.
+        */
+
+       if (unlikely(vmw_user_shader_size == 0))
+               vmw_user_shader_size = ttm_round_pot(sizeof(*ushader))
+                       + 128;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+                                  vmw_user_shader_size,
+                                  false, true);
+       if (unlikely(ret != 0)) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("Out of graphics memory for shader"
+                                 " creation.\n");
+               goto out_unlock;
+       }
+
+       ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
+       if (unlikely(ushader == NULL)) {
+               ttm_mem_global_free(vmw_mem_glob(dev_priv),
+                                   vmw_user_shader_size);
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
+
+       res = &ushader->shader.res;
+       ushader->base.shareable = false;
+       ushader->base.tfile = NULL;
+
+       /*
+        * From here on, the destructor takes over resource freeing.
+        */
+
+       ret = vmw_gb_shader_init(dev_priv, res, arg->size,
+                                arg->offset, shader_type, buffer,
+                                vmw_user_shader_free);
+       if (unlikely(ret != 0))
+               goto out_unlock;
+
+       tmp = vmw_resource_reference(res);
+       ret = ttm_base_object_init(tfile, &ushader->base, false,
+                                  VMW_RES_SHADER,
+                                  &vmw_user_shader_base_release, NULL);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&tmp);
+               goto out_err;
+       }
+
+       arg->shader_handle = ushader->base.hash.key;
+out_err:
+       vmw_resource_unreference(&res);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+out_bad_arg:
+       vmw_dmabuf_unreference(&buffer);
+
+       return ret;
+
+}
index 7de2ea8bd55357561913384bfa23196fe3479ec2..979da1c246a543a445257daee03787e794b266a1 100644 (file)
@@ -41,7 +41,6 @@ struct vmw_user_surface {
        struct ttm_prime_object prime;
        struct vmw_surface srf;
        uint32_t size;
-       uint32_t backup_handle;
 };
 
 /**
@@ -68,6 +67,14 @@ static int vmw_legacy_srf_unbind(struct vmw_resource *res,
                                 struct ttm_validate_buffer *val_buf);
 static int vmw_legacy_srf_create(struct vmw_resource *res);
 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
+static int vmw_gb_surface_create(struct vmw_resource *res);
+static int vmw_gb_surface_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_surface_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_surface_destroy(struct vmw_resource *res);
+
 
 static const struct vmw_user_resource_conv user_surface_conv = {
        .object_type = VMW_RES_SURFACE,
@@ -93,6 +100,18 @@ static const struct vmw_res_func vmw_legacy_surface_func = {
        .unbind = &vmw_legacy_srf_unbind
 };
 
+static const struct vmw_res_func vmw_gb_surface_func = {
+       .res_type = vmw_res_surface,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed surfaces",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_surface_create,
+       .destroy = vmw_gb_surface_destroy,
+       .bind = vmw_gb_surface_bind,
+       .unbind = vmw_gb_surface_unbind
+};
+
 /**
  * struct vmw_surface_dma - SVGA3D DMA command
  */
@@ -291,6 +310,11 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
        struct vmw_surface *srf;
        void *cmd;
 
+       if (res->func->destroy == vmw_gb_surface_destroy) {
+               (void) vmw_gb_surface_destroy(res);
+               return;
+       }
+
        if (res->id != -1) {
 
                cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
@@ -549,12 +573,15 @@ static int vmw_surface_init(struct vmw_private *dev_priv,
        struct vmw_resource *res = &srf->res;
 
        BUG_ON(res_free == NULL);
-       (void) vmw_3d_resource_inc(dev_priv, false);
+       if (!dev_priv->has_mob)
+               (void) vmw_3d_resource_inc(dev_priv, false);
        ret = vmw_resource_init(dev_priv, res, true, res_free,
+                               (dev_priv->has_mob) ? &vmw_gb_surface_func :
                                &vmw_legacy_surface_func);
 
        if (unlikely(ret != 0)) {
-               vmw_3d_resource_dec(dev_priv, false);
+               if (!dev_priv->has_mob)
+                       vmw_3d_resource_dec(dev_priv, false);
                res_free(res);
                return ret;
        }
@@ -750,7 +777,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 
        srf->base_size = *srf->sizes;
        srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
-       srf->multisample_count = 1;
+       srf->multisample_count = 0;
 
        cur_bo_offset = 0;
        cur_offset = srf->offsets;
@@ -843,6 +870,7 @@ out_unlock:
 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv)
 {
+       struct vmw_private *dev_priv = vmw_priv(dev);
        union drm_vmw_surface_reference_arg *arg =
            (union drm_vmw_surface_reference_arg *)data;
        struct drm_vmw_surface_arg *req = &arg->req;
@@ -854,7 +882,7 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
        struct ttm_base_object *base;
        int ret = -EINVAL;
 
-       base = ttm_base_object_lookup(tfile, req->sid);
+       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
        if (unlikely(base == NULL)) {
                DRM_ERROR("Could not find surface to reference.\n");
                return -EINVAL;
@@ -893,3 +921,436 @@ out_no_reference:
 
        return ret;
 }
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static int vmw_gb_surface_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct vmw_surface *srf = vmw_res_to_srf(res);
+       uint32_t cmd_len, submit_len;
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBSurface body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       (void) vmw_3d_resource_inc(dev_priv, false);
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a surface id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd_len = sizeof(cmd->body);
+       submit_len = sizeof(*cmd);
+       cmd = vmw_fifo_reserve(dev_priv, submit_len);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
+       cmd->header.size = cmd_len;
+       cmd->body.sid = srf->res.id;
+       cmd->body.surfaceFlags = srf->flags;
+       cmd->body.format = cpu_to_le32(srf->format);
+       cmd->body.numMipLevels = srf->mip_levels[0];
+       cmd->body.multisampleCount = srf->multisample_count;
+       cmd->body.autogenFilter = srf->autogen_filter;
+       cmd->body.size.width = srf->base_size.width;
+       cmd->body.size.height = srf->base_size.height;
+       cmd->body.size.depth = srf->base_size.depth;
+       vmw_fifo_commit(dev_priv, submit_len);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       vmw_3d_resource_dec(dev_priv, false);
+       return ret;
+}
+
+
+static int vmw_gb_surface_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBSurface body;
+       } *cmd2;
+       uint32_t submit_size;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
+
+       cmd1 = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd1 == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
+       cmd1->header.size = sizeof(cmd1->body);
+       cmd1->body.sid = res->id;
+       cmd1->body.mobid = bo->mem.start;
+       if (res->backup_dirty) {
+               cmd2 = (void *) &cmd1[1];
+               cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
+               cmd2->header.size = sizeof(cmd2->body);
+               cmd2->body.sid = res->id;
+               res->backup_dirty = false;
+       }
+       vmw_fifo_commit(dev_priv, submit_size);
+
+       return 0;
+}
+
+static int vmw_gb_surface_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct ttm_buffer_object *bo = val_buf->bo;
+       struct vmw_fence_obj *fence;
+
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBSurface body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBSurface body;
+       } *cmd2;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd3;
+       uint32_t submit_size;
+       uint8_t *cmd;
+
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
+       cmd = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       if (readback) {
+               cmd1 = (void *) cmd;
+               cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
+               cmd1->header.size = sizeof(cmd1->body);
+               cmd1->body.sid = res->id;
+               cmd3 = (void *) &cmd1[1];
+       } else {
+               cmd2 = (void *) cmd;
+               cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
+               cmd2->header.size = sizeof(cmd2->body);
+               cmd2->body.sid = res->id;
+               cmd3 = (void *) &cmd2[1];
+       }
+
+       cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
+       cmd3->header.size = sizeof(cmd3->body);
+       cmd3->body.sid = res->id;
+       cmd3->body.mobid = SVGA3D_INVALID_ID;
+
+       vmw_fifo_commit(dev_priv, submit_size);
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(val_buf->bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_surface_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBSurface body;
+       } *cmd;
+
+       if (likely(res->id == -1))
+               return 0;
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_res_list_kill(&res->binding_head);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "destruction.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.sid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       mutex_unlock(&dev_priv->binding_mutex);
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
+/**
+ * vmw_gb_surface_define_ioctl - Ioctl function implementing
+ *                               the user surface define functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_user_surface *user_srf;
+       struct vmw_surface *srf;
+       struct vmw_resource *res;
+       struct vmw_resource *tmp;
+       union drm_vmw_gb_surface_create_arg *arg =
+           (union drm_vmw_gb_surface_create_arg *)data;
+       struct drm_vmw_gb_surface_create_req *req = &arg->req;
+       struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret;
+       uint32_t size;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       const struct svga3d_surface_desc *desc;
+       uint32_t backup_handle;
+
+       if (unlikely(vmw_user_surface_size == 0))
+               vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+                       128;
+
+       size = vmw_user_surface_size + 128;
+
+       desc = svga3dsurface_get_desc(req->format);
+       if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
+               DRM_ERROR("Invalid surface format for surface creation.\n");
+               return -EINVAL;
+       }
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+                                  size, false, true);
+       if (unlikely(ret != 0)) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("Out of graphics memory for surface"
+                                 " creation.\n");
+               goto out_unlock;
+       }
+
+       user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
+       if (unlikely(user_srf == NULL)) {
+               ret = -ENOMEM;
+               goto out_no_user_srf;
+       }
+
+       srf = &user_srf->srf;
+       res = &srf->res;
+
+       srf->flags = req->svga3d_flags;
+       srf->format = req->format;
+       srf->scanout = req->drm_surface_flags & drm_vmw_surface_flag_scanout;
+       srf->mip_levels[0] = req->mip_levels;
+       srf->num_sizes = 1;
+       srf->sizes = NULL;
+       srf->offsets = NULL;
+       user_srf->size = size;
+       srf->base_size = req->base_size;
+       srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
+       srf->multisample_count = req->multisample_count;
+       res->backup_size = svga3dsurface_get_serialized_size
+         (srf->format, srf->base_size, srf->mip_levels[0],
+          srf->flags & SVGA3D_SURFACE_CUBEMAP);
+
+       user_srf->prime.base.shareable = false;
+       user_srf->prime.base.tfile = NULL;
+
+       /**
+        * From this point, the generic resource management functions
+        * destroy the object on failure.
+        */
+
+       ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
+       if (unlikely(ret != 0))
+               goto out_unlock;
+
+       if (req->buffer_handle != SVGA3D_INVALID_ID) {
+               ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
+                                            &res->backup);
+       } else if (req->drm_surface_flags &
+                  drm_vmw_surface_flag_create_buffer)
+               ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
+                                           res->backup_size,
+                                           req->drm_surface_flags &
+                                           drm_vmw_surface_flag_shareable,
+                                           &backup_handle,
+                                           &res->backup);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&res);
+               goto out_unlock;
+       }
+
+       tmp = vmw_resource_reference(&srf->res);
+       ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
+                                   req->drm_surface_flags &
+                                   drm_vmw_surface_flag_shareable,
+                                   VMW_RES_SURFACE,
+                                   &vmw_user_surface_base_release, NULL);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&tmp);
+               vmw_resource_unreference(&res);
+               goto out_unlock;
+       }
+
+       rep->handle = user_srf->prime.base.hash.key;
+       rep->backup_size = res->backup_size;
+       if (res->backup) {
+               rep->buffer_map_handle =
+                       drm_vma_node_offset_addr(&res->backup->base.vma_node);
+               rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
+               rep->buffer_handle = backup_handle;
+       } else {
+               rep->buffer_map_handle = 0;
+               rep->buffer_size = 0;
+               rep->buffer_handle = SVGA3D_INVALID_ID;
+       }
+
+       vmw_resource_unreference(&res);
+
+       ttm_read_unlock(&vmaster->lock);
+       return 0;
+out_no_user_srf:
+       ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
+
+/**
+ * vmw_gb_surface_reference_ioctl - Ioctl function implementing
+ *                                  the user surface reference functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       union drm_vmw_gb_surface_reference_arg *arg =
+           (union drm_vmw_gb_surface_reference_arg *)data;
+       struct drm_vmw_surface_arg *req = &arg->req;
+       struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_surface *srf;
+       struct vmw_user_surface *user_srf;
+       struct ttm_base_object *base;
+       uint32_t backup_handle;
+       int ret = -EINVAL;
+
+       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
+       if (unlikely(base == NULL)) {
+               DRM_ERROR("Could not find surface to reference.\n");
+               return -EINVAL;
+       }
+
+       if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
+               goto out_bad_resource;
+
+       user_srf = container_of(base, struct vmw_user_surface, prime.base);
+       srf = &user_srf->srf;
+       if (srf->res.backup == NULL) {
+               DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
+               goto out_bad_resource;
+       }
+
+       ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
+                                TTM_REF_USAGE, NULL);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not add a reference to a GB surface.\n");
+               goto out_bad_resource;
+       }
+
+       mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
+       ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
+                                       &backup_handle);
+       mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not add a reference to a GB surface "
+                         "backup buffer.\n");
+               (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+                                                req->sid,
+                                                TTM_REF_USAGE);
+               goto out_bad_resource;
+       }
+
+       rep->creq.svga3d_flags = srf->flags;
+       rep->creq.format = srf->format;
+       rep->creq.mip_levels = srf->mip_levels[0];
+       rep->creq.drm_surface_flags = 0;
+       rep->creq.multisample_count = srf->multisample_count;
+       rep->creq.autogen_filter = srf->autogen_filter;
+       rep->creq.buffer_handle = backup_handle;
+       rep->creq.base_size = srf->base_size;
+       rep->crep.handle = user_srf->prime.base.hash.key;
+       rep->crep.backup_size = srf->res.backup_size;
+       rep->crep.buffer_handle = backup_handle;
+       rep->crep.buffer_map_handle =
+               drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
+       rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
+
+out_bad_resource:
+       ttm_base_object_unref(&base);
+
+       return ret;
+}
index 7d6bed2225422fa2413130a606d2b20fd084cfd4..b2fd029d67b308ce60490d61cd908d743a9e520b 100644 (file)
@@ -1,6 +1,6 @@
 config TEGRA_HOST1X
        tristate "NVIDIA Tegra host1x driver"
-       depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
+       depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
        help
          Driver for the NVIDIA Tegra host1x hardware.
 
index afa1e9e4e51265fbdb21698072315786a6b730b7..c1189f0044411810fb2e0e58203421d6ffa302d7 100644 (file)
@@ -7,7 +7,9 @@ host1x-y = \
        channel.o \
        job.o \
        debug.o \
+       mipi.o \
        hw/host1x01.o \
-       hw/host1x02.o
+       hw/host1x02.o \
+       hw/host1x04.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
index 6a929591aa73801df1126433bc514980e80d1465..ccdd2e6da5e3710a205e1b5dc3a9c667a9ed6bcf 100644 (file)
@@ -188,6 +188,7 @@ int host1x_device_init(struct host1x_device *device)
 
        return 0;
 }
+EXPORT_SYMBOL(host1x_device_init);
 
 int host1x_device_exit(struct host1x_device *device)
 {
@@ -213,6 +214,7 @@ int host1x_device_exit(struct host1x_device *device)
 
        return 0;
 }
+EXPORT_SYMBOL(host1x_device_exit);
 
 static int host1x_register_client(struct host1x *host1x,
                                  struct host1x_client *client)
index 83ea51b9f0fce44ea6a5ff96f78c8db49f6b8839..b4ae3affb987bb92ed7dcd1f3317714b260fd61d 100644 (file)
@@ -43,6 +43,7 @@ int host1x_job_submit(struct host1x_job *job)
 
        return host1x_hw_channel_submit(host, job);
 }
+EXPORT_SYMBOL(host1x_job_submit);
 
 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
 {
@@ -60,6 +61,7 @@ struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
 
        return err ? NULL : channel;
 }
+EXPORT_SYMBOL(host1x_channel_get);
 
 void host1x_channel_put(struct host1x_channel *channel)
 {
@@ -76,6 +78,7 @@ void host1x_channel_put(struct host1x_channel *channel)
 
        mutex_unlock(&channel->reflock);
 }
+EXPORT_SYMBOL(host1x_channel_put);
 
 struct host1x_channel *host1x_channel_request(struct device *dev)
 {
@@ -115,6 +118,7 @@ fail:
        mutex_unlock(&host->chlist_mutex);
        return NULL;
 }
+EXPORT_SYMBOL(host1x_channel_request);
 
 void host1x_channel_free(struct host1x_channel *channel)
 {
@@ -124,3 +128,4 @@ void host1x_channel_free(struct host1x_channel *channel)
        list_del(&channel->list);
        kfree(channel);
 }
+EXPORT_SYMBOL(host1x_channel_free);
index 3ec7d77de24ddc846321f159229e3d592bf02a38..ee3d12b51c50a036b89c48c3e60576a2a14acf5b 100644 (file)
@@ -96,7 +96,6 @@ static void show_all(struct host1x *m, struct output *o)
                show_channels(ch, o, true);
 }
 
-#ifdef CONFIG_DEBUG_FS
 static void show_all_no_fifo(struct host1x *host1x, struct output *o)
 {
        struct host1x_channel *ch;
@@ -153,7 +152,7 @@ static const struct file_operations host1x_debug_fops = {
        .release        = single_release,
 };
 
-void host1x_debug_init(struct host1x *host1x)
+static void host1x_debugfs_init(struct host1x *host1x)
 {
        struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
 
@@ -180,18 +179,22 @@ void host1x_debug_init(struct host1x *host1x)
                           &host1x_debug_force_timeout_channel);
 }
 
-void host1x_debug_deinit(struct host1x *host1x)
+static void host1x_debugfs_exit(struct host1x *host1x)
 {
        debugfs_remove_recursive(host1x->debugfs);
 }
-#else
+
 void host1x_debug_init(struct host1x *host1x)
 {
+       if (IS_ENABLED(CONFIG_DEBUG_FS))
+               host1x_debugfs_init(host1x);
 }
+
 void host1x_debug_deinit(struct host1x *host1x)
 {
+       if (IS_ENABLED(CONFIG_DEBUG_FS))
+               host1x_debugfs_exit(host1x);
 }
-#endif
 
 void host1x_debug_dump(struct host1x *host1x)
 {
index 80da003d63de8d4b754cd37a607441c7c4901574..2529908d304bd851fdd9c2d0b9d71471e5d69b20 100644 (file)
@@ -34,6 +34,7 @@
 #include "debug.h"
 #include "hw/host1x01.h"
 #include "hw/host1x02.h"
+#include "hw/host1x04.h"
 
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
@@ -77,7 +78,17 @@ static const struct host1x_info host1x02_info = {
        .sync_offset = 0x3000,
 };
 
+static const struct host1x_info host1x04_info = {
+       .nb_channels = 12,
+       .nb_pts = 192,
+       .nb_mlocks = 16,
+       .nb_bases = 64,
+       .init = host1x04_init,
+       .sync_offset = 0x2100,
+};
+
 static struct of_device_id host1x_of_match[] = {
+       { .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
        { .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
        { .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
        { .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
@@ -210,17 +221,26 @@ static int __init tegra_host1x_init(void)
                return err;
 
        err = platform_driver_register(&tegra_host1x_driver);
-       if (err < 0) {
-               host1x_bus_exit();
-               return err;
-       }
+       if (err < 0)
+               goto unregister_bus;
+
+       err = platform_driver_register(&tegra_mipi_driver);
+       if (err < 0)
+               goto unregister_host1x;
 
        return 0;
+
+unregister_host1x:
+       platform_driver_unregister(&tegra_host1x_driver);
+unregister_bus:
+       host1x_bus_exit();
+       return err;
 }
 module_init(tegra_host1x_init);
 
 static void __exit tegra_host1x_exit(void)
 {
+       platform_driver_unregister(&tegra_mipi_driver);
        platform_driver_unregister(&tegra_host1x_driver);
        host1x_bus_exit();
 }
index a61a976e7a421a405d7fe075272228f08e3e3e6d..0b6e8e9629c5330fbc7fadba1a1ae318ae07da12 100644 (file)
@@ -306,4 +306,6 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
        host->debug_op->show_mlocks(host, o);
 }
 
+extern struct platform_driver tegra_mipi_driver;
+
 #endif
index e98caca0ca42a55b120e1a29085c9d02fc49c046..928946c2144bd17eaa814e1ab9f5449cf17264d8 100644 (file)
@@ -17,8 +17,8 @@
  */
 
 /* include hw specification */
-#include "host1x01.h"
-#include "host1x01_hardware.h"
+#include "host1x02.h"
+#include "host1x02_hardware.h"
 
 /* include code */
 #include "cdma_hw.c"
diff --git a/drivers/gpu/host1x/hw/host1x02_hardware.h b/drivers/gpu/host1x/hw/host1x02_hardware.h
new file mode 100644 (file)
index 0000000..1549018
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Tegra host1x Register Offsets for Tegra114
+ *
+ * Copyright (c) 2010-2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST1X_HOST1X02_HARDWARE_H
+#define __HOST1X_HOST1X02_HARDWARE_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include "hw_host1x02_channel.h"
+#include "hw_host1x02_sync.h"
+#include "hw_host1x02_uclass.h"
+
+static inline u32 host1x_class_host_wait_syncpt(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_wait_syncpt_indx_f(indx)
+               | host1x_uclass_wait_syncpt_thresh_f(threshold);
+}
+
+static inline u32 host1x_class_host_load_syncpt_base(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_load_syncpt_base_base_indx_f(indx)
+               | host1x_uclass_load_syncpt_base_value_f(threshold);
+}
+
+static inline u32 host1x_class_host_wait_syncpt_base(
+       unsigned indx, unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_wait_syncpt_base_indx_f(indx)
+               | host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_wait_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt_base(
+       unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_incr_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt(
+       unsigned cond, unsigned indx)
+{
+       return host1x_uclass_incr_syncpt_cond_f(cond)
+               | host1x_uclass_incr_syncpt_indx_f(indx);
+}
+
+static inline u32 host1x_class_host_indoff_reg_write(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indbe_f(0xf)
+               | host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset);
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+static inline u32 host1x_class_host_indoff_reg_read(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset)
+               | host1x_uclass_indoff_rwn_read_v();
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+/* cdma opcodes */
+static inline u32 host1x_opcode_setclass(
+       unsigned class_id, unsigned offset, unsigned mask)
+{
+       return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
+}
+
+static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
+{
+       return (1 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
+{
+       return (2 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
+{
+       return (3 << 28) | (offset << 16) | mask;
+}
+
+static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
+{
+       return (4 << 28) | (offset << 16) | value;
+}
+
+static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
+{
+       return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
+               host1x_class_host_incr_syncpt(cond, indx));
+}
+
+static inline u32 host1x_opcode_restart(unsigned address)
+{
+       return (5 << 28) | (address >> 4);
+}
+
+static inline u32 host1x_opcode_gather(unsigned count)
+{
+       return (6 << 28) | count;
+}
+
+static inline u32 host1x_opcode_gather_nonincr(unsigned offset,        unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | count;
+}
+
+static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
+}
+
+#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
+
+#endif
diff --git a/drivers/gpu/host1x/hw/host1x04.c b/drivers/gpu/host1x/hw/host1x04.c
new file mode 100644 (file)
index 0000000..8007c70
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Host1x init for Tegra124 SoCs
+ *
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* include hw specification */
+#include "host1x04.h"
+#include "host1x04_hardware.h"
+
+/* include code */
+#include "cdma_hw.c"
+#include "channel_hw.c"
+#include "debug_hw.c"
+#include "intr_hw.c"
+#include "syncpt_hw.c"
+
+#include "../dev.h"
+
+int host1x04_init(struct host1x *host)
+{
+       host->channel_op = &host1x_channel_ops;
+       host->cdma_op = &host1x_cdma_ops;
+       host->cdma_pb_op = &host1x_pushbuffer_ops;
+       host->syncpt_op = &host1x_syncpt_ops;
+       host->intr_op = &host1x_intr_ops;
+       host->debug_op = &host1x_debug_ops;
+
+       return 0;
+}
diff --git a/drivers/gpu/host1x/hw/host1x04.h b/drivers/gpu/host1x/hw/host1x04.h
new file mode 100644 (file)
index 0000000..a9ab749
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Host1x init for Tegra124 SoCs
+ *
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HOST1X_HOST1X04_H
+#define HOST1X_HOST1X04_H
+
+struct host1x;
+
+int host1x04_init(struct host1x *host);
+
+#endif
diff --git a/drivers/gpu/host1x/hw/host1x04_hardware.h b/drivers/gpu/host1x/hw/host1x04_hardware.h
new file mode 100644 (file)
index 0000000..de1a381
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Tegra host1x Register Offsets for Tegra124
+ *
+ * Copyright (c) 2010-2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST1X_HOST1X04_HARDWARE_H
+#define __HOST1X_HOST1X04_HARDWARE_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include "hw_host1x04_channel.h"
+#include "hw_host1x04_sync.h"
+#include "hw_host1x04_uclass.h"
+
+static inline u32 host1x_class_host_wait_syncpt(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_wait_syncpt_indx_f(indx)
+               | host1x_uclass_wait_syncpt_thresh_f(threshold);
+}
+
+static inline u32 host1x_class_host_load_syncpt_base(
+       unsigned indx, unsigned threshold)
+{
+       return host1x_uclass_load_syncpt_base_base_indx_f(indx)
+               | host1x_uclass_load_syncpt_base_value_f(threshold);
+}
+
+static inline u32 host1x_class_host_wait_syncpt_base(
+       unsigned indx, unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_wait_syncpt_base_indx_f(indx)
+               | host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_wait_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt_base(
+       unsigned base_indx, unsigned offset)
+{
+       return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
+               | host1x_uclass_incr_syncpt_base_offset_f(offset);
+}
+
+static inline u32 host1x_class_host_incr_syncpt(
+       unsigned cond, unsigned indx)
+{
+       return host1x_uclass_incr_syncpt_cond_f(cond)
+               | host1x_uclass_incr_syncpt_indx_f(indx);
+}
+
+static inline u32 host1x_class_host_indoff_reg_write(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indbe_f(0xf)
+               | host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset);
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+static inline u32 host1x_class_host_indoff_reg_read(
+       unsigned mod_id, unsigned offset, bool auto_inc)
+{
+       u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
+               | host1x_uclass_indoff_indroffset_f(offset)
+               | host1x_uclass_indoff_rwn_read_v();
+       if (auto_inc)
+               v |= host1x_uclass_indoff_autoinc_f(1);
+       return v;
+}
+
+/* cdma opcodes */
+static inline u32 host1x_opcode_setclass(
+       unsigned class_id, unsigned offset, unsigned mask)
+{
+       return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
+}
+
+static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
+{
+       return (1 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
+{
+       return (2 << 28) | (offset << 16) | count;
+}
+
+static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
+{
+       return (3 << 28) | (offset << 16) | mask;
+}
+
+static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
+{
+       return (4 << 28) | (offset << 16) | value;
+}
+
+static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
+{
+       return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
+               host1x_class_host_incr_syncpt(cond, indx));
+}
+
+static inline u32 host1x_opcode_restart(unsigned address)
+{
+       return (5 << 28) | (address >> 4);
+}
+
+static inline u32 host1x_opcode_gather(unsigned count)
+{
+       return (6 << 28) | count;
+}
+
+static inline u32 host1x_opcode_gather_nonincr(unsigned offset,        unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | count;
+}
+
+static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
+{
+       return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
+}
+
+#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
+
+#endif
index a3b3c9874413c1b420632b74df3137da31eaf73c..028e49d9bac9837132f3ccbcb10067a8514dea58 100644 (file)
@@ -111,6 +111,12 @@ static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
 }
 #define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
        host1x_uclass_wait_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_r(void)
+{
+       return 0xb;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
+       host1x_uclass_load_syncpt_base_r()
 static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
 {
        return (v & 0xff) << 24;
diff --git a/drivers/gpu/host1x/hw/hw_host1x04_channel.h b/drivers/gpu/host1x/hw/hw_host1x04_channel.h
new file mode 100644 (file)
index 0000000..95e6f96
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X04_CHANNEL_H
+#define HOST1X_HW_HOST1X04_CHANNEL_H
+
+static inline u32 host1x_channel_fifostat_r(void)
+{
+       return 0x0;
+}
+#define HOST1X_CHANNEL_FIFOSTAT \
+       host1x_channel_fifostat_r()
+static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
+{
+       return (r >> 11) & 0x1;
+}
+#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
+       host1x_channel_fifostat_cfempty_v(r)
+static inline u32 host1x_channel_dmastart_r(void)
+{
+       return 0x14;
+}
+#define HOST1X_CHANNEL_DMASTART \
+       host1x_channel_dmastart_r()
+static inline u32 host1x_channel_dmaput_r(void)
+{
+       return 0x18;
+}
+#define HOST1X_CHANNEL_DMAPUT \
+       host1x_channel_dmaput_r()
+static inline u32 host1x_channel_dmaget_r(void)
+{
+       return 0x1c;
+}
+#define HOST1X_CHANNEL_DMAGET \
+       host1x_channel_dmaget_r()
+static inline u32 host1x_channel_dmaend_r(void)
+{
+       return 0x20;
+}
+#define HOST1X_CHANNEL_DMAEND \
+       host1x_channel_dmaend_r()
+static inline u32 host1x_channel_dmactrl_r(void)
+{
+       return 0x24;
+}
+#define HOST1X_CHANNEL_DMACTRL \
+       host1x_channel_dmactrl_r()
+static inline u32 host1x_channel_dmactrl_dmastop(void)
+{
+       return 1 << 0;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
+       host1x_channel_dmactrl_dmastop()
+static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
+{
+       return (r >> 0) & 0x1;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
+       host1x_channel_dmactrl_dmastop_v(r)
+static inline u32 host1x_channel_dmactrl_dmagetrst(void)
+{
+       return 1 << 1;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
+       host1x_channel_dmactrl_dmagetrst()
+static inline u32 host1x_channel_dmactrl_dmainitget(void)
+{
+       return 1 << 2;
+}
+#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
+       host1x_channel_dmactrl_dmainitget()
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x04_sync.h b/drivers/gpu/host1x/hw/hw_host1x04_sync.h
new file mode 100644 (file)
index 0000000..ef2275b
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X04_SYNC_H
+#define HOST1X_HW_HOST1X04_SYNC_H
+
+#define REGISTER_STRIDE        4
+
+static inline u32 host1x_sync_syncpt_r(unsigned int id)
+{
+       return 0xf80 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT(id) \
+       host1x_sync_syncpt_r(id)
+static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_r(unsigned int id)
+{
+       return 0xe80 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id) \
+       host1x_sync_syncpt_thresh_cpu0_int_status_r(id)
+static inline u32 host1x_sync_syncpt_thresh_int_disable_r(unsigned int id)
+{
+       return 0xf00 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id) \
+       host1x_sync_syncpt_thresh_int_disable_r(id)
+static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_r(unsigned int id)
+{
+       return 0xf20 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id) \
+       host1x_sync_syncpt_thresh_int_enable_cpu0_r(id)
+static inline u32 host1x_sync_cf_setup_r(unsigned int channel)
+{
+       return 0xc00 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CF_SETUP(channel) \
+       host1x_sync_cf_setup_r(channel)
+static inline u32 host1x_sync_cf_setup_base_v(u32 r)
+{
+       return (r >> 0) & 0x3ff;
+}
+#define HOST1X_SYNC_CF_SETUP_BASE_V(r) \
+       host1x_sync_cf_setup_base_v(r)
+static inline u32 host1x_sync_cf_setup_limit_v(u32 r)
+{
+       return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CF_SETUP_LIMIT_V(r) \
+       host1x_sync_cf_setup_limit_v(r)
+static inline u32 host1x_sync_cmdproc_stop_r(void)
+{
+       return 0xac;
+}
+#define HOST1X_SYNC_CMDPROC_STOP \
+       host1x_sync_cmdproc_stop_r()
+static inline u32 host1x_sync_ch_teardown_r(void)
+{
+       return 0xb0;
+}
+#define HOST1X_SYNC_CH_TEARDOWN \
+       host1x_sync_ch_teardown_r()
+static inline u32 host1x_sync_usec_clk_r(void)
+{
+       return 0x1a4;
+}
+#define HOST1X_SYNC_USEC_CLK \
+       host1x_sync_usec_clk_r()
+static inline u32 host1x_sync_ctxsw_timeout_cfg_r(void)
+{
+       return 0x1a8;
+}
+#define HOST1X_SYNC_CTXSW_TIMEOUT_CFG \
+       host1x_sync_ctxsw_timeout_cfg_r()
+static inline u32 host1x_sync_ip_busy_timeout_r(void)
+{
+       return 0x1bc;
+}
+#define HOST1X_SYNC_IP_BUSY_TIMEOUT \
+       host1x_sync_ip_busy_timeout_r()
+static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
+{
+       return 0x340 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_MLOCK_OWNER(id) \
+       host1x_sync_mlock_owner_r(id)
+static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
+{
+       return (v & 0xf) << 8;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
+       host1x_sync_mlock_owner_chid_f(v)
+static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
+{
+       return (r >> 1) & 0x1;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(r) \
+       host1x_sync_mlock_owner_cpu_owns_v(r)
+static inline u32 host1x_sync_mlock_owner_ch_owns_v(u32 r)
+{
+       return (r >> 0) & 0x1;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(r) \
+       host1x_sync_mlock_owner_ch_owns_v(r)
+static inline u32 host1x_sync_syncpt_int_thresh_r(unsigned int id)
+{
+       return 0x1380 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_INT_THRESH(id) \
+       host1x_sync_syncpt_int_thresh_r(id)
+static inline u32 host1x_sync_syncpt_base_r(unsigned int id)
+{
+       return 0x600 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_BASE(id) \
+       host1x_sync_syncpt_base_r(id)
+static inline u32 host1x_sync_syncpt_cpu_incr_r(unsigned int id)
+{
+       return 0xf60 + id * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_SYNCPT_CPU_INCR(id) \
+       host1x_sync_syncpt_cpu_incr_r(id)
+static inline u32 host1x_sync_cbread_r(unsigned int channel)
+{
+       return 0xc80 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CBREAD(channel) \
+       host1x_sync_cbread_r(channel)
+static inline u32 host1x_sync_cfpeek_ctrl_r(void)
+{
+       return 0x74c;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL \
+       host1x_sync_cfpeek_ctrl_r()
+static inline u32 host1x_sync_cfpeek_ctrl_addr_f(u32 v)
+{
+       return (v & 0x3ff) << 0;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(v) \
+       host1x_sync_cfpeek_ctrl_addr_f(v)
+static inline u32 host1x_sync_cfpeek_ctrl_channr_f(u32 v)
+{
+       return (v & 0xf) << 16;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(v) \
+       host1x_sync_cfpeek_ctrl_channr_f(v)
+static inline u32 host1x_sync_cfpeek_ctrl_ena_f(u32 v)
+{
+       return (v & 0x1) << 31;
+}
+#define HOST1X_SYNC_CFPEEK_CTRL_ENA_F(v) \
+       host1x_sync_cfpeek_ctrl_ena_f(v)
+static inline u32 host1x_sync_cfpeek_read_r(void)
+{
+       return 0x750;
+}
+#define HOST1X_SYNC_CFPEEK_READ \
+       host1x_sync_cfpeek_read_r()
+static inline u32 host1x_sync_cfpeek_ptrs_r(void)
+{
+       return 0x754;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS \
+       host1x_sync_cfpeek_ptrs_r()
+static inline u32 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(u32 r)
+{
+       return (r >> 0) & 0x3ff;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(r) \
+       host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(r)
+static inline u32 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(u32 r)
+{
+       return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(r) \
+       host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(r)
+static inline u32 host1x_sync_cbstat_r(unsigned int channel)
+{
+       return 0xcc0 + channel * REGISTER_STRIDE;
+}
+#define HOST1X_SYNC_CBSTAT(channel) \
+       host1x_sync_cbstat_r(channel)
+static inline u32 host1x_sync_cbstat_cboffset_v(u32 r)
+{
+       return (r >> 0) & 0xffff;
+}
+#define HOST1X_SYNC_CBSTAT_CBOFFSET_V(r) \
+       host1x_sync_cbstat_cboffset_v(r)
+static inline u32 host1x_sync_cbstat_cbclass_v(u32 r)
+{
+       return (r >> 16) & 0x3ff;
+}
+#define HOST1X_SYNC_CBSTAT_CBCLASS_V(r) \
+       host1x_sync_cbstat_cbclass_v(r)
+
+#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x04_uclass.h b/drivers/gpu/host1x/hw/hw_host1x04_uclass.h
new file mode 100644 (file)
index 0000000..d1460e9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+ /*
+  * Function naming determines intended use:
+  *
+  *     <x>_r(void) : Returns the offset for register <x>.
+  *
+  *     <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
+  *
+  *     <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
+  *
+  *     <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
+  *         and masked to place it at field <y> of register <x>.  This value
+  *         can be |'d with others to produce a full register value for
+  *         register <x>.
+  *
+  *     <x>_<y>_m(void) : Returns a mask for field <y> of register <x>.  This
+  *         value can be ~'d and then &'d to clear the value of field <y> for
+  *         register <x>.
+  *
+  *     <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
+  *         to place it at field <y> of register <x>.  This value can be |'d
+  *         with others to produce a full register value for <x>.
+  *
+  *     <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
+  *         <x> value 'r' after being shifted to place its LSB at bit 0.
+  *         This value is suitable for direct comparison with other unshifted
+  *         values appropriate for use in field <y> of register <x>.
+  *
+  *     <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
+  *         field <y> of register <x>.  This value is suitable for direct
+  *         comparison with unshifted values appropriate for use in field <y>
+  *         of register <x>.
+  */
+
+#ifndef HOST1X_HW_HOST1X04_UCLASS_H
+#define HOST1X_HW_HOST1X04_UCLASS_H
+
+static inline u32 host1x_uclass_incr_syncpt_r(void)
+{
+       return 0x0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT \
+       host1x_uclass_incr_syncpt_r()
+static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
+{
+       return (v & 0xff) << 8;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
+       host1x_uclass_incr_syncpt_cond_f(v)
+static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
+{
+       return (v & 0xff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
+       host1x_uclass_incr_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_r(void)
+{
+       return 0x8;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT \
+       host1x_uclass_wait_syncpt_r()
+static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
+       host1x_uclass_wait_syncpt_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
+       host1x_uclass_wait_syncpt_thresh_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_r(void)
+{
+       return 0x9;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
+       host1x_uclass_wait_syncpt_base_r()
+static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
+       host1x_uclass_wait_syncpt_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 16;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_wait_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
+{
+       return (v & 0xffff) << 0;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
+       host1x_uclass_wait_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_r(void)
+{
+       return 0xb;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
+       host1x_uclass_load_syncpt_base_r()
+static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_load_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
+       host1x_uclass_load_syncpt_base_value_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
+{
+       return (v & 0xff) << 24;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
+       host1x_uclass_incr_syncpt_base_base_indx_f(v)
+static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
+{
+       return (v & 0xffffff) << 0;
+}
+#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
+       host1x_uclass_incr_syncpt_base_offset_f(v)
+static inline u32 host1x_uclass_indoff_r(void)
+{
+       return 0x2d;
+}
+#define HOST1X_UCLASS_INDOFF \
+       host1x_uclass_indoff_r()
+static inline u32 host1x_uclass_indoff_indbe_f(u32 v)
+{
+       return (v & 0xf) << 28;
+}
+#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \
+       host1x_uclass_indoff_indbe_f(v)
+static inline u32 host1x_uclass_indoff_autoinc_f(u32 v)
+{
+       return (v & 0x1) << 27;
+}
+#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \
+       host1x_uclass_indoff_autoinc_f(v)
+static inline u32 host1x_uclass_indoff_indmodid_f(u32 v)
+{
+       return (v & 0xff) << 18;
+}
+#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \
+       host1x_uclass_indoff_indmodid_f(v)
+static inline u32 host1x_uclass_indoff_indroffset_f(u32 v)
+{
+       return (v & 0xffff) << 2;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+       host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_indoff_rwn_read_v(void)
+{
+       return 1;
+}
+#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
+       host1x_uclass_indoff_indroffset_f(v)
+
+#endif
index de5ec333ce1adc1974001d01bad56d2544d472d3..1146e3bba6e19bb69cd7f866c149b4aa7202ae46 100644 (file)
@@ -75,12 +75,14 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
 
        return job;
 }
+EXPORT_SYMBOL(host1x_job_alloc);
 
 struct host1x_job *host1x_job_get(struct host1x_job *job)
 {
        kref_get(&job->ref);
        return job;
 }
+EXPORT_SYMBOL(host1x_job_get);
 
 static void job_free(struct kref *ref)
 {
@@ -93,6 +95,7 @@ void host1x_job_put(struct host1x_job *job)
 {
        kref_put(&job->ref, job_free);
 }
+EXPORT_SYMBOL(host1x_job_put);
 
 void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,
                           u32 words, u32 offset)
@@ -104,6 +107,7 @@ void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,
        cur_gather->offset = offset;
        job->num_gathers++;
 }
+EXPORT_SYMBOL(host1x_job_add_gather);
 
 /*
  * NULL an already satisfied WAIT_SYNCPT host method, by patching its
@@ -560,6 +564,7 @@ out:
 
        return err;
 }
+EXPORT_SYMBOL(host1x_job_pin);
 
 void host1x_job_unpin(struct host1x_job *job)
 {
@@ -577,6 +582,7 @@ void host1x_job_unpin(struct host1x_job *job)
                                      job->gather_copy_mapped,
                                      job->gather_copy);
 }
+EXPORT_SYMBOL(host1x_job_unpin);
 
 /*
  * Debug routine used to dump job entries
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
new file mode 100644 (file)
index 0000000..9882ea1
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/host1x.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "dev.h"
+
+#define MIPI_CAL_CTRL                  0x00
+#define MIPI_CAL_CTRL_START            (1 << 0)
+
+#define MIPI_CAL_AUTOCAL_CTRL          0x01
+
+#define MIPI_CAL_STATUS                        0x02
+#define MIPI_CAL_STATUS_DONE           (1 << 16)
+#define MIPI_CAL_STATUS_ACTIVE         (1 <<  0)
+
+#define MIPI_CAL_CONFIG_CSIA           0x05
+#define MIPI_CAL_CONFIG_CSIB           0x06
+#define MIPI_CAL_CONFIG_CSIC           0x07
+#define MIPI_CAL_CONFIG_CSID           0x08
+#define MIPI_CAL_CONFIG_CSIE           0x09
+#define MIPI_CAL_CONFIG_DSIA           0x0e
+#define MIPI_CAL_CONFIG_DSIB           0x0f
+#define MIPI_CAL_CONFIG_DSIC           0x10
+#define MIPI_CAL_CONFIG_DSID           0x11
+
+#define MIPI_CAL_CONFIG_SELECT         (1 << 21)
+#define MIPI_CAL_CONFIG_HSPDOS(x)      (((x) & 0x1f) << 16)
+#define MIPI_CAL_CONFIG_HSPUOS(x)      (((x) & 0x1f) <<  8)
+#define MIPI_CAL_CONFIG_TERMOS(x)      (((x) & 0x1f) <<  0)
+
+#define MIPI_CAL_BIAS_PAD_CFG0         0x16
+#define MIPI_CAL_BIAS_PAD_PDVCLAMP     (1 << 1)
+#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0)
+
+#define MIPI_CAL_BIAS_PAD_CFG1         0x17
+
+#define MIPI_CAL_BIAS_PAD_CFG2         0x18
+#define MIPI_CAL_BIAS_PAD_PDVREG       (1 << 1)
+
+static const struct module {
+       unsigned long reg;
+} modules[] = {
+       { .reg = MIPI_CAL_CONFIG_CSIA },
+       { .reg = MIPI_CAL_CONFIG_CSIB },
+       { .reg = MIPI_CAL_CONFIG_CSIC },
+       { .reg = MIPI_CAL_CONFIG_CSID },
+       { .reg = MIPI_CAL_CONFIG_CSIE },
+       { .reg = MIPI_CAL_CONFIG_DSIA },
+       { .reg = MIPI_CAL_CONFIG_DSIB },
+       { .reg = MIPI_CAL_CONFIG_DSIC },
+       { .reg = MIPI_CAL_CONFIG_DSID },
+};
+
+struct tegra_mipi {
+       void __iomem *regs;
+       struct mutex lock;
+       struct clk *clk;
+};
+
+struct tegra_mipi_device {
+       struct platform_device *pdev;
+       struct tegra_mipi *mipi;
+       struct device *device;
+       unsigned long pads;
+};
+
+static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi,
+                                            unsigned long reg)
+{
+       return readl(mipi->regs + (reg << 2));
+}
+
+static inline void tegra_mipi_writel(struct tegra_mipi *mipi,
+                                    unsigned long value, unsigned long reg)
+{
+       writel(value, mipi->regs + (reg << 2));
+}
+
+struct tegra_mipi_device *tegra_mipi_request(struct device *device)
+{
+       struct device_node *np = device->of_node;
+       struct tegra_mipi_device *dev;
+       struct of_phandle_args args;
+       int err;
+
+       err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate",
+                                        "#nvidia,mipi-calibrate-cells", 0,
+                                        &args);
+       if (err < 0)
+               return ERR_PTR(err);
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               of_node_put(args.np);
+               err = -ENOMEM;
+               goto out;
+       }
+
+       dev->pdev = of_find_device_by_node(args.np);
+       if (!dev->pdev) {
+               of_node_put(args.np);
+               err = -ENODEV;
+               goto free;
+       }
+
+       of_node_put(args.np);
+
+       dev->mipi = platform_get_drvdata(dev->pdev);
+       if (!dev->mipi) {
+               err = -EPROBE_DEFER;
+               goto pdev_put;
+       }
+
+       dev->pads = args.args[0];
+       dev->device = device;
+
+       return dev;
+
+pdev_put:
+       platform_device_put(dev->pdev);
+free:
+       kfree(dev);
+out:
+       return ERR_PTR(err);
+}
+EXPORT_SYMBOL(tegra_mipi_request);
+
+void tegra_mipi_free(struct tegra_mipi_device *device)
+{
+       platform_device_put(device->pdev);
+       kfree(device);
+}
+EXPORT_SYMBOL(tegra_mipi_free);
+
+static int tegra_mipi_wait(struct tegra_mipi *mipi)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(250);
+       unsigned long value;
+
+       while (time_before(jiffies, timeout)) {
+               value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
+               if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
+                   (value & MIPI_CAL_STATUS_DONE) != 0)
+                       return 0;
+
+               usleep_range(10, 50);
+       }
+
+       return -ETIMEDOUT;
+}
+
+int tegra_mipi_calibrate(struct tegra_mipi_device *device)
+{
+       unsigned long value;
+       unsigned int i;
+       int err;
+
+       err = clk_enable(device->mipi->clk);
+       if (err < 0)
+               return err;
+
+       mutex_lock(&device->mipi->lock);
+
+       value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0);
+       value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
+       value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
+       tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
+
+       value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
+       value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
+       tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
+
+       for (i = 0; i < ARRAY_SIZE(modules); i++) {
+               if (device->pads & BIT(i))
+                       value = MIPI_CAL_CONFIG_SELECT |
+                               MIPI_CAL_CONFIG_HSPDOS(0) |
+                               MIPI_CAL_CONFIG_HSPUOS(4) |
+                               MIPI_CAL_CONFIG_TERMOS(5);
+               else
+                       value = 0;
+
+               tegra_mipi_writel(device->mipi, value, modules[i].reg);
+       }
+
+       tegra_mipi_writel(device->mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL);
+
+       err = tegra_mipi_wait(device->mipi);
+
+       mutex_unlock(&device->mipi->lock);
+       clk_disable(device->mipi->clk);
+
+       return err;
+}
+EXPORT_SYMBOL(tegra_mipi_calibrate);
+
+static int tegra_mipi_probe(struct platform_device *pdev)
+{
+       struct tegra_mipi *mipi;
+       struct resource *res;
+       int err;
+
+       mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
+       if (!mipi)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mipi->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mipi->regs))
+               return PTR_ERR(mipi->regs);
+
+       mutex_init(&mipi->lock);
+
+       mipi->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(mipi->clk)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               return PTR_ERR(mipi->clk);
+       }
+
+       err = clk_prepare(mipi->clk);
+       if (err < 0)
+               return err;
+
+       platform_set_drvdata(pdev, mipi);
+
+       return 0;
+}
+
+static int tegra_mipi_remove(struct platform_device *pdev)
+{
+       struct tegra_mipi *mipi = platform_get_drvdata(pdev);
+
+       clk_unprepare(mipi->clk);
+
+       return 0;
+}
+
+static struct of_device_id tegra_mipi_of_match[] = {
+       { .compatible = "nvidia,tegra114-mipi", },
+       { },
+};
+
+struct platform_driver tegra_mipi_driver = {
+       .driver = {
+               .name = "tegra-mipi",
+               .of_match_table = tegra_mipi_of_match,
+       },
+       .probe = tegra_mipi_probe,
+       .remove = tegra_mipi_remove,
+};
index 159c479829c959d0bd898742f9bcfec54e74020e..bfb09d802abdfe0c9bcba38d879477610d44bbd8 100644 (file)
@@ -93,6 +93,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp)
 {
        return sp->id;
 }
+EXPORT_SYMBOL(host1x_syncpt_id);
 
 /*
  * Updates the value sent to hardware.
@@ -168,6 +169,7 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp)
 {
        return host1x_hw_syncpt_cpu_incr(sp->host, sp);
 }
+EXPORT_SYMBOL(host1x_syncpt_incr);
 
 /*
  * Updated sync point form hardware, and returns true if syncpoint is expired,
@@ -377,6 +379,7 @@ struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
        struct host1x *host = dev_get_drvdata(dev->parent);
        return host1x_syncpt_alloc(host, dev, flags);
 }
+EXPORT_SYMBOL(host1x_syncpt_request);
 
 void host1x_syncpt_free(struct host1x_syncpt *sp)
 {
@@ -390,6 +393,7 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
        sp->name = NULL;
        sp->client_managed = false;
 }
+EXPORT_SYMBOL(host1x_syncpt_free);
 
 void host1x_syncpt_deinit(struct host1x *host)
 {
@@ -408,6 +412,7 @@ u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
        smp_rmb();
        return (u32)atomic_read(&sp->max_val);
 }
+EXPORT_SYMBOL(host1x_syncpt_read_max);
 
 /*
  * Read min, which is a shadow of the current sync point value in hardware.
@@ -417,6 +422,7 @@ u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
        smp_rmb();
        return (u32)atomic_read(&sp->min_val);
 }
+EXPORT_SYMBOL(host1x_syncpt_read_min);
 
 int host1x_syncpt_nb_pts(struct host1x *host)
 {
@@ -439,13 +445,16 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)
                return NULL;
        return host->syncpt + id;
 }
+EXPORT_SYMBOL(host1x_syncpt_get);
 
 struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
 {
        return sp ? sp->base : NULL;
 }
+EXPORT_SYMBOL(host1x_syncpt_get_base);
 
 u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
 {
        return base->id;
 }
+EXPORT_SYMBOL(host1x_syncpt_base_id);
index e661edee4d0cf0d92b7ab5e6899d1993bb264799..9704537aee3cd1921233339340c084365ed958bb 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/module.h>
-#include <linux/clk/tegra.h>
+#include <linux/reset.h>
 
 #include <asm/unaligned.h>
 
@@ -160,6 +160,7 @@ struct tegra_i2c_dev {
        struct i2c_adapter adapter;
        struct clk *div_clk;
        struct clk *fast_clk;
+       struct reset_control *rst;
        void __iomem *base;
        int cont_id;
        int irq;
@@ -415,9 +416,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
                return err;
        }
 
-       tegra_periph_reset_assert(i2c_dev->div_clk);
+       reset_control_assert(i2c_dev->rst);
        udelay(2);
-       tegra_periph_reset_deassert(i2c_dev->div_clk);
+       reset_control_deassert(i2c_dev->rst);
 
        if (i2c_dev->is_dvc)
                tegra_dvc_init(i2c_dev);
@@ -743,6 +744,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->cont_id = pdev->id;
        i2c_dev->dev = &pdev->dev;
 
+       i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c");
+       if (IS_ERR(i2c_dev->rst)) {
+               dev_err(&pdev->dev, "missing controller reset");
+               return PTR_ERR(i2c_dev->rst);
+       }
+
        ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency",
                                        &i2c_dev->bus_clk_rate);
        if (ret)
index f80b700f821ca4ece2a17ef1db08c099738f74fe..797ed29a36ea7969765e90641d15f3a66e982db3 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[] __initdata = {
+static struct cpuidle_state nehalem_cstates[] = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[] __initdata = {
+static struct cpuidle_state snb_cstates[] = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[] __initdata = {
+static struct cpuidle_state ivb_cstates[] = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[] __initdata = {
+static struct cpuidle_state hsw_cstates[] = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[] __initdata = {
+static struct cpuidle_state atom_cstates[] = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .enter = NULL }
 };
-static struct cpuidle_state avn_cstates[] __initdata = {
+static struct cpuidle_state avn_cstates[] = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -344,6 +344,8 @@ static struct cpuidle_state avn_cstates[] __initdata = {
                .exit_latency = 15,
                .target_residency = 45,
                .enter = &intel_idle },
+       {
+               .enter = NULL }
 };
 
 /**
index 12fef76c791c524454bd9a0c48d5b4a967ac19af..45126879ad28a2149351232a1f9c4a2551f06c09 100644 (file)
@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
-#define FILTER_SEL_WIDTH_VIN_P_FC \
-       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
-#define FILTER_SEL_WIDTH_TAG_P_FC \
-       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-
-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
-                                 struct l2t_entry *l2t)
-{
-       unsigned int ntuple = 0;
-       u32 viid;
-
-       switch (dev->rdev.lldi.filt_mode) {
-
-       /* default filter mode */
-       case HW_TPL_FR_MT_PR_IV_P_FC:
-               if (l2t->vlan == VLAN_NONE)
-                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
-               else {
-                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
-                       ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
-               }
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       case HW_TPL_FR_MT_PR_OV_P_FC: {
-               viid = cxgb4_port_viid(l2t->neigh->dev);
-
-               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
-               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
-               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       }
-       default:
-               break;
-       }
-       return ntuple;
-}
-
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req->local_ip = la->sin_addr.s_addr;
                        req->peer_ip = ra->sin_addr.s_addr;
                        req->opt0 = cpu_to_be64(opt0);
-                       req->params = cpu_to_be32(select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t));
+                       req->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req6->peer_ip_lo = *((__be64 *)
                                                (ra6->sin6_addr.s6_addr + 8));
                        req6->opt0 = cpu_to_be64(opt0);
-                       req6->params = cpu_to_be32(
-                                       select_ntuple(ep->com.dev, ep->dst,
-                                                     ep->l2t));
+                       req6->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
                }
        } else {
@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
                        t5_req->peer_ip = ra->sin_addr.s_addr;
                        t5_req->opt0 = cpu_to_be64(opt0);
                        t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
-                                               select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t)));
+                                                    cxgb4_select_ntuple(
+                                            ep->com.dev->rdev.lldi.ports[0],
+                                            ep->l2t)));
                        t5_req->opt2 = cpu_to_be32(opt2);
                } else {
                        t5_req6 = (struct cpl_t5_act_open_req6 *)
@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
                                                (ra6->sin6_addr.s6_addr + 8));
                        t5_req6->opt0 = cpu_to_be64(opt0);
                        t5_req6->params = (__force __be64)cpu_to_be32(
-                               select_ntuple(ep->com.dev, ep->dst, ep->l2t));
+                                                       cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        t5_req6->opt2 = cpu_to_be32(opt2);
                }
        }
@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        memset(req, 0, sizeof(*req));
        req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
-       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+       req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
+                                    ep->com.dev->rdev.lldi.ports[0],
                                     ep->l2t));
        sin = (struct sockaddr_in *)&ep->com.local_addr;
        req->le.lport = sin->sin_port;
@@ -2938,7 +2899,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       if (dev->rdev.lldi.enable_fw_ofld_conn)
+       if (dev->rdev.lldi.enable_fw_ofld_conn &&
+           ep->com.local_addr.ss_family == AF_INET)
                ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
                                             cm_id->local_addr.ss_family, ep);
        else
@@ -3323,9 +3285,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Calculate the server tid from filter hit index from cpl_rx_pkt.
         */
-       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
-                                         - dev->rdev.lldi.tids->sftid_base
-                                         + dev->rdev.lldi.tids->nstids;
+       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
        lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
        if (!lep) {
@@ -3397,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        window = (__force u16) htons((__force u16)tcph->window);
 
        /* Calcuate filter portion for LE region. */
-       filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
+       filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
+                                                   dev->rdev.lldi.ports[0],
+                                                   e));
 
        /*
         * Synthesize the cpl_pass_accept_req. We have everything except the
index c29b5c8388331458bb2a2caf85580d76031f1dcb..cdc7df4fdb8aedea8c9026de82d774e5f5fe502b 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>      /* For ARPHRD_xxx */
 #include <linux/module.h>
 #include <net/rtnetlink.h>
 #include "ipoib.h"
@@ -103,7 +104,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
-       if (!pdev)
+       if (!pdev || pdev->type != ARPHRD_INFINIBAND)
                return -ENODEV;
 
        ppriv = netdev_priv(pdev);
index 846ccdd905b19b66872762fd05db29ea0552a8cb..d2965e4b32243a90f40db55a7722c3229d4edb3a 100644 (file)
@@ -1871,6 +1871,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
                break;
 
        case EV_ABS:
+               input_alloc_absinfo(dev);
+               if (!dev->absinfo)
+                       return;
+
                __set_bit(code, dev->absbit);
                break;
 
index 8508879f6fafd2663d393cb6afad9f00340b341c..9757a58bc8978c3f81b50c2cafbe1438940a6b5e 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/input/matrix_keypad.h>
-#include <linux/clk/tegra.h>
+#include <linux/reset.h>
 #include <linux/err.h>
 
 #define KBC_MAX_KPENT  8
@@ -116,6 +116,7 @@ struct tegra_kbc {
        u32 wakeup_key;
        struct timer_list timer;
        struct clk *clk;
+       struct reset_control *rst;
        const struct tegra_kbc_hw_support *hw_support;
        int max_keys;
        int num_rows_and_columns;
@@ -373,9 +374,9 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
        clk_prepare_enable(kbc->clk);
 
        /* Reset the KBC controller to clear all previous status.*/
-       tegra_periph_reset_assert(kbc->clk);
+       reset_control_assert(kbc->rst);
        udelay(100);
-       tegra_periph_reset_deassert(kbc->clk);
+       reset_control_assert(kbc->rst);
        udelay(100);
 
        tegra_kbc_config_pins(kbc);
@@ -663,6 +664,12 @@ static int tegra_kbc_probe(struct platform_device *pdev)
                return PTR_ERR(kbc->clk);
        }
 
+       kbc->rst = devm_reset_control_get(&pdev->dev, "kbc");
+       if (IS_ERR(kbc->rst)) {
+               dev_err(&pdev->dev, "failed to get keyboard reset\n");
+               return PTR_ERR(kbc->rst);
+       }
+
        /*
         * The time delay between two consecutive reads of the FIFO is
         * the sum of the repeat time and the time taken for scanning
index 75762d6ff3ba70934190bb2fe70ef6d6135d49c5..aa127ba392a45cbabe9f95180876543dd6441865 100644 (file)
@@ -455,7 +455,18 @@ static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
        }
 }
 
-static irqreturn_t zforce_interrupt(int irq, void *dev_id)
+static irqreturn_t zforce_irq(int irq, void *dev_id)
+{
+       struct zforce_ts *ts = dev_id;
+       struct i2c_client *client = ts->client;
+
+       if (ts->suspended && device_may_wakeup(&client->dev))
+               pm_wakeup_event(&client->dev, 500);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
        struct zforce_ts *ts = dev_id;
        struct i2c_client *client = ts->client;
@@ -465,12 +476,10 @@ static irqreturn_t zforce_interrupt(int irq, void *dev_id)
        u8 *payload;
 
        /*
-        * When suspended, emit a wakeup signal if necessary and return.
+        * When still suspended, return.
         * Due to the level-interrupt we will get re-triggered later.
         */
        if (ts->suspended) {
-               if (device_may_wakeup(&client->dev))
-                       pm_wakeup_event(&client->dev, 500);
                msleep(20);
                return IRQ_HANDLED;
        }
@@ -763,8 +772,8 @@ static int zforce_probe(struct i2c_client *client,
         * Therefore we can trigger the interrupt anytime it is low and do
         * not need to limit it to the interrupt edge.
         */
-       ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       zforce_interrupt,
+       ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                       zforce_irq, zforce_irq_thread,
                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        input_dev->name, ts);
        if (ret) {
index 497bd026c2378eec6e781df68d007c135be4c1f7..4a48255281887e8c03f9dbacccf404f4f9c52476 100644 (file)
@@ -1643,10 +1643,6 @@ setup_hfcpci(struct IsdnCard *card)
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
index f6ab63aa699590278531ba9ae6ceabe75ba90813..33eeb4602c7e7131078d78d97b24f09971b8396e 100644 (file)
@@ -290,10 +290,6 @@ int setup_telespci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
index 05188351711d2d80f5ac8cd0a006159b732b2c90..a97263e902ffc6b927db6b935cb290902909f21e 100644 (file)
@@ -244,18 +244,12 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -427,15 +421,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5521_load_engine(chip);
+       ret = lp5521_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5521_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 6b553d9f4266d570eec78a2180eee9b56194d62c..fd9ab5f61441c50716620138bf55b175c2ac1045 100644 (file)
@@ -337,18 +337,12 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -548,15 +542,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5523_load_engine_and_select_page(chip);
+       ret = lp5523_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5523_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 11e20afbdcacb7d31e49798db6d2dfbf0504afd8..705698fd2c7ed0f8f5e4fcada7b060627352be05 100644 (file)
@@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
 
        pcr->remove_pci = true;
 
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
 
        mfd_remove_devices(&pcidev->dev);
 
index d210d131fef255da97e7d277574ac80f01a66341..0f55589a56b815af4c00bc521c504db468774fa5 100644 (file)
@@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        info->map.cached =
-               ioremap_cached(info->map.phys, info->map.size);
+               ioremap_cache(info->map.phys, info->map.size);
        if (!info->map.cached)
                printk(KERN_WARNING "Failed to ioremap cached %s\n",
                       info->map.name);
index 187b1b7772ef1b873303fc46998a591137bec7b7..4ced59436558e65a723df9975e8302fcec2cbb62 100644 (file)
@@ -2201,20 +2201,25 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2229,20 +2234,25 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2258,15 +2268,21 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
-       // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
-       // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+       __get_state_machine_lock(port);
+       /* on link down we are zeroing duplex and speed since
+        * some of the adaptors(ce1000.lan) report full duplex/speed
+        * instead of N/A(duplex) / 0(speed).
+        *
+        * on link up we are forcing recheck on the duplex and speed since
+        * some of he adaptors(ce1000.lan) report.
+        */
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2282,10 +2298,15 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
                port->actor_oper_port_key = (port->actor_admin_port_key &=
                                             ~AD_SPEED_KEY_BITS);
        }
-       //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       pr_debug("Port %d changed link status to %s",
+               port->actor_port_number,
+               (link == BOND_LINK_UP) ? "UP" : "DOWN");
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /*
index 398e299ee1bded33a57d7eb91318b00b24513658..4b8c58b0ec243575bbc17a547f7370b8d0b26d54 100644 (file)
@@ -3732,7 +3732,8 @@ static inline int bond_slave_override(struct bonding *bond,
 }
 
 
-static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index b2ffad1304d221ef54e60cd1a82138a4d8344975..248baf6273fb76a2b179c50fe068aeddff51a42e 100644 (file)
@@ -565,6 +565,8 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        /* Make sure pointer to data buffer is set */
        wmb();
 
+       skb_tx_timestamp(skb);
+
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
        /* Increment index to point to the next BD */
@@ -579,8 +581,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index a36a760ada28af64272a5132a60648c543963bed..29801750f239b247389c7040f6616f9b79d14983 100644 (file)
@@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
         * Mask some pcie error bits
         */
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
-       data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       if (pos) {
+               pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+               data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+               pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       }
        /* clear error status */
        pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
index a1f66e2c9a8694c9d83471dd63f6659d431840eb..ec6119089b82b8445cd573d961378c70b28632e5 100644 (file)
@@ -520,10 +520,12 @@ struct bnx2x_fastpath {
 #define BNX2X_FP_STATE_IDLE                  0
 #define BNX2X_FP_STATE_NAPI            (1 << 0)    /* NAPI owns this FP */
 #define BNX2X_FP_STATE_POLL            (1 << 1)    /* poll owns this FP */
-#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 2)    /* NAPI yielded this FP */
-#define BNX2X_FP_STATE_POLL_YIELD      (1 << 3)    /* poll yielded this FP */
+#define BNX2X_FP_STATE_DISABLED                (1 << 2)
+#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 3)    /* NAPI yielded this FP */
+#define BNX2X_FP_STATE_POLL_YIELD      (1 << 4)    /* poll yielded this FP */
+#define BNX2X_FP_OWNED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
 #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD)
-#define BNX2X_FP_LOCKED        (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
+#define BNX2X_FP_LOCKED        (BNX2X_FP_OWNED | BNX2X_FP_STATE_DISABLED)
 #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD)
        /* protect state */
        spinlock_t lock;
@@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = true;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        if (fp->state & BNX2X_FP_LOCKED) {
                WARN_ON(fp->state & BNX2X_FP_STATE_NAPI);
                fp->state |= BNX2X_FP_STATE_NAPI_YIELD;
@@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
                /* we don't care if someone yielded */
                fp->state = BNX2X_FP_STATE_NAPI;
        }
-       spin_unlock(&fp->lock);
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = false;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        WARN_ON(fp->state &
                (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD));
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
-       spin_unlock(&fp->lock);
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
        spin_unlock_bh(&fp->lock);
        return rc;
 }
@@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 /* true if a socket is polling, even if it did not get the lock */
 static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
-       WARN_ON(!(fp->state & BNX2X_FP_LOCKED));
+       WARN_ON(!(fp->state & BNX2X_FP_OWNED));
        return fp->state & BNX2X_FP_USER_PEND;
 }
+
+/* false if fp is currently owned */
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       int rc = true;
+
+       spin_lock_bh(&fp->lock);
+       if (fp->state & BNX2X_FP_OWNED)
+               rc = false;
+       fp->state |= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
+
+       return rc;
+}
 #else
 static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp)
 {
@@ -709,6 +729,10 @@ static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
        return false;
 }
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       return true;
+}
 #endif /* CONFIG_NET_RX_BUSY_POLL */
 
 /* Use 2500 as a mini-jumbo MTU for FCoE */
@@ -1250,7 +1274,10 @@ struct bnx2x_slowpath {
         * Therefore, if they would have been defined in the same union,
         * data can get corrupted.
         */
-       struct afex_vif_list_ramrod_data func_afex_rdata;
+       union {
+               struct afex_vif_list_ramrod_data        viflist_data;
+               struct function_update_data             func_update;
+       } func_afex_rdata;
 
        /* used by dmae command executer */
        struct dmae_command             dmae[MAX_DMAE_C];
@@ -2499,4 +2526,6 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
 #define MCPR_SCRATCH_BASE(bp) \
        (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 
+#define E1H_MAX_MF_SB_COUNT (HC_SB_MAX_SB_E1X/(E1HVN_MAX * PORT_MAX))
+
 #endif /* bnx2x.h */
index ec96130533cc54630c3f26f6253e58b5a0f5a7cf..bf811565ee245a0472cffc0ea5f70b30da053beb 100644 (file)
@@ -160,6 +160,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        struct sk_buff *skb = tx_buf->skb;
        u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
        int nbd;
+       u16 split_bd_len = 0;
 
        /* prefetch skb end pointer to speedup dev_kfree_skb() */
        prefetch(&skb->end);
@@ -167,10 +168,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        DP(NETIF_MSG_TX_DONE, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
           txdata->txq_index, idx, tx_buf, skb);
 
-       /* unmap first bd */
        tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
-       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-                        BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
@@ -188,12 +186,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        --nbd;
        bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
 
-       /* ...and the TSO split header bd since they have no mapping */
+       /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */
        if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
+               tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
+               split_bd_len = BD_UNMAP_LEN(tx_data_bd);
                --nbd;
                bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
        }
 
+       /* unmap first bd */
+       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
+                        BD_UNMAP_LEN(tx_start_bd) + split_bd_len,
+                        DMA_TO_DEVICE);
+
        /* now free frags */
        while (nbd > 0) {
 
@@ -1790,26 +1795,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_rx_queue_cnic(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_eth_queue(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 void bnx2x_netif_start(struct bnx2x *bp)
@@ -1832,7 +1833,8 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
                bnx2x_napi_disable_cnic(bp);
 }
 
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
index da8fcaa74495475cb2c2c3984f3aa3cf85fc83ba..41f3ca5ad972b396498cbe5b7d7ad72ea9bdb1a7 100644 (file)
@@ -524,7 +524,8 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
 int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
index 20dcc02431cac441a8bf3076a7fe6db1abfb04e9..11fc79585491f484f7ffd56d7a2e8e876ebb8e79 100644 (file)
@@ -3865,6 +3865,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
        } else {
+               /* Enable Auto-Detect to support 1G over CL37 as well */
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
+
+               /* Force cl48 sync_status LOW to avoid getting stuck in CL73
+                * parallel-detect loop when CL73 and CL37 are enabled.
+                */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI, 0x0800);
+               bnx2x_set_aer_mmd(params, phy);
+
                bnx2x_disable_kr2(params, vars, phy);
        }
 
@@ -8120,17 +8133,20 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                *edc_mode = EDC_MODE_ACTIVE_DAC;
                        else
                                check_limiting_mode = 1;
-               } else if (copper_module_type &
-                       SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+               } else {
+                       *edc_mode = EDC_MODE_PASSIVE_DAC;
+                       /* Even in case PASSIVE_DAC indication is not set,
+                        * treat it as a passive DAC cable, since some cables
+                        * don't have this indication.
+                        */
+                       if (copper_module_type &
+                           SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
                                   "Passive Copper cable detected\n");
-                               *edc_mode =
-                                     EDC_MODE_PASSIVE_DAC;
-               } else {
-                       DP(NETIF_MSG_LINK,
-                          "Unknown copper-cable-type 0x%x !!!\n",
-                          copper_module_type);
-                       return -EINVAL;
+                       } else {
+                               DP(NETIF_MSG_LINK,
+                                  "Unknown copper-cable-type\n");
+                       }
                }
                break;
        }
@@ -10825,9 +10841,9 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                           (1<<11));
 
        if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-                       (phy->req_line_speed == SPEED_1000)) {
+            (phy->speed_cap_mask &
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+           (phy->req_line_speed == SPEED_1000)) {
                an_1000_val |= (1<<8);
                autoneg_val |= (1<<9 | 1<<12);
                if (phy->req_duplex == DUPLEX_FULL)
@@ -10843,30 +10859,32 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                        0x09,
                        &an_1000_val);
 
-       /* Set 100 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
-                       an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-
-       /* Set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Advertise 10/100 link speed */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       an_10_100_val |= (1<<7);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       an_10_100_val |= (1<<8);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13342,6 +13360,10 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
 
+       /* Do not touch the link in case physical link down */
+       if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+               return 1;
+
        /* a. Update shmem->link_status accordingly
         * b. Update link_vars->link_up
         */
@@ -13550,7 +13572,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
         */
        not_kr2_device = (((base_page & 0x8000) == 0) ||
                          (((base_page & 0x8000) &&
-                           ((next_page & 0xe0) == 0x2))));
+                           ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
        if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
index 814d0eca9b334ea86c862bc617a46f137f04d475..8b3107b2fcc13dd619ae08290f4467c47e8e67b7 100644 (file)
@@ -11447,9 +11447,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                }
        }
 
-       /* adjust igu_sb_cnt to MF for E1x */
-       if (CHIP_IS_E1x(bp) && IS_MF(bp))
-               bp->igu_sb_cnt /= E1HVN_MAX;
+       /* adjust igu_sb_cnt to MF for E1H */
+       if (CHIP_IS_E1H(bp) && IS_MF(bp))
+               bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, E1H_MAX_MF_SB_COUNT);
 
        /* port info */
        bnx2x_get_port_hwinfo(bp);
index 3efbb35267c853d576cc3a4d3104ec4ba1a18d1d..14ffb6e56e593d6a371e1036edf02ff7c193eb08 100644 (file)
@@ -7179,6 +7179,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX1_PCI_CTRL                       0x80ca
 #define MDIO_WC_REG_RX2_PCI_CTRL                       0x80da
 #define MDIO_WC_REG_RX3_PCI_CTRL                       0x80ea
+#define MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI             0x80fa
 #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G          0x8104
 #define MDIO_WC_REG_XGXS_STATUS3                       0x8129
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
index 32c92abf50949fa1494812ab9d3734a5a2f3db1f..18438a504d573082239fe53532035d5516ff2881 100644 (file)
@@ -2038,6 +2038,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        struct bnx2x_vlan_mac_ramrod_params p;
        struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
        struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+       unsigned long flags;
        int read_lock;
        int rc = 0;
 
@@ -2046,8 +2047,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        spin_lock_bh(&exeq->lock);
 
        list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
-               if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-                   *vlan_mac_flags) {
+               flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        rc = exeq->remove(bp, exeq->owner, exeq_pos);
                        if (rc) {
                                BNX2X_ERR("Failed to remove command\n");
@@ -2080,7 +2082,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
                return read_lock;
 
        list_for_each_entry(pos, &o->head, link) {
-               if (pos->vlan_mac_flags == *vlan_mac_flags) {
+               flags = pos->vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
                        memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
                        rc = bnx2x_config_vlan_mac(bp, &p);
@@ -4382,8 +4386,11 @@ int bnx2x_config_rss(struct bnx2x *bp,
        struct bnx2x_raw_obj *r = &o->raw;
 
        /* Do nothing if only driver cleanup was requested */
-       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+               DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
+                  p->ramrod_flags);
                return 0;
+       }
 
        r->set_pending(r);
 
index 658f4e33abf9281d76e083873cb963c9b47b05f1..6a53c15c85a338c8efbb45ecf3348913272e038a 100644 (file)
@@ -266,6 +266,13 @@ enum {
        BNX2X_DONT_CONSUME_CAM_CREDIT,
        BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
+/* When looking for matching filters, some flags are not interesting */
+#define BNX2X_VLAN_MAC_CMP_MASK        (1 << BNX2X_UC_LIST_MAC | \
+                                1 << BNX2X_ETH_MAC | \
+                                1 << BNX2X_ISCSI_ETH_MAC | \
+                                1 << BNX2X_NETQ_ETH_MAC)
+#define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
+       ((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
 struct bnx2x_vlan_mac_ramrod_params {
        /* Object to run the command from */
index 2e46c28fc6019a892f7792c6017effe3f7db7063..e7845e5be1c76fb452d8ecb94943326844ab5eaa 100644 (file)
@@ -1209,6 +1209,11 @@ static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf)
                /* next state */
                vfop->state = BNX2X_VFOP_RXMODE_DONE;
 
+               /* record the accept flags in vfdb so hypervisor can modify them
+                * if necessary
+                */
+               bnx2x_vfq(vf, ramrod->cl_id - vf->igu_base_id, accept_flags) =
+                       ramrod->rx_accept_flags;
                vfop->rc = bnx2x_config_rx_mode(bp, ramrod);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 op_err:
@@ -1224,39 +1229,43 @@ op_pending:
        return;
 }
 
+static void bnx2x_vf_prep_rx_mode(struct bnx2x *bp, u8 qid,
+                                 struct bnx2x_rx_mode_ramrod_params *ramrod,
+                                 struct bnx2x_virtf *vf,
+                                 unsigned long accept_flags)
+{
+       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
+
+       memset(ramrod, 0, sizeof(*ramrod));
+       ramrod->cid = vfq->cid;
+       ramrod->cl_id = vfq_cl_id(vf, vfq);
+       ramrod->rx_mode_obj = &bp->rx_mode_obj;
+       ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
+       ramrod->rx_accept_flags = accept_flags;
+       ramrod->tx_accept_flags = accept_flags;
+       ramrod->pstate = &vf->filter_state;
+       ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
+
+       set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
+       set_bit(RAMROD_RX, &ramrod->ramrod_flags);
+       set_bit(RAMROD_TX, &ramrod->ramrod_flags);
+
+       ramrod->rdata = bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
+       ramrod->rdata_mapping = bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+}
+
 int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
                          struct bnx2x_virtf *vf,
                          struct bnx2x_vfop_cmd *cmd,
                          int qid, unsigned long accept_flags)
 {
-       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
 
        if (vfop) {
                struct bnx2x_rx_mode_ramrod_params *ramrod =
                        &vf->op_params.rx_mode;
 
-               memset(ramrod, 0, sizeof(*ramrod));
-
-               /* Prepare ramrod parameters */
-               ramrod->cid = vfq->cid;
-               ramrod->cl_id = vfq_cl_id(vf, vfq);
-               ramrod->rx_mode_obj = &bp->rx_mode_obj;
-               ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
-
-               ramrod->rx_accept_flags = accept_flags;
-               ramrod->tx_accept_flags = accept_flags;
-               ramrod->pstate = &vf->filter_state;
-               ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
-
-               set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
-               set_bit(RAMROD_RX, &ramrod->ramrod_flags);
-               set_bit(RAMROD_TX, &ramrod->ramrod_flags);
-
-               ramrod->rdata =
-                       bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
-               ramrod->rdata_mapping =
-                       bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+               bnx2x_vf_prep_rx_mode(bp, qid, ramrod, vf, accept_flags);
 
                bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG,
                                 bnx2x_vfop_rxmode, cmd->done);
@@ -3202,13 +3211,16 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
        }
 
-       /* prepare msix vectors in VF configuration space */
+       /* prepare msix vectors in VF configuration space - the value in the
+        * PCI configuration space should be the index of the last entry,
+        * namely one less than the actual size of the table
+        */
        for (vf_idx = first_vf; vf_idx < first_vf + req_vfs; vf_idx++) {
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
-                      num_vf_queues);
+                      num_vf_queues - 1);
                DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
-                  vf_idx, num_vf_queues);
+                  vf_idx, num_vf_queues - 1);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
@@ -3436,10 +3448,18 @@ out:
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
+       struct bnx2x_queue_state_params q_params = {NULL};
+       struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+       struct bnx2x_queue_update_params *update_params;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_rx_mode_ramrod_params rx_ramrod;
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
+       unsigned long vlan_mac_flags = 0;
+       unsigned long ramrod_flags = 0;
        struct bnx2x_virtf *vf = NULL;
-       struct pf_vf_bulletin_content *bulletin = NULL;
+       unsigned long accept_flags;
+       int rc;
 
        /* sanity and init */
        rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
@@ -3457,104 +3477,118 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        /* update PF's copy of the VF's bulletin. No point in posting the vlan
         * to the VF since it doesn't have anything to do with it. But it useful
         * to store it here in case the VF is not up yet and we can only
-        * configure the vlan later when it does.
+        * configure the vlan later when it does. Treat vlan id 0 as remove the
+        * Host tag.
         */
-       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       if (vlan > 0)
+               bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       else
+               bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
        bulletin->vlan = vlan;
 
        /* is vf initialized and queue set up? */
-       q_logical_state =
-               bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj));
-       if (vf->state == VF_ENABLED &&
-           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
-               /* configure the vlan in device on this vf's queue */
-               unsigned long ramrod_flags = 0;
-               unsigned long vlan_mac_flags = 0;
-               struct bnx2x_vlan_mac_obj *vlan_obj =
-                       &bnx2x_leading_vfq(vf, vlan_obj);
-               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-               struct bnx2x_queue_state_params q_params = {NULL};
-               struct bnx2x_queue_update_params *update_params;
+       if (vf->state != VF_ENABLED ||
+           bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
+           BNX2X_Q_LOGICAL_STATE_ACTIVE)
+               return rc;
 
-               rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-               if (rc)
-                       return rc;
-               memset(&ramrod_param, 0, sizeof(ramrod_param));
+       /* configure the vlan in device on this vf's queue */
+       vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
+       rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
+       if (rc)
+               return rc;
 
-               /* must lock vfpf channel to protect against vf flows */
-               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       /* must lock vfpf channel to protect against vf flows */
+       bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
-               /* remove existing vlans */
-               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
-                                         &ramrod_flags);
-               if (rc) {
-                       BNX2X_ERR("failed to delete vlans\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
+       /* remove existing vlans */
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                 &ramrod_flags);
+       if (rc) {
+               BNX2X_ERR("failed to delete vlans\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* need to remove/add the VF's accept_any_vlan bit */
+       accept_flags = bnx2x_leading_vfq(vf, accept_flags);
+       if (vlan)
+               clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+       else
+               set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+       bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
+                             accept_flags);
+       bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
+       bnx2x_config_rx_mode(bp, &rx_ramrod);
+
+       /* configure the new vlan to device */
+       memset(&ramrod_param, 0, sizeof(ramrod_param));
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       ramrod_param.vlan_mac_obj = vlan_obj;
+       ramrod_param.ramrod_flags = ramrod_flags;
+       set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+               &ramrod_param.user_req.vlan_mac_flags);
+       ramrod_param.user_req.u.vlan.vlan = vlan;
+       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+       if (rc) {
+               BNX2X_ERR("failed to configure vlan\n");
+               rc =  -EINVAL;
+               goto out;
+       }
 
-               /* send queue update ramrod to configure default vlan and silent
-                * vlan removal
+       /* send queue update ramrod to configure default vlan and silent
+        * vlan removal
+        */
+       __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+       q_params.cmd = BNX2X_Q_CMD_UPDATE;
+       q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
+       update_params = &q_params.params.update;
+       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                 &update_params->update_flags);
+       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                 &update_params->update_flags);
+       if (vlan == 0) {
+               /* if vlan is 0 then we want to leave the VF traffic
+                * untagged, and leave the incoming traffic untouched
+                * (i.e. do not remove any vlan tags).
                 */
-               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-               q_params.cmd = BNX2X_Q_CMD_UPDATE;
-               q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
-               update_params = &q_params.params.update;
-               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+               __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                           &update_params->update_flags);
+               __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                           &update_params->update_flags);
+       } else {
+               /* configure default vlan to vf queue and set silent
+                * vlan removal (the vf remains unaware of this vlan).
+                */
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
                          &update_params->update_flags);
-               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
                          &update_params->update_flags);
+               update_params->def_vlan = vlan;
+               update_params->silent_removal_value =
+                       vlan & VLAN_VID_MASK;
+               update_params->silent_removal_mask = VLAN_VID_MASK;
+       }
 
-               if (vlan == 0) {
-                       /* if vlan is 0 then we want to leave the VF traffic
-                        * untagged, and leave the incoming traffic untouched
-                        * (i.e. do not remove any vlan tags).
-                        */
-                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                   &update_params->update_flags);
-                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                   &update_params->update_flags);
-               } else {
-                       /* configure the new vlan to device */
-                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-                       ramrod_param.vlan_mac_obj = vlan_obj;
-                       ramrod_param.ramrod_flags = ramrod_flags;
-                       ramrod_param.user_req.u.vlan.vlan = vlan;
-                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-                       if (rc) {
-                               BNX2X_ERR("failed to configure vlan\n");
-                               rc =  -EINVAL;
-                               goto out;
-                       }
-
-                       /* configure default vlan to vf queue and set silent
-                        * vlan removal (the vf remains unaware of this vlan).
-                        */
-                       update_params = &q_params.params.update;
-                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                 &update_params->update_flags);
-                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                 &update_params->update_flags);
-                       update_params->def_vlan = vlan;
-               }
+       /* Update the Queue state */
+       rc = bnx2x_queue_state_change(bp, &q_params);
+       if (rc) {
+               BNX2X_ERR("Failed to configure default VLAN\n");
+               goto out;
+       }
 
-               /* Update the Queue state */
-               rc = bnx2x_queue_state_change(bp, &q_params);
-               if (rc) {
-                       BNX2X_ERR("Failed to configure default VLAN\n");
-                       goto out;
-               }
 
-               /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured the Vlan before vf was
-                * up and we were called because the VF came up later
-                */
+       /* clear the flag indicating that this VF needs its vlan
+        * (will only be set if the HV configured the Vlan before vf was
+        * up and we were called because the VF came up later
+        */
 out:
-               vf->cfg_flags &= ~VF_CFG_VLAN;
-               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
-       }
+       vf->cfg_flags &= ~VF_CFG_VLAN;
+       bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
        return rc;
 }
 
index 1ff6a9366629ed88fe79a079391c92e95d1e9baf..8c213fa52174f918d4f445dae554b593b54845db 100644 (file)
@@ -74,6 +74,7 @@ struct bnx2x_vf_queue {
        /* VLANs object */
        struct bnx2x_vlan_mac_obj       vlan_obj;
        atomic_t vlan_count;            /* 0 means vlan-0 is set  ~ untagged */
+       unsigned long accept_flags;     /* last accept flags configured */
 
        /* Queue Slow-path State object */
        struct bnx2x_queue_sp_obj       sp_obj;
index efa8a151d78907d4b17d5f5dd07eaed9b1f2c02c..0756d7dabdd59ae0e58139e07081d9ba02ca5a10 100644 (file)
@@ -208,7 +208,7 @@ static int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
                return -EINVAL;
        }
 
-       BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);
+       DP(BNX2X_MSG_IOV, "valid ME register value: 0x%08x\n", me_reg);
 
        *vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;
 
@@ -1598,6 +1598,8 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
                if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
                        unsigned long accept = 0;
+                       struct pf_vf_bulletin_content *bulletin =
+                               BP_VF_BULLETIN(bp, vf->index);
 
                        /* covert VF-PF if mask to bnx2x accept flags */
                        if (msg->rx_mask & VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST)
@@ -1617,9 +1619,11 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                __set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
 
                        /* A packet arriving the vf's mac should be accepted
-                        * with any vlan
+                        * with any vlan, unless a vlan has already been
+                        * configured.
                         */
-                       __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
+                       if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
+                               __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
 
                        /* set rx-mode */
                        rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd,
@@ -1710,6 +1714,21 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
                        goto response;
                }
        }
+       /* if vlan was set by hypervisor we don't allow guest to config vlan */
+       if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
+               int i;
+
+               /* search for vlan filters */
+               for (i = 0; i < filters->n_mac_vlan_filters; i++) {
+                       if (filters->filters[i].flags &
+                           VFPF_Q_FILTER_VLAN_TAG_VALID) {
+                               BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
+                                         vf->abs_vfid);
+                               vf->op_rc = -EPERM;
+                               goto response;
+                       }
+               }
+       }
 
        /* verify vf_qid */
        if (filters->vf_qid > vf_rxq_count(vf))
@@ -1805,6 +1824,9 @@ static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
 
        /* flags handled individually for backward/forward compatability */
+       vf_op_params->rss_flags = 0;
+       vf_op_params->ramrod_flags = 0;
+
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
                __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
index f3dd93b4aeaac1bc8cdff71c9113d6668e085fd2..15a66e4b1f57a19d2d1e7feb31b557e3809fe6b0 100644 (file)
@@ -7622,7 +7622,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return (base > 0xffffdcc0) && (base + len + 8 < base);
+       return base + len + 8 < base;
 }
 
 /* Test for TSO DMA buffers that cross into regions which are within MSS bytes
index 6c9308850453bf1ecd21173afa1d1cf11681c8c7..56e0415f8cdff396aca4d6462f2432278e258018 100644 (file)
@@ -228,6 +228,25 @@ struct tp_params {
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
+
+       u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
+       u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
+
+       /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
+        * subset of the set of fields which may be present in the Compressed
+        * Filter Tuple portion of filters and TCP TCB connections.  The
+        * fields which are present are controlled by the TP_VLAN_PRI_MAP.
+        * Since a variable number of fields may or may not be present, their
+        * shifted field positions within the Compressed Filter Tuple may
+        * vary, or not even be present if the field isn't selected in
+        * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
+        * places we store their offsets here, or a -1 if the field isn't
+        * present.
+        */
+       int vlan_shift;
+       int vnic_shift;
+       int port_shift;
+       int protocol_shift;
 };
 
 struct vpd_params {
@@ -926,6 +945,8 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
               const u8 *fw_data, unsigned int fw_size,
               struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
+int t4_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
index d6b12e035a7d9f27d84d397dc2921713c7fed46f..fff02ed1295e5ef7bab408cbe19c46dbd5eedd52 100644 (file)
@@ -2986,7 +2986,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
                stid += t->stid_base;
-               t->stids_in_use++;
+               /* IPv6 requires max of 520 bits or 16 cells in TCAM
+                * This is equivalent to 4 TIDs. With CLIP enabled it
+                * needs 2 TIDs.
+                */
+               if (family == PF_INET)
+                       t->stids_in_use++;
+               else
+                       t->stids_in_use += 4;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -3012,7 +3019,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
        }
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
-               stid += t->stid_base;
+               stid -= t->nstids;
+               stid += t->sftid_base;
                t->stids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
@@ -3024,14 +3032,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        spin_lock_bh(&t->stid_lock);
        if (family == PF_INET)
                __clear_bit(stid, t->stid_bmap);
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       t->stids_in_use--;
+       if (family == PF_INET)
+               t->stids_in_use--;
+       else
+               t->stids_in_use -= 4;
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -3134,6 +3152,7 @@ static int tid_init(struct tid_info *t)
        size_t size;
        unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
+       struct adapter *adap = container_of(t, struct adapter, tids);
 
        stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
        size = t->ntids * sizeof(*t->tid_tab) +
@@ -3167,6 +3186,11 @@ static int tid_init(struct tid_info *t)
                t->afree = t->atid_tab;
        }
        bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
+       /* Reserve stid 0 for T4/T5 adapters */
+       if (!t->stid_base &&
+           (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
+               __set_bit(0, t->stid_bmap);
+
        return 0;
 }
 
@@ -3731,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
-       lli.filt_mode = adap->filter_mode;
+       lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
                lli.tx_modq[i] = i;
@@ -4179,7 +4203,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        /* Check to make sure the filter requested is writable ...
@@ -4205,12 +4229,17 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
                        f->fs.val.lip[i] = val[i];
                        f->fs.mask.lip[i] = ~0;
                }
-               if (adap->filter_mode & F_PORT) {
+               if (adap->params.tp.vlan_pri_map & F_PORT) {
                        f->fs.val.iport = port;
                        f->fs.mask.iport = mask;
                }
        }
 
+       if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+
        f->fs.dirsteer = 1;
        f->fs.iq = queue;
        /* Mark filter as locked */
@@ -4237,7 +4266,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        f = &adap->tids.ftid_tab[stid];
@@ -5092,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
        enum dev_state state;
        u32 params[7], val[7];
        struct fw_caps_config_cmd caps_cmd;
-       int reset = 1, j;
+       int reset = 1;
 
        /*
         * Contact FW, advertising Master capability (and potentially forcing
@@ -5434,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
        /*
         * These are finalized by FW initialization, load their values now.
         */
-       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
        t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
        t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                     adap->params.b_wnd);
 
-       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
-       for (j = 0; j < NCHAN; j++)
-               adap->params.tp.tx_modq[j] = j;
-
-       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
-                        &adap->filter_mode, 1,
-                        TP_VLAN_PRI_MAP);
-
+       t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
 
index 6f21f2451c3052a24ecd2e8d8d16ee9bdf9996fe..4dd0a82533e442f8b330c5ede554359ea450a087 100644 (file)
@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
index 29878098101eb07771626399a1c5050a9544d055..cb05be905defdceb0e2d0b76386dcd224169b5b0 100644 (file)
@@ -45,6 +45,7 @@
 #include "l2t.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "t4_regs.h"
 
 #define VLAN_NONE 0xfff
 
@@ -411,6 +412,40 @@ done:
 }
 EXPORT_SYMBOL(cxgb4_l2t_get);
 
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t)
+{
+       struct adapter *adap = netdev2adap(dev);
+       struct tp_params *tp = &adap->params.tp;
+       u64 ntuple = 0;
+
+       /* Initialize each of the fields which we care about which are present
+        * in the Compressed Filter Tuple.
+        */
+       if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
+               ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)l2t->lport << tp->port_shift;
+
+       if (tp->protocol_shift >= 0)
+               ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
+
+       if (tp->vnic_shift >= 0) {
+               u32 viid = cxgb4_port_viid(dev);
+               u32 vf = FW_VIID_VIN_GET(viid);
+               u32 pf = FW_VIID_PFN_GET(viid);
+               u32 vld = FW_VIID_VIVLD_GET(viid);
+
+               ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
+                               V_FT_VNID_ID_PF(pf) |
+                               V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+       }
+
+       return ntuple;
+}
+EXPORT_SYMBOL(cxgb4_select_ntuple);
+
 /*
  * Called when address resolution fails for an L2T entry to handle packets
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
index 108c0f1fce1c4e5776b687538d741cd6f771a909..85eb5c71358d80ad91e21df648289047165dbf39 100644 (file)
@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
 struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                const struct net_device *physdev,
                                unsigned int priority);
-
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t);
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
 struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
 int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
index cc380c36e1a8687cd1c7f3b4c3dbf2d0b8c1bf47..cc3511a5cd0c0f9ea54e0d186878821f3dad8096 100644 (file)
@@ -2581,7 +2581,7 @@ static int t4_sge_init_soft(struct adapter *adap)
        #undef READ_FL_BUF
 
        if (fl_small_pg != PAGE_SIZE ||
-           (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg ||
+           (fl_large_pg != 0 && (fl_large_pg < fl_small_pg ||
                                  (fl_large_pg & (fl_large_pg-1)) != 0))) {
                dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
                        fl_small_pg, fl_large_pg);
index 74a6fce5a15a6914faf74bbf903dcc76ec717775..e1413eacdbd20ab2233fd3217222bb76e6b779d1 100644 (file)
@@ -3808,6 +3808,109 @@ int t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
+/**
+ *      t4_init_tp_params - initialize adap->params.tp
+ *      @adap: the adapter
+ *
+ *      Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
+{
+       int chan;
+       u32 v;
+
+       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+
+       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+       for (chan = 0; chan < NCHAN; chan++)
+               adap->params.tp.tx_modq[chan] = chan;
+
+       /* Cache the adapter's Compressed Filter Mode and global Incress
+        * Configuration.
+        */
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.vlan_pri_map, 1,
+                        TP_VLAN_PRI_MAP);
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.ingress_config, 1,
+                        TP_INGRESS_CONFIG);
+
+       /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+        * shift positions of several elements of the Compressed Filter Tuple
+        * for this adapter which we need frequently ...
+        */
+       adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+       adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+       adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+       adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
+                                                              F_PROTOCOL);
+
+       /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+        * represents the presense of an Outer VLAN instead of a VNIC ID.
+        */
+       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+               adap->params.tp.vnic_shift = -1;
+
+       return 0;
+}
+
+/**
+ *      t4_filter_field_shift - calculate filter field shift
+ *      @adap: the adapter
+ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ *      Return the shift position of a filter field within the Compressed
+ *      Filter Tuple.  The filter field is specified via its selection bit
+ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+       unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+       unsigned int sel;
+       int field_shift;
+
+       if ((filter_mode & filter_sel) == 0)
+               return -1;
+
+       for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+               switch (filter_mode & sel) {
+               case F_FCOE:
+                       field_shift += W_FT_FCOE;
+                       break;
+               case F_PORT:
+                       field_shift += W_FT_PORT;
+                       break;
+               case F_VNIC_ID:
+                       field_shift += W_FT_VNIC_ID;
+                       break;
+               case F_VLAN:
+                       field_shift += W_FT_VLAN;
+                       break;
+               case F_TOS:
+                       field_shift += W_FT_TOS;
+                       break;
+               case F_PROTOCOL:
+                       field_shift += W_FT_PROTOCOL;
+                       break;
+               case F_ETHERTYPE:
+                       field_shift += W_FT_ETHERTYPE;
+                       break;
+               case F_MACMATCH:
+                       field_shift += W_FT_MACMATCH;
+                       break;
+               case F_MPSHITTYPE:
+                       field_shift += W_FT_MPSHITTYPE;
+                       break;
+               case F_FRAGMENTATION:
+                       field_shift += W_FT_FRAGMENTATION;
+                       break;
+               }
+       }
+       return field_shift;
+}
+
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
index 0a8205d69d2c290aae4dbec30245c9dc3e18bd39..4082522d81408bf0a23cff8eaf9700bef14533a9 100644 (file)
 
 #define A_TP_TX_SCHED_PCMD 0x25
 
+#define S_VNIC    11
+#define V_VNIC(x) ((x) << S_VNIC)
+#define F_VNIC    V_VNIC(1U)
+
+#define S_FRAGMENTATION    9
+#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
+#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
+
+#define S_MPSHITTYPE    8
+#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
+#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
+
+#define S_MACMATCH    7
+#define V_MACMATCH(x) ((x) << S_MACMATCH)
+#define F_MACMATCH    V_MACMATCH(1U)
+
+#define S_ETHERTYPE    6
+#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
+#define F_ETHERTYPE    V_ETHERTYPE(1U)
+
+#define S_PROTOCOL    5
+#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+#define F_PROTOCOL    V_PROTOCOL(1U)
+
+#define S_TOS    4
+#define V_TOS(x) ((x) << S_TOS)
+#define F_TOS    V_TOS(1U)
+
+#define S_VLAN    3
+#define V_VLAN(x) ((x) << S_VLAN)
+#define F_VLAN    V_VLAN(1U)
+
+#define S_VNIC_ID    2
+#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
+#define F_VNIC_ID    V_VNIC_ID(1U)
+
 #define S_PORT    1
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define S_FCOE    0
+#define V_FCOE(x) ((x) << S_FCOE)
+#define F_FCOE    V_FCOE(1U)
+
 #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
 #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
 
 #define V_CHIPID(x) ((x) << S_CHIPID)
 #define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
 
+/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present.  These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE                       1
+#define W_FT_PORT                       3
+#define W_FT_VNIC_ID                    17
+#define W_FT_VLAN                       17
+#define W_FT_TOS                        8
+#define W_FT_PROTOCOL                   8
+#define W_FT_ETHERTYPE                  16
+#define W_FT_MACMATCH                   9
+#define W_FT_MPSHITTYPE                 3
+#define W_FT_FRAGMENTATION              1
+
+/* Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD                   16
+#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF                 0
+#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF                 7
+#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD                16
+#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
+
 #endif /* __T4_REGS_H */
index 5878df619b531ad0b3ea96167f53e8909ff9fd21..4ccaf9af6fc90cde0d9d13490fa5753e480c543e 100644 (file)
@@ -104,6 +104,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE3_MAX_RSS_QS         16
 #define BE3_MAX_TX_QS          16
 #define BE3_MAX_EVT_QS         16
+#define BE3_SRIOV_MAX_EVT_QS   8
 
 #define MAX_RX_QS              32
 #define MAX_EVT_QS             32
@@ -480,7 +481,7 @@ struct be_adapter {
        struct list_head entry;
 
        u32 flash_status;
-       struct completion flash_compl;
+       struct completion et_cmd_compl;
 
        struct be_resources res;        /* resources available for the func */
        u16 num_vfs;                    /* Number of VFs provisioned by PF */
index e0e8bc1ef14c47e93336df2c784d1ff14e6b4143..94c35c8d799d9f1e4f4b9fd78121600ad600505e 100644 (file)
@@ -141,11 +141,17 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                subsystem = resp_hdr->subsystem;
        }
 
+       if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
+           subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
+               complete(&adapter->et_cmd_compl);
+               return 0;
+       }
+
        if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
             (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
            (subsystem == CMD_SUBSYSTEM_COMMON)) {
                adapter->flash_status = compl_status;
-               complete(&adapter->flash_compl);
+               complete(&adapter->et_cmd_compl);
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
@@ -2017,6 +2023,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
                        0x3ea83c02, 0x4a110304};
        int status;
 
+       if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
+               return 0;
+
        if (mutex_lock_interruptible(&adapter->mbox_lock))
                return -1;
 
@@ -2160,7 +2169,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
                                         msecs_to_jiffies(60000)))
                status = -1;
        else
@@ -2255,8 +2264,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(40000)))
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
+                                        msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2367,6 +2376,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_loopback_test *req;
+       struct be_cmd_resp_loopback_test *resp;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2381,8 +2391,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
-       req->hdr.timeout = cpu_to_le32(4);
 
+       req->hdr.timeout = cpu_to_le32(15);
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
        req->dest_port = cpu_to_le32(port_num);
@@ -2390,12 +2400,15 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
        req->num_pkts = cpu_to_le32(num_pkts);
        req->loopback_type = cpu_to_le32(loopback_type);
 
-       status = be_mcc_notify_wait(adapter);
-       if (!status) {
-               struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-               status = le32_to_cpu(resp->status);
-       }
+       be_mcc_notify(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
 
+       wait_for_completion(&adapter->et_cmd_compl);
+       resp = embedded_payload(wrb);
+       status = le32_to_cpu(resp->status);
+
+       return status;
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
index 0fde69d5cb6afd610db5f2a57325e5d2e9f5ed94..bf40fdaecfa3e89b96fb90336cb26f909642de36 100644 (file)
@@ -2744,13 +2744,16 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                                RSS_ENABLE_UDP_IPV6;
+       } else {
+               /* Disable RSS, if only default RX Q is created */
+               adapter->rss_flags = RSS_ENABLE_NONE;
+       }
 
-               rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
-                                      128);
-               if (rc) {
-                       adapter->rss_flags = 0;
-                       return rc;
-               }
+       rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
+                              128);
+       if (rc) {
+               adapter->rss_flags = RSS_ENABLE_NONE;
+               return rc;
        }
 
        /* First time posting */
@@ -3124,11 +3127,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
        bool use_sriov = false;
+       int max_vfs;
 
-       if (BE3_chip(adapter) && sriov_want(adapter)) {
-               int max_vfs;
+       max_vfs = pci_sriov_get_totalvfs(pdev);
 
-               max_vfs = pci_sriov_get_totalvfs(pdev);
+       if (BE3_chip(adapter) && sriov_want(adapter)) {
                res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
                use_sriov = res->max_vfs;
        }
@@ -3159,7 +3162,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
                                           BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
        res->max_rx_qs = res->max_rss_qs + 1;
 
-       res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1;
+       if (be_physfn(adapter))
+               res->max_evt_qs = (max_vfs > 0) ?
+                                       BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
+       else
+               res->max_evt_qs = 1;
 
        res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
        if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
@@ -4205,7 +4212,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
-       init_completion(&adapter->flash_compl);
+       init_completion(&adapter->et_cmd_compl);
        pci_save_state(adapter->pdev);
        return 0;
 
index e7c8b749c5a53f969096e3f442195d88f82597d7..50bb71c663e20a010c9a4390c3d1c38726037c85 100644 (file)
@@ -428,6 +428,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(bdp, fep);
 
+       skb_tx_timestamp(skb);
+
        fep->cur_tx = bdp;
 
        if (fep->cur_tx == fep->dirty_tx)
@@ -436,8 +438,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index 895450e9bb3cfe81d22f19148b4a52d9fc14352a..ff2d806eaef71bc2a7a861a8971c228cd6856e2a 100644 (file)
@@ -718,8 +718,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        e1000_release_phy_80003es2lan(hw);
 
        /* Disable IBIST slave mode (far-end loopback) */
-       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-                                       &kum_reg_data);
+       ret_val =
+           e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                           &kum_reg_data);
+       if (ret_val)
+               return ret_val;
        kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
        e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
                                         kum_reg_data);
index 8d3945ab7334840684db42ea6eefa9bafc52c061..c30d41d6e4260d4830c82ccb1dd6b0bcec3bfa1d 100644 (file)
@@ -6174,7 +6174,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int e1000_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -6193,7 +6193,7 @@ static int e1000_resume(struct device *dev)
 
        return __e1000_resume(pdev);
 }
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_RUNTIME
 static int e1000_runtime_suspend(struct device *dev)
index da2be59505c06226b4cd79f9e8cc120945ca1d17..20e71f4ca4261f99694b04eccd3647906326239d 100644 (file)
@@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
-               if (ret_val)
+               if (ret_val) {
                        /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               msleep(usec_interval / 1000);
+                       else
+                               udelay(usec_interval);
+               }
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & BMSR_LSTATUS)
                        break;
                if (usec_interval >= 1000)
-                       mdelay(usec_interval / 1000);
+                       msleep(usec_interval / 1000);
                else
                        udelay(usec_interval);
        }
index cc06854296a379a6f5d1fac21ecf9412d94d477b..5bcc870f8367f803c309f5c28115cded7284748c 100644 (file)
@@ -6827,12 +6827,20 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
        return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
-#ifdef IXGBE_FCOE
-static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
+                             void *accel_priv)
 {
+       struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
+#ifdef IXGBE_FCOE
        struct ixgbe_adapter *adapter;
        struct ixgbe_ring_feature *f;
        int txq;
+#endif
+
+       if (fwd_adapter)
+               return skb->queue_mapping + fwd_adapter->tx_base_queue;
+
+#ifdef IXGBE_FCOE
 
        /*
         * only execute the code below if protocol is FCoE
@@ -6858,9 +6866,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
                txq -= f->indices;
 
        return txq + f->offset;
+#else
+       return __netdev_pick_tx(dev, skb);
+#endif
 }
 
-#endif
 netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                          struct ixgbe_adapter *adapter,
                          struct ixgbe_ring *tx_ring)
@@ -7629,27 +7639,11 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
        kfree(fwd_adapter);
 }
 
-static netdev_tx_t ixgbe_fwd_xmit(struct sk_buff *skb,
-                                 struct net_device *dev,
-                                 void *priv)
-{
-       struct ixgbe_fwd_adapter *fwd_adapter = priv;
-       unsigned int queue;
-       struct ixgbe_ring *tx_ring;
-
-       queue = skb->queue_mapping + fwd_adapter->tx_base_queue;
-       tx_ring = fwd_adapter->real_adapter->tx_ring[queue];
-
-       return __ixgbe_xmit_frame(skb, dev, tx_ring);
-}
-
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
        .ndo_start_xmit         = ixgbe_xmit_frame,
-#ifdef IXGBE_FCOE
        .ndo_select_queue       = ixgbe_select_queue,
-#endif
        .ndo_set_rx_mode        = ixgbe_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbe_set_mac,
@@ -7689,7 +7683,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
-       .ndo_dfwd_start_xmit    = ixgbe_fwd_xmit,
 };
 
 /**
index d6f0c0d8cf11ddb395617e2749bbf25329cae42c..72084f70adbba84c5b3e4df8f890155c2643a13b 100644 (file)
@@ -291,7 +291,9 @@ static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
        int err;
+#ifdef CONFIG_PCI_IOV
        u32 current_flags = adapter->flags;
+#endif
 
        err = ixgbe_disable_sriov(adapter);
 
index 6a6c1f76d8e04406b1c6de12820a48a7d27337fd..ec94a20d709952d1f678f69ac7778205f75e8ffe 100644 (file)
@@ -619,7 +619,8 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 }
 
 static u16
-ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     void *accel_priv)
 {
        /* we are currently only using the first queue */
        return 0;
index 7354960b583bc83b45a8aadd001c03c456912f81..c4eeb69a5beee6f4e4214746b9c958c614e64beb 100644 (file)
@@ -92,6 +92,12 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
                        if (time_is_before_jiffies(end))
                                ++timedout;
                } else {
+                       /* wait_event_timeout does not guarantee a delay of at
+                        * least one whole jiffie, so timeout must be no less
+                        * than two.
+                        */
+                       if (timeout < 2)
+                               timeout = 2;
                        wait_event_timeout(dev->smi_busy_wait,
                                           orion_mdio_smi_is_done(dev),
                                           timeout);
index f54ebd5a1702457524bf5fc6918fbdf191a5d73f..a7fcd593b2dbb397bdf3d2a810ff42f71d0806b6 100644 (file)
@@ -592,7 +592,8 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
        }
 }
 
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
index f3758de59c05f5adeb195661814ff4041b405c4a..d5758adceaa2f264b74d83e99f8091b7e1ead948 100644 (file)
@@ -714,7 +714,8 @@ int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
index 7692dfd4f262db9045f285aadc194c1713fb724a..cc68657f05368d5642b62091bc6dbec1bc00bd1c 100644 (file)
@@ -1604,13 +1604,13 @@ netxen_process_lro(struct netxen_adapter *adapter,
        u32 seq_number;
        u8 vhdr_len = 0;
 
-       if (unlikely(ring > adapter->max_rds_rings))
+       if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
 
        rds_ring = &recv_ctx->rds_rings[ring];
 
        index = netxen_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
index 631ea0ac1cd89c47bddb863c56f04c28469bd745..f2a7c7166e2408a747dd03ef0fc456ba6121486c 100644 (file)
@@ -487,6 +487,7 @@ struct qlcnic_hardware_context {
        struct qlcnic_mailbox *mailbox;
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
+       u8 lb_mode;
 };
 
 struct qlcnic_adapter_stats {
@@ -578,6 +579,8 @@ struct qlcnic_host_tx_ring {
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
        struct netdev_queue *txq;
+       /* Lock to protect Tx descriptors cleanup */
+       spinlock_t tx_clean_lock;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -808,6 +811,7 @@ struct qlcnic_mac_list_s {
 
 #define QLCNIC_ILB_MODE                0x1
 #define QLCNIC_ELB_MODE                0x2
+#define QLCNIC_LB_MODE_MASK    0x3
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
@@ -1093,7 +1097,6 @@ struct qlcnic_adapter {
        struct qlcnic_filter_hash rx_fhash;
        struct list_head vf_mc_list;
 
-       spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
        /* spinlock for catching rcv filters for eswitch traffic */
        spinlock_t rx_mac_learn_lock;
@@ -1708,6 +1711,7 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
 void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
+void qlcnic_update_stats(struct qlcnic_adapter *);
 
 /* Adapter hardware abstraction */
 struct qlcnic_hardware_ops {
index 6055d397a29edf70317299e83966aba18b6ff5dc..f776f99f79155ea42d3371b7e9aadcc901421898 100644 (file)
@@ -1684,12 +1684,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2121,6 +2115,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
index e3be2760665cd9e0781dc967a813fd1976778c3e..6b08194aa0d4900f8e29a4c5eca433f1d1709d9c 100644 (file)
@@ -167,27 +167,35 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 #define QLCNIC_TEST_LEN        ARRAY_SIZE(qlcnic_gstrings_test)
 
-static inline int qlcnic_82xx_statistics(void)
+static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_device_gstrings_stats) +
-              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
-static inline int qlcnic_83xx_statistics(void)
+static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
               ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
-              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
+              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
 static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
 {
-       if (qlcnic_82xx_check(adapter))
-               return qlcnic_82xx_statistics();
-       else if (qlcnic_83xx_check(adapter))
-               return qlcnic_83xx_statistics();
-       else
-               return -1;
+       int len = -1;
+
+       if (qlcnic_82xx_check(adapter)) {
+               len = qlcnic_82xx_statistics(adapter);
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
+       } else if (qlcnic_83xx_check(adapter)) {
+               len = qlcnic_83xx_statistics(adapter);
+       }
+
+       return len;
 }
 
 #define        QLCNIC_TX_INTR_NOT_CONFIGURED   0X78563412
@@ -920,18 +928,13 @@ static int qlcnic_eeprom_test(struct net_device *dev)
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
-       int len;
 
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        switch (sset) {
        case ETH_SS_TEST:
                return QLCNIC_TEST_LEN;
        case ETH_SS_STATS:
-               len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN;
-               if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-                   qlcnic_83xx_check(adapter))
-                       return len;
-               return qlcnic_82xx_statistics();
+               return qlcnic_dev_statistics_len(adapter);
        default:
                return -EOPNOTSUPP;
        }
@@ -1267,7 +1270,7 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
        return data;
 }
 
-static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
+void qlcnic_update_stats(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;
index e9c21e5d0ca95c7cc08df0c5f29cca2f7b473ba4..c4262c23ed7c77b009f6c5cebf233a54ebfd685b 100644 (file)
@@ -134,6 +134,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_skb_frag *buffrag;
        int i, j;
 
+       spin_lock(&tx_ring->tx_clean_lock);
+
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -157,6 +159,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
                }
                cmd_buf++;
        }
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 }
 
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
index eda6c691d8970418ae14eb67db450a87314aa882..ad1531ae3aa8f8e3cda7f56c36bb12ec46694464 100644 (file)
@@ -689,6 +689,10 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
                adapter->ahw->linkup = 0;
                netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
+               /* Do not advertise Link up if the port is in loopback mode */
+               if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode)
+                       return;
+
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
                netif_carrier_on(netdev);
@@ -778,7 +782,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_skb_frag *frag;
 
-       if (!spin_trylock(&adapter->tx_clean_lock))
+       if (!spin_trylock(&tx_ring->tx_clean_lock))
                return 1;
 
        sw_consumer = tx_ring->sw_consumer;
@@ -807,8 +811,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
                        break;
        }
 
+       tx_ring->sw_consumer = sw_consumer;
+
        if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
                smp_mb();
                if (netif_tx_queue_stopped(tx_ring->txq) &&
                    netif_carrier_ok(netdev)) {
@@ -834,7 +839,8 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
         */
        hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
        done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 
        return done;
 }
index 2c8cac0c6a55a7e9a32541c4f88e7d0ddcd5a977..550791b8fbae98404f4be790520d0c4985871802 100644 (file)
@@ -1756,7 +1756,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_sriov_vf_check(adapter))
                qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        adapter->ahw->linkup = 0;
        netif_tx_disable(netdev);
@@ -1777,7 +1776,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        for (ring = 0; ring < adapter->drv_tx_rings; ring++)
                qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */
@@ -2172,6 +2170,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
                }
                memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
                tx_ring->cmd_buf_arr = cmd_buf_arr;
+               spin_lock_init(&tx_ring->tx_clean_lock);
        }
 
        if (qlcnic_83xx_check(adapter) ||
@@ -2299,7 +2298,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        rwlock_init(&adapter->ahw->crb_lock);
        mutex_init(&adapter->ahw->mem_lock);
 
-       spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
        qlcnic_register_dcb(adapter);
@@ -2782,6 +2780,9 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               qlcnic_update_stats(adapter);
+
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
index 686f460b15022b4b2b7759ad29493a64a1f84592..024f8161d2fe1cccd0e97cc2a1eccd67371b8ab4 100644 (file)
@@ -75,7 +75,6 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
        num_vfs = sriov->num_vfs;
        max = num_vfs + 1;
        info->bit_offsets = 0xffff;
-       info->max_tx_ques = res->num_tx_queues / max;
        info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
        num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
 
@@ -86,6 +85,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_mac_filters = temp;
                info->min_tx_bw = 0;
                info->max_tx_bw = MAX_BW;
+               info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
        } else {
                id = qlcnic_sriov_func_to_index(adapter, func);
                if (id < 0)
@@ -95,6 +95,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_bw = vp->max_tx_bw;
                info->max_rx_ucast_mac_filters = num_vf_macs;
                info->max_tx_mac_filters = num_vf_macs;
+               info->max_tx_ques = QLCNIC_SINGLE_RING;
        }
 
        info->max_rx_ip_addr = res->num_destip / max;
index 8a7a23a84ac5c3b6a7b7d4979e8c5866097895a5..797b56a0efc4a4e7ab1ff5c9af1f0e50f29e9d17 100644 (file)
@@ -622,17 +622,15 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
-       if (netif_msg_hw(priv)) {
-               if (priv->dma_cap.time_stamp) {
-                       pr_debug("IEEE 1588-2002 Time Stamp supported\n");
-                       priv->adv_ts = 0;
-               }
-               if (priv->dma_cap.atime_stamp && priv->extend_desc) {
-                       pr_debug
-                           ("IEEE 1588-2008 Advanced Time Stamp supported\n");
-                       priv->adv_ts = 1;
-               }
-       }
+       priv->adv_ts = 0;
+       if (priv->dma_cap.atime_stamp && priv->extend_desc)
+               priv->adv_ts = 1;
+
+       if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
+               pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+
+       if (netif_msg_hw(priv) && priv->adv_ts)
+               pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
 
        priv->hw->ptp = &stmmac_ptp;
        priv->hwts_tx_en = 0;
index b8b0eeed0f92bb68f34e1dac22e1f072faec77ce..7680581ebe12fe58a60de42b419467e3f2f065f7 100644 (file)
@@ -56,7 +56,7 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 
        priv->hw->ptp->config_addend(priv->ioaddr, addend);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
@@ -91,7 +91,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
 
        priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
index 5120d9ce1dd4cdbdd8608550f87392d0a5f6bbb9..5330fd298705e06181b7d1a2a1557e0cea27e85c 100644 (file)
@@ -740,6 +740,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
                /* set speed_in input in case RMII mode is used in 100Mbps */
                if (phy->speed == 100)
                        mac_control |= BIT(15);
+               else if (phy->speed == 10)
+                       mac_control |= BIT(18); /* In Band mode */
 
                *link = true;
        } else {
@@ -2106,7 +2108,7 @@ static int cpsw_probe(struct platform_device *pdev)
        while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
                        if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
-                                            dev_name(priv->dev), priv)) {
+                                            dev_name(&pdev->dev), priv)) {
                                dev_err(priv->dev, "error attaching irq\n");
                                goto clean_ale_ret;
                        }
index 628b736e5ae776fcf00333bed8c355e4b518314e..0e9fb3301b1136e333cdd3d9bc62bcacc89dd4bb 100644 (file)
@@ -2080,7 +2080,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 }
 
 /* Return subqueue id on this core (one per core). */
-static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
+                                void *accel_priv)
 {
        return smp_processor_id();
 }
index 3169252613faae400904201fa5ad9f1a7decf1cf..5d78c1d08abd60fcc6bcee5dea5ab178a2a166da 100644 (file)
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+                       return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 1971411574db1c7ae2dd6549490ab6975e816cd1..61dd2447e1bb4eedb5d8e6b72abcf21e9f273afb 100644 (file)
@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCYAMGCFG:
+               memset(&yi, 0, sizeof(yi));
                yi.cfg.mask = 0xffffffff;
                yi.cfg.iobase = yp->iobase;
                yi.cfg.irq = yp->irq;
index f8135725bcf678c231cb833c3ab50487b1ec67e6..71baeb3ed905cfa9ed930ab9f7ac63c3edd206b7 100644 (file)
@@ -261,9 +261,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        struct sk_buff *skb;
 
        net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
-       if (!net) {
-               netdev_err(net, "got receive callback but net device"
-                       " not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED) {
                packet->status = NVSP_STAT_FAIL;
                return 0;
        }
@@ -435,19 +433,11 @@ static int netvsc_probe(struct hv_device *dev,
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
 
-       ret = register_netdev(net);
-       if (ret != 0) {
-               pr_err("Unable to register netdev.\n");
-               free_netdev(net);
-               goto out;
-       }
-
        /* Notify the netvsc driver of the new device */
        device_info.ring_size = ring_size;
        ret = rndis_filter_device_add(dev, &device_info);
        if (ret != 0) {
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               unregister_netdev(net);
                free_netdev(net);
                hv_set_drvdata(dev, NULL);
                return ret;
@@ -456,7 +446,13 @@ static int netvsc_probe(struct hv_device *dev,
 
        netif_carrier_on(net);
 
-out:
+       ret = register_netdev(net);
+       if (ret != 0) {
+               pr_err("Unable to register netdev.\n");
+               rndis_filter_device_remove(dev);
+               free_netdev(net);
+       }
+
        return ret;
 }
 
index acf93798dc675929394e82ffed96cd1616c3a31d..bc8faaec33f5afb0bbf7efdd88cd082122c3cc7f 100644 (file)
@@ -299,7 +299,7 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
        if (vlan->fwd_priv) {
                skb->dev = vlan->lowerdev;
-               ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
+               ret = dev_queue_xmit_accel(skb, vlan->fwd_priv);
        } else {
                ret = macvlan_queue_xmit(skb, dev);
        }
@@ -338,6 +338,8 @@ static const struct header_ops macvlan_hard_header_ops = {
        .cache_update   = eth_header_cache_update,
 };
 
+static struct rtnl_link_ops macvlan_link_ops;
+
 static int macvlan_open(struct net_device *dev)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
@@ -353,7 +355,8 @@ static int macvlan_open(struct net_device *dev)
                goto hash_add;
        }
 
-       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD &&
+           dev->rtnl_link_ops == &macvlan_link_ops) {
                vlan->fwd_priv =
                      lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
 
@@ -362,10 +365,8 @@ static int macvlan_open(struct net_device *dev)
                 */
                if (IS_ERR_OR_NULL(vlan->fwd_priv)) {
                        vlan->fwd_priv = NULL;
-               } else {
-                       dev->features &= ~NETIF_F_LLTX;
+               } else
                        return 0;
-               }
        }
 
        err = -EBUSY;
@@ -690,8 +691,18 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
                                              netdev_features_t features)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       netdev_features_t mask;
+
+       features |= NETIF_F_ALL_FOR_ALL;
+       features &= (vlan->set_features | ~MACVLAN_FEATURES);
+       mask = features;
+
+       features = netdev_increment_features(vlan->lowerdev->features,
+                                            features,
+                                            mask);
+       features |= NETIF_F_LLTX;
 
-       return features & (vlan->set_features | ~MACVLAN_FEATURES);
+       return features;
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1019,9 +1030,8 @@ static int macvlan_device_event(struct notifier_block *unused,
                break;
        case NETDEV_FEAT_CHANGE:
                list_for_each_entry(vlan, &port->vlans, list) {
-                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
                        vlan->dev->gso_max_size = dev->gso_max_size;
-                       netdev_features_change(vlan->dev);
+                       netdev_update_features(vlan->dev);
                }
                break;
        case NETDEV_UNREGISTER:
index 36c6994436b7ce7edb9ff9a0d9725c1aa09a4407..98434b84f0415ef2bfd635ba9dc4bc2f7a9ea762 100644 (file)
@@ -565,10 +565,8 @@ int phy_start_interrupts(struct phy_device *phydev)
        int err = 0;
 
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
+                       phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
index 736050d6b4516b3de85eb2c214d0464ff690d99f..b75ae5bde6734c1c70b196c00a841d84f0f984dd 100644 (file)
@@ -1647,7 +1647,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 7c8343a4f91823a579910cbcccc5827a2eb1d986..ecec8029c5e84c557374817429c29a505f699c0d 100644 (file)
@@ -348,7 +348,8 @@ unlock:
  * different rxq no. here. If we could not get rxhash, then we would
  * hope the rxq no. may help here.
  */
-static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
index 85e4a01670f06e207609299ecacd035df3e098f3..47b0f732b0b10d21a07d4567e778efcbe4a7fddb 100644 (file)
@@ -276,12 +276,12 @@ config USB_NET_CDC_MBIM
          module will be called cdc_mbim.
 
 config USB_NET_DM9601
-       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
        help
-         This option adds support for Davicom DM9601 based USB 1.1
-         10/100 Ethernet adapters.
+         This option adds support for Davicom DM9601/DM9620/DM9621A
+         based USB 10/100 Ethernet adapters.
 
 config USB_NET_SR9700
        tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
index c6867f926cffc18a981c7682e5493ae36924d988..14aa48fa8d7e5610087aee24b5eb0e493593cd83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ * Davicom DM96xx USB 10/100Mbps ethernet devices
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
+
+       /* dm9620/21a require room for 4 byte padding, even in dm9601
+        * mode, so we need +1 to be able to receive full size
+        * ethernet frames.
+        */
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
@@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
                                       gfp_t flags)
 {
-       int len;
+       int len, pad;
 
        /* format:
           b1: packet length low
@@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
           b3..n: packet data
        */
 
-       len = skb->len;
+       len = skb->len + DM_TX_OVERHEAD;
+
+       /* workaround for dm962x errata with tx fifo getting out of
+        * sync if a USB bulk transfer retry happens right after a
+        * packet with odd / maxpacket length by adding up to 3 bytes
+        * padding.
+        */
+       while ((len & 1) || !(len % dev->maxpacket))
+               len++;
 
-       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+       len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
+       pad = len - skb->len;
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
                struct sk_buff *skb2;
 
-               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
                dev_kfree_skb_any(skb);
                skb = skb2;
                if (!skb)
@@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        __skb_push(skb, DM_TX_OVERHEAD);
 
-       /* usbnet adds padding if length is a multiple of packet size
-          if so, adjust length value in header */
-       if ((skb->len % dev->maxpacket) == 0)
-               len++;
+       if (pad) {
+               memset(skb->data + skb->len, 0, pad);
+               __skb_put(skb, pad);
+       }
 
        skb->data[0] = len;
        skb->data[1] = len >> 8;
@@ -543,7 +559,7 @@ static int dm9601_link_reset(struct usbnet *dev)
 }
 
 static const struct driver_info dm9601_info = {
-       .description    = "Davicom DM9601 USB Ethernet",
+       .description    = "Davicom DM96xx USB 10/100 Ethernet",
        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
        .bind           = dm9601_bind,
        .rx_fixup       = dm9601_rx_fixup,
@@ -594,6 +610,10 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
        {},                     // END
 };
 
@@ -612,5 +632,5 @@ static struct usb_driver dm9601_driver = {
 module_usb_driver(dm9601_driver);
 
 MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 MODULE_LICENSE("GPL");
index 86292e6aaf4955c4412ead6579f74e6848bcd089..1a482344b3f507e97486059d56280dfd3f23d37c 100644 (file)
@@ -185,7 +185,6 @@ enum rx_ctrl_state{
 #define BM_REQUEST_TYPE (0xa1)
 #define B_NOTIFICATION  (0x20)
 #define W_VALUE         (0x0)
-#define W_INDEX         (0x2)
 #define W_LENGTH        (0x2)
 
 #define B_OVERRUN       (0x1<<6)
@@ -1487,6 +1486,7 @@ static void tiocmget_intr_callback(struct urb *urb)
        struct uart_icount *icount;
        struct hso_serial_state_notification *serial_state_notification;
        struct usb_device *usb;
+       int if_num;
 
        /* Sanity checks */
        if (!serial)
@@ -1495,15 +1495,24 @@ static void tiocmget_intr_callback(struct urb *urb)
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
+
+       /* tiocmget is only supported on HSO_PORT_MODEM */
        tiocmget = serial->tiocmget;
        if (!tiocmget)
                return;
+       BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
+
        usb = serial->parent->usb;
+       if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+
+       /* wIndex should be the USB interface number of the port to which the
+        * notification applies, which should always be the Modem port.
+        */
        serial_state_notification = &tiocmget->serial_state_notification;
        if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
            serial_state_notification->bNotification != B_NOTIFICATION ||
            le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-           le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+           le16_to_cpu(serial_state_notification->wIndex) != if_num ||
            le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
                dev_warn(&usb->dev,
                         "hso received invalid serial state notification\n");
index 03832d3780aa6134059dc4768bb7614d71075b82..f54637828574f6b4af868d978288d4920aa3061a 100644 (file)
@@ -117,7 +117,6 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
-       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -561,26 +560,16 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
        bool link, link_changed;
-       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
-       link = !(buf[1] & 0x20);
+       link = !(buf[1] == 0x20);
        link_changed = netif_carrier_ok(dev->net) != link;
        if (link_changed) {
-               data->link_counter++;
-               /*
-                  track link state 20 times to guard against erroneous
-                  link state changes reported sometimes by the chip
-                */
-               if (data->link_counter > 20) {
-                       data->link_counter = 0;
-                       usbnet_link_change(dev, link, 0);
-                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
-               }
-       } else
-               data->link_counter = 0;
+               usbnet_link_change(dev, link, 0);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
 }
 
 static const struct driver_info moschip_info = {
index d208f860498106013913211183baa39a37f33982..5d776447d9c33e2da56b622a2537536cf950ca0c 100644 (file)
@@ -1797,16 +1797,17 @@ static int virtnet_restore(struct virtio_device *vdev)
        if (err)
                return err;
 
-       if (netif_running(vi->dev))
+       if (netif_running(vi->dev)) {
+               for (i = 0; i < vi->curr_queue_pairs; i++)
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
+
                for (i = 0; i < vi->max_queue_pairs; i++)
                        virtnet_napi_enable(&vi->rq[i]);
+       }
 
        netif_device_attach(vi->dev);
 
-       for (i = 0; i < vi->curr_queue_pairs; i++)
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
-
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
index 249e01c5600c9010a19ca07c175867ec9e5fb91d..ed384fee76ac9ffa12eff0563864424f95ab2d01 100644 (file)
@@ -2440,7 +2440,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
index 8d78253c26cee6f459121e7e8ef5c3e0e44b8b2a..a366d6b4626f5fdd0bcf04b1d6b9c6063a70afbd 100644 (file)
@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
                }
 
-               isr = REG_READ(ah, AR_ISR_RAC);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        *masked |= ATH9K_INT_TX;
 
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                               s0_s = REG_READ(ah, AR_ISR_S0_S);
+                               s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       } else {
+                               s0_s = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0_s);
+                               s1_s = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+                               isr &= ~(AR_ISR_TXOK |
+                                        AR_ISR_TXDESC |
+                                        AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                *masked |= mask2;
        }
 
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
+       if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
                u32 s5_s;
 
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                       s5_s = REG_READ(ah, AR_ISR_S5_S);
+               } else {
+                       s5_s = REG_READ(ah, AR_ISR_S5);
+               }
+
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR_S5, s5_s);
+                       isr &= ~AR_ISR_GENTMR;
+               }
        }
 
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+               REG_WRITE(ah, AR_ISR, isr);
+               REG_READ(ah, AR_ISR);
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
        if (sync_cause) {
                ath9k_debug_sync_cause(common, sync_cause);
                fatal_int =
index 9a2657fdd9ccd4ec62f96f8a639182e2ded29fec..608d739d13782233db4271f9248c3472601b1a5f 100644 (file)
@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       if (iter_data->hw_macaddr != NULL) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               iter_data->hw_macaddr = mac;
+       }
 }
 
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_vif_iter_data iter_data;
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
-       iter_data.hw_macaddr = common->macaddr;
+       iter_data.hw_macaddr = NULL;
        memset(&iter_data.mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+       if (iter_data.hw_macaddr)
+               memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
        ath_hw_setbssidmask(common);
 }
 
@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        /*
         * Stop ANI only if there are no associated station interfaces.
index 74f452c7b1667c47a65506a077042f2b0668c3a8..21aa09e0e825df1161a4fcca3753ca08e9632558 100644 (file)
@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
index 86605027c41d6b4187c15ba874ef8fe25056676e..e6272546395a982d6d3e6e23239eaddc1bc3bf60 100644 (file)
@@ -357,21 +357,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5190, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
index c72438bb2fafd24b8e59f416d4e4311752dce941..a1b32ee9594a6b9b899caa03cea53f3d9a0ddf90 100644 (file)
@@ -2011,7 +2011,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
           (hwsim_flags & HWSIM_TX_STAT_ACK)) {
                if (skb->len >= 16) {
                        hdr = (struct ieee80211_hdr *) skb->data;
-                       mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+                       mac80211_hwsim_monitor_ack(data2->channel,
                                                   hdr->addr2);
                }
                txi->flags |= IEEE80211_TX_STAT_ACK;
index 78e8a6666cc6edad81bd87c98dcf0353af371866..8bb8988c435cf04b0280aef69d4e9d01acc24fee 100644 (file)
@@ -746,7 +746,8 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 }
 
 static u16
-mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        skb->priority = cfg80211_classify8021d(skb);
        return mwifiex_1d_to_wmm_queue[skb->priority];
index 0f494444bcd1d90b457b927d704bf77abe0592ca..5a53195d016b61da57f3198ad1f616343e1ebd3d 100644 (file)
@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        };
        int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
+       if (rtlpci->driver_is_goingto_unload)
+               return;
        /*RX NORMAL PKT */
        while (count--) {
                /*rx descriptor */
@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
         */
        set_hal_stop(rtlhal);
 
+       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->disable_interrupt(hw);
        cancel_work_sync(&rtlpriv->works.lps_change_work);
 
@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        ppsc->rfchange_inprogress = true;
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
 
-       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->hw_disable(hw);
        /* some things are not needed if firmware not available */
        if (!rtlpriv->max_fw_size)
index 08ae01b41c832d7144bdeceb70b976adaf281d4c..c47794b9d42f9bfd71d2761a48f8429a8b4633c5 100644 (file)
@@ -101,6 +101,13 @@ struct xenvif_rx_meta {
 
 #define MAX_PENDING_REQS 256
 
+/* It's possible for an skb to have a maximal number of frags
+ * but still be less than MAX_BUFFER_OFFSET in size. Thus the
+ * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * ring slot.
+ */
+#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+
 struct xenvif {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -143,13 +150,13 @@ struct xenvif {
         */
        RING_IDX rx_req_cons_peek;
 
-       /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
-        * head/fragment page uses 2 copy operations because it
-        * straddles two buffers in the frontend.
-        */
-       struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
-       struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+       /* This array is allocated seperately as it is large */
+       struct gnttab_copy *grant_copy_op;
 
+       /* We create one meta structure per ring request we consume, so
+        * the maximum number is the same as the ring size.
+        */
+       struct xenvif_rx_meta meta[XEN_NETIF_RX_RING_SIZE];
 
        u8               fe_dev_addr[6];
 
index 870f1fa583702ee4bc61d9acab3e4925a4d984e0..fff8cddfed816d3479fac57a6f91b4d827272033 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
 
 #include <xen/events.h>
 #include <asm/xen/hypercall.h>
@@ -307,6 +308,15 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        SET_NETDEV_DEV(dev, parent);
 
        vif = netdev_priv(dev);
+
+       vif->grant_copy_op = vmalloc(sizeof(struct gnttab_copy) *
+                                    MAX_GRANT_COPY_OPS);
+       if (vif->grant_copy_op == NULL) {
+               pr_warn("Could not allocate grant copy space for %s\n", name);
+               free_netdev(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
        vif->domid  = domid;
        vif->handle = handle;
        vif->can_sg = 1;
@@ -487,6 +497,7 @@ void xenvif_free(struct xenvif *vif)
 
        unregister_netdev(vif->dev);
 
+       vfree(vif->grant_copy_op);
        free_netdev(vif->dev);
 
        module_put(THIS_MODULE);
index 27bbe58dcbe7bf424fdfd54a461af847836836eb..78425554a537579b01378b99295913c1706f0b0a 100644 (file)
@@ -608,7 +608,7 @@ void xenvif_rx_action(struct xenvif *vif)
        if (!npo.copy_prod)
                return;
 
-       BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
+       BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -1209,8 +1209,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1227,8 +1229,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
@@ -1350,8 +1354,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1368,8 +1374,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
index de6f8990246fefc8aaef7c0e88e0371143ae9859..c6973f101a3e4ae9e00c604cd9e1708d1bd88485 100644 (file)
@@ -20,7 +20,7 @@ config OF_SELFTEST
        depends on OF_IRQ
        help
          This option builds in test cases for the device tree infrastructure
-         that are executed one at boot time, and the results dumped to the
+         that are executed once at boot time, and the results dumped to the
          console.
 
          If unsure, say N here, but this option is safe to enable.
index 4b9317bdb81ce85209573e6c28f86492e643962b..d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a 100644 (file)
@@ -69,14 +69,6 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                 (unsigned long long)cp, (unsigned long long)s,
                 (unsigned long long)da);
 
-       /*
-        * If the number of address cells is larger than 2 we assume the
-        * mapping doesn't specify a physical address. Rather, the address
-        * specifies an identifier that must match exactly.
-        */
-       if (na > 2 && memcmp(range, addr, na * 4) != 0)
-               return OF_BAD_ADDR;
-
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
        return da - cp;
index 2fa024b97c4350c680e384c645dc17d0fc5dc177..758b4f8b30b7d237c92b6a541f01db535d37101b 100644 (file)
@@ -922,8 +922,16 @@ void __init unflatten_device_tree(void)
  */
 void __init unflatten_and_copy_device_tree(void)
 {
-       int size = __be32_to_cpu(initial_boot_params->totalsize);
-       void *dt = early_init_dt_alloc_memory_arch(size,
+       int size;
+       void *dt;
+
+       if (!initial_boot_params) {
+               pr_warn("No valid device tree found, continuing without\n");
+               return;
+       }
+
+       size = __be32_to_cpu(initial_boot_params->totalsize);
+       dt = early_init_dt_alloc_memory_arch(size,
                __alignof__(struct boot_param_header));
 
        if (dt) {
index 786b0b47fae46802503ecbecee5719887830c44c..27212402c53247819cf4edf09e576d2cc69f3136 100644 (file)
@@ -165,7 +165,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                if (of_get_property(ipar, "interrupt-controller", NULL) !=
                                NULL) {
                        pr_debug(" -> got it !\n");
-                       of_node_put(old);
                        return 0;
                }
 
@@ -250,8 +249,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                 * Successfully parsed an interrrupt-map translation; copy new
                 * interrupt specifier into the out_irq structure
                 */
-               of_node_put(out_irq->np);
-               out_irq->np = of_node_get(newpar);
+               out_irq->np = newpar;
 
                match_array = imap - newaddrsize - newintsize;
                for (i = 0; i < newintsize; i++)
@@ -268,7 +266,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
        }
  fail:
        of_node_put(ipar);
-       of_node_put(out_irq->np);
        of_node_put(newpar);
 
        return -EINVAL;
index 0afbbbc55c81e4bca1ab5ef4f9b556fcad0dc6b1..0175041ab728b8a641194f432146fa3e1e84c646 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/interrupt.h>
@@ -39,6 +38,7 @@
 #include <linux/of_platform.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/tegra-cpuidle.h>
@@ -259,10 +259,13 @@ struct tegra_pcie {
 
        struct clk *pex_clk;
        struct clk *afi_clk;
-       struct clk *pcie_xclk;
        struct clk *pll_e;
        struct clk *cml_clk;
 
+       struct reset_control *pex_rst;
+       struct reset_control *afi_rst;
+       struct reset_control *pcie_xrst;
+
        struct tegra_msi msi;
 
        struct list_head ports;
@@ -858,7 +861,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
        pads_writel(pcie, value, PADS_CTL);
 
        /* take the PCIe interface module out of reset */
-       tegra_periph_reset_deassert(pcie->pcie_xclk);
+       reset_control_deassert(pcie->pcie_xrst);
 
        /* finally enable PCIe */
        value = afi_readl(pcie, AFI_CONFIGURATION);
@@ -891,9 +894,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
 
        /* TODO: disable and unprepare clocks? */
 
-       tegra_periph_reset_assert(pcie->pcie_xclk);
-       tegra_periph_reset_assert(pcie->afi_clk);
-       tegra_periph_reset_assert(pcie->pex_clk);
+       reset_control_assert(pcie->pcie_xrst);
+       reset_control_assert(pcie->afi_rst);
+       reset_control_assert(pcie->pex_rst);
 
        tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
 
@@ -921,9 +924,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
        const struct tegra_pcie_soc_data *soc = pcie->soc_data;
        int err;
 
-       tegra_periph_reset_assert(pcie->pcie_xclk);
-       tegra_periph_reset_assert(pcie->afi_clk);
-       tegra_periph_reset_assert(pcie->pex_clk);
+       reset_control_assert(pcie->pcie_xrst);
+       reset_control_assert(pcie->afi_rst);
+       reset_control_assert(pcie->pex_rst);
 
        tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
 
@@ -952,13 +955,14 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
        }
 
        err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
-                                               pcie->pex_clk);
+                                               pcie->pex_clk,
+                                               pcie->pex_rst);
        if (err) {
                dev_err(pcie->dev, "powerup sequence failed: %d\n", err);
                return err;
        }
 
-       tegra_periph_reset_deassert(pcie->afi_clk);
+       reset_control_deassert(pcie->afi_rst);
 
        err = clk_prepare_enable(pcie->afi_clk);
        if (err < 0) {
@@ -996,10 +1000,6 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)
        if (IS_ERR(pcie->afi_clk))
                return PTR_ERR(pcie->afi_clk);
 
-       pcie->pcie_xclk = devm_clk_get(pcie->dev, "pcie_xclk");
-       if (IS_ERR(pcie->pcie_xclk))
-               return PTR_ERR(pcie->pcie_xclk);
-
        pcie->pll_e = devm_clk_get(pcie->dev, "pll_e");
        if (IS_ERR(pcie->pll_e))
                return PTR_ERR(pcie->pll_e);
@@ -1013,6 +1013,23 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)
        return 0;
 }
 
+static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
+{
+       pcie->pex_rst = devm_reset_control_get(pcie->dev, "pex");
+       if (IS_ERR(pcie->pex_rst))
+               return PTR_ERR(pcie->pex_rst);
+
+       pcie->afi_rst = devm_reset_control_get(pcie->dev, "afi");
+       if (IS_ERR(pcie->afi_rst))
+               return PTR_ERR(pcie->afi_rst);
+
+       pcie->pcie_xrst = devm_reset_control_get(pcie->dev, "pcie_x");
+       if (IS_ERR(pcie->pcie_xrst))
+               return PTR_ERR(pcie->pcie_xrst);
+
+       return 0;
+}
+
 static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
 {
        struct platform_device *pdev = to_platform_device(pcie->dev);
@@ -1025,6 +1042,12 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
                return err;
        }
 
+       err = tegra_pcie_resets_get(pcie);
+       if (err) {
+               dev_err(&pdev->dev, "failed to get resets: %d\n", err);
+               return err;
+       }
+
        err = tegra_pcie_power_on(pcie);
        if (err) {
                dev_err(&pdev->dev, "failed to power up: %d\n", err);
index 1cf605f6767357947e9a097981caa7d7869ca2f0..e86439283a5d1911933eed185e22a50146093968 100644 (file)
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
+               if (status != AE_NOT_FOUND)
+                       acpi_handle_warn(handle,
+                               "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
        slot->flags &= (~SLOT_ENABLED);
 }
 
+static bool acpiphp_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       return adev && adev->flags.no_hotplug;
+}
+
+static bool slot_no_hotplug(struct acpiphp_slot *slot)
+{
+       struct acpiphp_func *func;
+
+       list_for_each_entry(func, &slot->funcs, sibling)
+               if (acpiphp_no_hotplug(func_to_handle(func)))
+                       return true;
+
+       return false;
+}
 
 /**
  * get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev)
                unsigned long long sta;
 
                status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-               alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
+               alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
+                       || acpiphp_no_hotplug(handle);
        }
        if (!alive) {
                u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                struct pci_dev *dev, *tmp;
 
                mutex_lock(&slot->crit_sect);
-               /* wake up all functions */
-               if (get_slot_status(slot) == ACPI_STA_ALL) {
+               if (slot_no_hotplug(slot)) {
+                       ; /* do nothing */
+               } else if (get_slot_status(slot) == ACPI_STA_ALL) {
                        /* remove stale devices if any */
                        list_for_each_entry_safe(dev, tmp, &bus->devices,
                                                 bus_list)
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..f7ebdba14bde9bc1c7e3dd702bc6e47506067ff5 100644 (file)
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+       if (!adev)
+               return;
+
+       pci_acpi_add_pm_notifier(adev, pci_dev);
+       if (!adev->wakeup.flags.valid)
                return;
 
        device_set_wakeup_capable(dev, true);
        acpi_pci_sleep_wake(pci_dev, false);
-
-       pci_acpi_add_pm_notifier(adev, pci_dev);
        if (adev->wakeup.flags.run_wake)
                device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+
+       if (!adev)
+               return;
 
-       if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
+       pci_acpi_remove_pm_notifier(adev);
+       if (adev->wakeup.flags.valid) {
                device_set_wakeup_capable(dev, false);
                device_set_run_wake(dev, false);
-               pci_acpi_remove_pm_notifier(adev);
        }
 }
 
index 5e2054afe840e9d6412a28c5250f34d1017aa7b2..85ad58c6da17233a9503650500b69579887c84bb 100644 (file)
@@ -196,6 +196,7 @@ config BATTERY_MAX17040
 config BATTERY_MAX17042
        tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
        depends on I2C
+       select REGMAP_I2C
        help
          MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
          in handheld and portable equipment. The MAX17042 is configured
index 00e6672963601754262ced9e842f31c27e07c69e..557af943b2f53d0a3ee2a280122e42e69db94c67 100644 (file)
@@ -511,6 +511,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        dev_set_drvdata(dev, psy);
        psy->dev = dev;
 
+       rc = dev_set_name(dev, "%s", psy->name);
+       if (rc)
+               goto dev_set_name_failed;
+
        INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
        rc = power_supply_check_supplies(psy);
@@ -524,10 +528,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto wakeup_init_failed;
 
-       rc = kobject_set_name(&dev->kobj, "%s", psy->name);
-       if (rc)
-               goto kobject_set_name_failed;
-
        rc = device_add(dev);
        if (rc)
                goto device_add_failed;
@@ -553,11 +553,11 @@ create_triggers_failed:
 register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
-wakeup_init_failed:
        device_del(dev);
-kobject_set_name_failed:
 device_add_failed:
+wakeup_init_failed:
 check_supplies_failed:
+dev_set_name_failed:
        put_device(dev);
 success:
        return rc;
index 3f4ca4e09a4ccc4d49fba39d64094fafe1f1fdc7..34629ea913d4eb3bd77fefee02bd301e946cf5a3 100644 (file)
@@ -942,7 +942,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                return rc;
        }
 
-       tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows);
+       tp->screen = tty3270_alloc_screen(tp->view.rows, tp->view.cols);
        if (IS_ERR(tp->screen)) {
                rc = PTR_ERR(tp->screen);
                raw3270_put_view(&tp->view);
index eb1f1ef5fa2eb69db729b6061b2d96c85aaf968b..9fc66e83c1a789b1c4046992ea1c3f6810335b43 100644 (file)
@@ -448,6 +448,7 @@ config SPI_MXS
 config SPI_TEGRA114
        tristate "NVIDIA Tegra114 SPI Controller"
        depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
+       depends on RESET_CONTROLLER
        help
          SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
          is different than the older SoCs SPI controller and also register interface
@@ -456,6 +457,7 @@ config SPI_TEGRA114
 config SPI_TEGRA20_SFLASH
        tristate "Nvidia Tegra20 Serial flash Controller"
        depends on ARCH_TEGRA || COMPILE_TEST
+       depends on RESET_CONTROLLER
        help
          SPI driver for Nvidia Tegra20 Serial flash Controller interface.
          The main usecase of this controller is to use spi flash as boot
@@ -464,6 +466,7 @@ config SPI_TEGRA20_SFLASH
 config SPI_TEGRA20_SLINK
        tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
        depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
+       depends on RESET_CONTROLLER
        help
          SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
 
index aaecfb3ebf580bd9f746458b26175da61f1bc994..c8604981a05840cf04b790b358807f5fb0add2ee 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
@@ -34,6 +33,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/reset.h>
 #include <linux/spi/spi.h>
 
 #define SPI_COMMAND1                           0x000
@@ -174,10 +174,10 @@ struct tegra_spi_data {
        spinlock_t                              lock;
 
        struct clk                              *clk;
+       struct reset_control                    *rst;
        void __iomem                            *base;
        phys_addr_t                             phys;
        unsigned                                irq;
-       int                                     dma_req_sel;
        u32                                     spi_max_frequency;
        u32                                     cur_speed;
 
@@ -600,15 +600,15 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
        dma_addr_t dma_phys;
        int ret;
        struct dma_slave_config dma_sconfig;
-       dma_cap_mask_t mask;
 
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-       dma_chan = dma_request_channel(mask, NULL, NULL);
-       if (!dma_chan) {
-               dev_err(tspi->dev,
-                       "Dma channel is not available, will try later\n");
-               return -EPROBE_DEFER;
+       dma_chan = dma_request_slave_channel_reason(tspi->dev,
+                                       dma_to_memory ? "rx" : "tx");
+       if (IS_ERR(dma_chan)) {
+               ret = PTR_ERR(dma_chan);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(tspi->dev,
+                               "Dma channel is not available: %d\n", ret);
+               return ret;
        }
 
        dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size,
@@ -619,7 +619,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
                return -ENOMEM;
        }
 
-       dma_sconfig.slave_id = tspi->dma_req_sel;
        if (dma_to_memory) {
                dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
                dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -918,9 +917,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
                        tspi->status_reg);
                dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
                        tspi->command1_reg, tspi->dma_control_reg);
-               tegra_periph_reset_assert(tspi->clk);
+               reset_control_assert(tspi->rst);
                udelay(2);
-               tegra_periph_reset_deassert(tspi->clk);
+               reset_control_deassert(tspi->rst);
                complete(&tspi->xfer_completion);
                goto exit;
        }
@@ -990,9 +989,9 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
                        tspi->status_reg);
                dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
                        tspi->command1_reg, tspi->dma_control_reg);
-               tegra_periph_reset_assert(tspi->clk);
+               reset_control_assert(tspi->rst);
                udelay(2);
-               tegra_periph_reset_deassert(tspi->clk);
+               reset_control_deassert(tspi->rst);
                complete(&tspi->xfer_completion);
                spin_unlock_irqrestore(&tspi->lock, flags);
                return IRQ_HANDLED;
@@ -1054,11 +1053,6 @@ static void tegra_spi_parse_dt(struct platform_device *pdev,
        struct tegra_spi_data *tspi)
 {
        struct device_node *np = pdev->dev.of_node;
-       u32 of_dma[2];
-
-       if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
-                               of_dma, 2) >= 0)
-               tspi->dma_req_sel = of_dma[1];
 
        if (of_property_read_u32(np, "spi-max-frequency",
                                &tspi->spi_max_frequency))
@@ -1127,25 +1121,25 @@ static int tegra_spi_probe(struct platform_device *pdev)
                goto exit_free_irq;
        }
 
+       tspi->rst = devm_reset_control_get(&pdev->dev, "spi");
+       if (IS_ERR(tspi->rst)) {
+               dev_err(&pdev->dev, "can not get reset\n");
+               ret = PTR_ERR(tspi->rst);
+               goto exit_free_irq;
+       }
+
        tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
        tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
 
-       if (tspi->dma_req_sel) {
-               ret = tegra_spi_init_dma_param(tspi, true);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret);
-                       goto exit_free_irq;
-               }
-
-               ret = tegra_spi_init_dma_param(tspi, false);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret);
-                       goto exit_rx_dma_free;
-               }
-               tspi->max_buf_size = tspi->dma_buf_size;
-               init_completion(&tspi->tx_dma_complete);
-               init_completion(&tspi->rx_dma_complete);
-       }
+       ret = tegra_spi_init_dma_param(tspi, true);
+       if (ret < 0)
+               goto exit_free_irq;
+       ret = tegra_spi_init_dma_param(tspi, false);
+       if (ret < 0)
+               goto exit_rx_dma_free;
+       tspi->max_buf_size = tspi->dma_buf_size;
+       init_completion(&tspi->tx_dma_complete);
+       init_completion(&tspi->rx_dma_complete);
 
        init_completion(&tspi->xfer_completion);
 
index 4dc8e8129459b3eaa4bb18744e33dcbd578b0da2..e6f382b338184b4cb98b5a1b40bd0964a3ff463d 100644 (file)
@@ -32,8 +32,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/reset.h>
 #include <linux/spi/spi.h>
-#include <linux/clk/tegra.h>
 
 #define SPI_COMMAND                            0x000
 #define SPI_GO                                 BIT(30)
@@ -118,6 +118,7 @@ struct tegra_sflash_data {
        spinlock_t                              lock;
 
        struct clk                              *clk;
+       struct reset_control                    *rst;
        void __iomem                            *base;
        unsigned                                irq;
        u32                                     spi_max_frequency;
@@ -389,9 +390,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd)
                dev_err(tsd->dev,
                        "CpuXfer 0x%08x:0x%08x\n", tsd->command_reg,
                                tsd->dma_control_reg);
-               tegra_periph_reset_assert(tsd->clk);
+               reset_control_assert(tsd->rst);
                udelay(2);
-               tegra_periph_reset_deassert(tsd->clk);
+               reset_control_deassert(tsd->rst);
                complete(&tsd->xfer_completion);
                goto exit;
        }
@@ -505,6 +506,13 @@ static int tegra_sflash_probe(struct platform_device *pdev)
                goto exit_free_irq;
        }
 
+       tsd->rst = devm_reset_control_get(&pdev->dev, "spi");
+       if (IS_ERR(tsd->rst)) {
+               dev_err(&pdev->dev, "can not get reset\n");
+               ret = PTR_ERR(tsd->rst);
+               goto exit_free_irq;
+       }
+
        init_completion(&tsd->xfer_completion);
        pm_runtime_enable(&pdev->dev);
        if (!pm_runtime_enabled(&pdev->dev)) {
@@ -520,9 +528,9 @@ static int tegra_sflash_probe(struct platform_device *pdev)
        }
 
        /* Reset controller */
-       tegra_periph_reset_assert(tsd->clk);
+       reset_control_assert(tsd->rst);
        udelay(2);
-       tegra_periph_reset_deassert(tsd->clk);
+       reset_control_deassert(tsd->rst);
 
        tsd->def_command_reg  = SPI_M_S | SPI_CS_SW;
        tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
index e66715ba37ed680811d7a53eb08e1b66979994c7..a728bb82090fa5a956b68eca4f5c613c346a2a5f 100644 (file)
@@ -33,8 +33,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/reset.h>
 #include <linux/spi/spi.h>
-#include <linux/clk/tegra.h>
 
 #define SLINK_COMMAND                  0x000
 #define SLINK_BIT_LENGTH(x)            (((x) & 0x1f) << 0)
@@ -167,10 +167,10 @@ struct tegra_slink_data {
        spinlock_t                              lock;
 
        struct clk                              *clk;
+       struct reset_control                    *rst;
        void __iomem                            *base;
        phys_addr_t                             phys;
        unsigned                                irq;
-       int                                     dma_req_sel;
        u32                                     spi_max_frequency;
        u32                                     cur_speed;
 
@@ -629,15 +629,15 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi,
        dma_addr_t dma_phys;
        int ret;
        struct dma_slave_config dma_sconfig;
-       dma_cap_mask_t mask;
 
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-       dma_chan = dma_request_channel(mask, NULL, NULL);
-       if (!dma_chan) {
-               dev_err(tspi->dev,
-                       "Dma channel is not available, will try later\n");
-               return -EPROBE_DEFER;
+       dma_chan = dma_request_slave_channel_reason(tspi->dev,
+                                               dma_to_memory ? "rx" : "tx");
+       if (IS_ERR(dma_chan)) {
+               ret = PTR_ERR(dma_chan);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(tspi->dev,
+                               "Dma channel is not available: %d\n", ret);
+               return ret;
        }
 
        dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size,
@@ -648,7 +648,6 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi,
                return -ENOMEM;
        }
 
-       dma_sconfig.slave_id = tspi->dma_req_sel;
        if (dma_to_memory) {
                dma_sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
                dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -884,9 +883,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi)
                dev_err(tspi->dev,
                        "CpuXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
                                tspi->command2_reg, tspi->dma_control_reg);
-               tegra_periph_reset_assert(tspi->clk);
+               reset_control_assert(tspi->rst);
                udelay(2);
-               tegra_periph_reset_deassert(tspi->clk);
+               reset_control_deassert(tspi->rst);
                complete(&tspi->xfer_completion);
                goto exit;
        }
@@ -957,9 +956,9 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_slink_data *tspi)
                dev_err(tspi->dev,
                        "DmaXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
                                tspi->command2_reg, tspi->dma_control_reg);
-               tegra_periph_reset_assert(tspi->clk);
+               reset_control_assert(tspi->rst);
                udelay(2);
-               tegra_periph_reset_deassert(tspi->clk);
+               reset_control_assert(tspi->rst);
                complete(&tspi->xfer_completion);
                spin_unlock_irqrestore(&tspi->lock, flags);
                return IRQ_HANDLED;
@@ -1020,11 +1019,6 @@ static irqreturn_t tegra_slink_isr(int irq, void *context_data)
 static void tegra_slink_parse_dt(struct tegra_slink_data *tspi)
 {
        struct device_node *np = tspi->dev->of_node;
-       u32 of_dma[2];
-
-       if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
-                               of_dma, 2) >= 0)
-               tspi->dma_req_sel = of_dma[1];
 
        if (of_property_read_u32(np, "spi-max-frequency",
                                        &tspi->spi_max_frequency))
@@ -1118,25 +1112,25 @@ static int tegra_slink_probe(struct platform_device *pdev)
                goto exit_free_irq;
        }
 
+       tspi->rst = devm_reset_control_get(&pdev->dev, "spi");
+       if (IS_ERR(tspi->rst)) {
+               dev_err(&pdev->dev, "can not get reset\n");
+               ret = PTR_ERR(tspi->rst);
+               goto exit_free_irq;
+       }
+
        tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
        tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
 
-       if (tspi->dma_req_sel) {
-               ret = tegra_slink_init_dma_param(tspi, true);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret);
-                       goto exit_free_irq;
-               }
-
-               ret = tegra_slink_init_dma_param(tspi, false);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret);
-                       goto exit_rx_dma_free;
-               }
-               tspi->max_buf_size = tspi->dma_buf_size;
-               init_completion(&tspi->tx_dma_complete);
-               init_completion(&tspi->rx_dma_complete);
-       }
+       ret = tegra_slink_init_dma_param(tspi, true);
+       if (ret < 0)
+               goto exit_free_irq;
+       ret = tegra_slink_init_dma_param(tspi, false);
+       if (ret < 0)
+               goto exit_rx_dma_free;
+       tspi->max_buf_size = tspi->dma_buf_size;
+       init_completion(&tspi->tx_dma_complete);
+       init_completion(&tspi->rx_dma_complete);
 
        init_completion(&tspi->xfer_completion);
 
index 53fee2f9a498866c6a19d3d6c3ca1d078fd7206e..8dfdd2732bdc329b3865c010d0afdb8e1e248337 100644 (file)
@@ -39,7 +39,8 @@ static INT bcm_close(struct net_device *dev)
        return 0;
 }
 
-static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
index 96e4eee344ef602174acec2ce27cf57bfb0ce128..09ef5fb8bae6f9cb4b99f936b2fcb52739f9edd9 100644 (file)
@@ -448,6 +448,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
                goto err_vblank;
        }
 
+       platform_set_drvdata(drm->platformdev, drm);
        mutex_unlock(&imxdrm->mutex);
        return 0;
 
@@ -848,7 +849,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&imx_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index 235d2b1ec593c4dfba7a83c4eb5fd0f578e0c5c4..eedffed17e391d3243443c443ff9338bf494c440 100644 (file)
@@ -306,7 +306,8 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
        return NETDEV_TX_OK;
 }
 
-static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb)
+static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        return (u16)smp_processor_id();
 }
index 49ea76b3435dcd19b9a9f8bbbfb561a92b0a53fe..986870593b0cd2241d9fbd3cb66ce1ac0a5aaf64 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
-#include <linux/clk/tegra.h>
 
 #include "nvec.h"
 
@@ -734,9 +733,9 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec)
 
        clk_prepare_enable(nvec->i2c_clk);
 
-       tegra_periph_reset_assert(nvec->i2c_clk);
+       reset_control_assert(nvec->rst);
        udelay(2);
-       tegra_periph_reset_deassert(nvec->i2c_clk);
+       reset_control_deassert(nvec->rst);
 
        val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN |
            (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
@@ -837,6 +836,12 @@ static int tegra_nvec_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       nvec->rst = devm_reset_control_get(&pdev->dev, "i2c");
+       if (IS_ERR(nvec->rst)) {
+               dev_err(nvec->dev, "failed to get controller reset\n");
+               return PTR_ERR(nvec->rst);
+       }
+
        nvec->base = base;
        nvec->irq = res->start;
        nvec->i2c_clk = i2c_clk;
index e880518935fb016bbf15ef8495c64527489be8ef..e271375053faa01729e1a91f096a4491e148dba0 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
+#include <linux/reset.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
@@ -109,7 +110,8 @@ struct nvec_msg {
  * @irq: The IRQ of the I2C device
  * @i2c_addr: The address of the I2C slave
  * @base: The base of the memory mapped region of the I2C device
- * @clk: The clock of the I2C device
+ * @i2c_clk: The clock of the I2C device
+ * @rst: The reset of the I2C device
  * @notifier_list: Notifiers to be called on received messages, see
  *                 nvec_register_notifier()
  * @rx_data: Received messages that have to be processed
@@ -139,6 +141,7 @@ struct nvec_chip {
        int i2c_addr;
        void __iomem *base;
        struct clk *i2c_clk;
+       struct reset_control *rst;
        struct atomic_notifier_head notifier_list;
        struct list_head rx_data, tx_data;
        struct notifier_block nvec_status_notifier;
index 17659bb04befc24fabded5439be74aba9fdcb5d1..dd69e344e4099c852ffd0bd5ef11ef859a0e274c 100644 (file)
@@ -652,7 +652,8 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
        return dscp >> 5;
 }
 
-static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
index dfe79ccc4fb3c66f473604c2ac867b181e6e7e00..d5c2a287b7e760728d0c38e58d08fb2361c670ee 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/of_device.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_core.h>
@@ -44,8 +45,6 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
-#include <linux/clk/tegra.h>
-
 #define TEGRA_UART_TYPE                                "TEGRA_UART"
 #define TX_EMPTY_STATUS                                (UART_LSR_TEMT | UART_LSR_THRE)
 #define BYTES_TO_ALIGN(x)                      ((unsigned long)(x) & 0x3)
@@ -103,6 +102,7 @@ struct tegra_uart_port {
        const struct tegra_uart_chip_data       *cdata;
 
        struct clk                              *uart_clk;
+       struct reset_control                    *rst;
        unsigned int                            current_baud;
 
        /* Register shadow */
@@ -120,7 +120,6 @@ struct tegra_uart_port {
        bool                                    rx_timeout;
        int                                     rx_in_progress;
        int                                     symb_bit;
-       int                                     dma_req_sel;
 
        struct dma_chan                         *rx_dma_chan;
        struct dma_chan                         *tx_dma_chan;
@@ -832,9 +831,9 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
        clk_prepare_enable(tup->uart_clk);
 
        /* Reset the UART controller to clear all previous status.*/
-       tegra_periph_reset_assert(tup->uart_clk);
+       reset_control_assert(tup->rst);
        udelay(10);
-       tegra_periph_reset_deassert(tup->uart_clk);
+       reset_control_deassert(tup->rst);
 
        tup->rx_in_progress = 0;
        tup->tx_in_progress = 0;
@@ -910,15 +909,14 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
        dma_addr_t dma_phys;
        int ret;
        struct dma_slave_config dma_sconfig;
-       dma_cap_mask_t mask;
 
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-       dma_chan = dma_request_channel(mask, NULL, NULL);
-       if (!dma_chan) {
+       dma_chan = dma_request_slave_channel_reason(tup->uport.dev,
+                                               dma_to_memory ? "rx" : "tx");
+       if (IS_ERR(dma_chan)) {
+               ret = PTR_ERR(dma_chan);
                dev_err(tup->uport.dev,
-                       "Dma channel is not available, will try later\n");
-               return -EPROBE_DEFER;
+                       "DMA channel alloc failed: %d\n", ret);
+               return ret;
        }
 
        if (dma_to_memory) {
@@ -938,7 +936,6 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
                dma_buf = tup->uport.state->xmit.buf;
        }
 
-       dma_sconfig.slave_id = tup->dma_req_sel;
        if (dma_to_memory) {
                dma_sconfig.src_addr = tup->uport.mapbase;
                dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
@@ -1222,17 +1219,8 @@ static int tegra_uart_parse_dt(struct platform_device *pdev,
        struct tegra_uart_port *tup)
 {
        struct device_node *np = pdev->dev.of_node;
-       u32 of_dma[2];
        int port;
 
-       if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
-                               of_dma, 2) >= 0) {
-               tup->dma_req_sel = of_dma[1];
-       } else {
-               dev_err(&pdev->dev, "missing dma requestor in device tree\n");
-               return -EINVAL;
-       }
-
        port = of_alias_get_id(np, "serial");
        if (port < 0) {
                dev_err(&pdev->dev, "failed to get alias id, errno %d\n", port);
@@ -1320,6 +1308,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
                return PTR_ERR(tup->uart_clk);
        }
 
+       tup->rst = devm_reset_control_get(&pdev->dev, "serial");
+       if (IS_ERR(tup->rst)) {
+               dev_err(&pdev->dev, "Couldn't get the reset\n");
+               return PTR_ERR(tup->rst);
+       }
+
        u->iotype = UPIO_MEM32;
        u->irq = platform_get_irq(pdev, 0);
        u->regshift = 2;
index b9fd0396011e54b79405cbac891540a6cd4c8964..6f7e23dd1417815204d4f4e7258bbae2689acefb 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
@@ -29,6 +28,7 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
@@ -62,6 +62,7 @@ static int (*orig_hub_control)(struct usb_hcd *hcd,
 struct tegra_ehci_hcd {
        struct tegra_usb_phy *phy;
        struct clk *clk;
+       struct reset_control *rst;
        int port_resuming;
        bool needs_double_reset;
        enum tegra_usb_phy_port_speed port_speed;
@@ -385,13 +386,20 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto cleanup_hcd_create;
        }
 
+       tegra->rst = devm_reset_control_get(&pdev->dev, "usb");
+       if (IS_ERR(tegra->rst)) {
+               dev_err(&pdev->dev, "Can't get ehci reset\n");
+               err = PTR_ERR(tegra->rst);
+               goto cleanup_hcd_create;
+       }
+
        err = clk_prepare_enable(tegra->clk);
        if (err)
                goto cleanup_hcd_create;
 
-       tegra_periph_reset_assert(tegra->clk);
+       reset_control_assert(tegra->rst);
        udelay(1);
-       tegra_periph_reset_deassert(tegra->clk);
+       reset_control_deassert(tegra->rst);
 
        u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
        if (IS_ERR(u_phy)) {
index 010d19105ebc4b9651eaf7c53bfd40a90bf36322..e296967a3abb69880e8afa97e31dc55a08a599ad 100644 (file)
@@ -1577,10 +1577,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
 static int do_unregister_framebuffer(struct fb_info *fb_info);
 
 #define VGA_FB_PHYS 0xA0000
-static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
-                                    const char *name, bool primary)
+static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
+                                             const char *name, bool primary)
 {
-       int i;
+       int i, ret;
 
        /* check all firmware fbs and kick off if the base addr overlaps */
        for (i = 0 ; i < FB_MAX; i++) {
@@ -1599,22 +1599,29 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
                        printk(KERN_INFO "fb: conflicting fb hw usage "
                               "%s vs %s - removing generic driver\n",
                               name, registered_fb[i]->fix.id);
-                       do_unregister_framebuffer(registered_fb[i]);
+                       ret = do_unregister_framebuffer(registered_fb[i]);
+                       if (ret)
+                               return ret;
                }
        }
+
+       return 0;
 }
 
 static int do_register_framebuffer(struct fb_info *fb_info)
 {
-       int i;
+       int i, ret;
        struct fb_event event;
        struct fb_videomode mode;
 
        if (fb_check_foreignness(fb_info))
                return -ENOSYS;
 
-       do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
-                                        fb_is_primary_device(fb_info));
+       ret = do_remove_conflicting_framebuffers(fb_info->apertures,
+                                                fb_info->fix.id,
+                                                fb_is_primary_device(fb_info));
+       if (ret)
+               return ret;
 
        if (num_registered_fb == FB_MAX)
                return -ENXIO;
@@ -1739,12 +1746,16 @@ int unlink_framebuffer(struct fb_info *fb_info)
 }
 EXPORT_SYMBOL(unlink_framebuffer);
 
-void remove_conflicting_framebuffers(struct apertures_struct *a,
-                                    const char *name, bool primary)
+int remove_conflicting_framebuffers(struct apertures_struct *a,
+                                   const char *name, bool primary)
 {
+       int ret;
+
        mutex_lock(&registration_lock);
-       do_remove_conflicting_framebuffers(a, name, primary);
+       ret = do_remove_conflicting_framebuffers(a, name, primary);
        mutex_unlock(&registration_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
index aa3397620342d20beba92abc732845273d3663ca..2c29db6a247e4788256461100bed11ac79648d26 100644 (file)
@@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
 extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-               const unsigned char *path,
-               struct cifs_sb_info *cifs_sb, unsigned int xid);
+extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                             struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr,
+                             const unsigned char *path);
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
index 124aa0230c1b8738edb8d04ca5d764f0a6cc5b12..d707edb6b852695f0de3993c9ef9cd12a3f909f3 100644 (file)
@@ -4010,7 +4010,7 @@ QFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4179,7 +4179,7 @@ UnixQFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4263,7 +4263,7 @@ UnixQPathInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
index 11ff5f116b20e663bf5e0428a940b437d9b232aa..a514e0a65f69b5936fbd60934b33938666f70dd0 100644 (file)
@@ -193,7 +193,7 @@ check_name(struct dentry *direntry)
 static int
 cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
               struct tcon_link *tlink, unsigned oflags, umode_t mode,
-              __u32 *oplock, struct cifs_fid *fid, int *created)
+              __u32 *oplock, struct cifs_fid *fid)
 {
        int rc = -ENOENT;
        int create_options = CREATE_NOT_DIR;
@@ -349,7 +349,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
                                .device = 0,
                };
 
-               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -480,13 +479,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
        cifs_add_pending_open(&fid, tlink, &open);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, opened);
+                           &oplock, &fid);
 
        if (rc) {
                cifs_del_pending_open(&open);
                goto out;
        }
 
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               *opened |= FILE_CREATED;
+
        rc = finish_open(file, direntry, generic_file_open, opened);
        if (rc) {
                if (server->ops->close)
@@ -529,7 +531,6 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        struct TCP_Server_Info *server;
        struct cifs_fid fid;
        __u32 oplock;
-       int created = FILE_CREATED;
 
        cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n",
                 inode, direntry->d_name.name, direntry);
@@ -546,7 +547,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                server->ops->new_lease_key(&fid);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, &created);
+                           &oplock, &fid);
        if (!rc && server->ops->close)
                server->ops->close(xid, tcon, &fid);
 
index 36f9ebb93ceba676c363cdf7b973f3936a9dde8f..49719b8228e58bd44b373fd4b39d844be9e2043b 100644 (file)
@@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                              full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
@@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                          full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
index cc0234710ddbb780cae5037b717a93d8a7d3d54d..92aee08483a52e100011fb05e1fcfc5255b340ac 100644 (file)
@@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
 
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                  const unsigned char *path)
 {
-       int rc = 0;
+       int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
-       struct cifs_tcon *ptcon;
 
        if (!CIFSCouldBeMFSymlink(fattr))
                /* it's not a symlink */
                return 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!buf)
+               return -ENOMEM;
 
-       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
-       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
-               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
-                                                &bytes_read, cifs_sb, xid);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
+                                               &bytes_read, cifs_sb, xid);
        else
-               goto out;
+               rc = -ENOSYS;
 
-       if (rc != 0)
+       if (rc)
                goto out;
 
        if (bytes_read == 0) /* not a symlink */
index 8b5e2584c840903bc9aeffab1a31aa0a2149b595..af903128891cfa0365f7fac36ba8fc052cc584a4 100644 (file)
@@ -1907,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                        }
                }
        }
-       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
-               tep = tf.file->private_data;
-               mutex_lock_nested(&tep->mtx, 1);
-       }
 
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
index 4410cc3d6ee2cc817f947e09475e565cebb07211..3384dc4bed4034921beffb84783327024e4cf22e 100644 (file)
@@ -4218,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         */
        map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
        newex.ee_block = cpu_to_le32(map->m_lblk);
-       cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk);
+       cluster_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
index b7fc035a6943cc40f649f1cca7be5858fbcf1cbc..73f3e4ee403793e1ae39c75b5d652f64c6a4b52a 100644 (file)
@@ -986,6 +986,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       struct address_space *mapping = inode->i_mapping;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int rv;
@@ -1006,6 +1007,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
        if (rv != 1)
                goto out; /* dio not valid, fall back to buffered i/o */
 
+       /*
+        * Now since we are holding a deferred (CW) lock at this point, you
+        * might be wondering why this is ever needed. There is a case however
+        * where we've granted a deferred local lock against a cached exclusive
+        * glock. That is ok provided all granted local locks are deferred, but
+        * it also means that it is possible to encounter pages which are
+        * cached and possibly also mapped. So here we check for that and sort
+        * them out ahead of the dio. The glock state machine will take care of
+        * everything else.
+        *
+        * If in fact the cached glock state (gl->gl_state) is deferred (CW) in
+        * the first place, mapping->nr_pages will always be zero.
+        */
+       if (mapping->nrpages) {
+               loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
+               loff_t len = iov_length(iov, nr_segs);
+               loff_t end = PAGE_ALIGN(offset + len) - 1;
+
+               rv = 0;
+               if (len == 0)
+                       goto out;
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len);
+               rv = filemap_write_and_wait_range(mapping, lstart, end);
+               if (rv)
+                       return rv;
+               truncate_inode_pages_range(mapping, lstart, end);
+       }
+
        rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, gfs2_get_block_direct,
                                  NULL, NULL, 0);
index c8420f7e4db604da3663da61c5ae4556b6439783..6f7a47c052592145d7601c0e9ab0341c4dd8c4d7 100644 (file)
@@ -1655,6 +1655,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
        struct task_struct *gh_owner = NULL;
        char flags_buf[32];
 
+       rcu_read_lock();
        if (gh->gh_owner_pid)
                gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
        gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
@@ -1664,6 +1665,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
                       gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
                       gh_owner ? gh_owner->comm : "(ended)",
                       (void *)gh->gh_ip);
+       rcu_read_unlock();
        return 0;
 }
 
index db908f697139cfffbca462d3a7528e13139576b5..f88dcd92501098e4a9bca28724da34e8df5a0154 100644 (file)
@@ -192,8 +192,11 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
        if (ip && !S_ISREG(ip->i_inode.i_mode))
                ip = NULL;
-       if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
-               unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+       if (ip) {
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+               inode_dio_wait(&ip->i_inode);
+       }
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
@@ -410,6 +413,9 @@ static int inode_go_lock(struct gfs2_holder *gh)
                        return error;
        }
 
+       if (gh->gh_state != LM_ST_DEFERRED)
+               inode_dio_wait(&ip->i_inode);
+
        if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
            (gl->gl_state == LM_ST_EXCLUSIVE) &&
            (gh->gh_state == LM_ST_EXCLUSIVE)) {
index 610613fb65b552dccfdf9853ac96d2f667bd36d4..9dcb9777a5f80eb32bcfce88aca3a8026776f047 100644 (file)
@@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct buffer_head *bh = bd->bd_bh;
        struct gfs2_glock *gl = bd->bd_gl;
 
-       gfs2_remove_from_ail(bd);
-       bd->bd_bh = NULL;
        bh->b_private = NULL;
        bd->bd_blkno = bh->b_blocknr;
+       gfs2_remove_from_ail(bd); /* drops ref on bh */
+       bd->bd_bh = NULL;
        bd->bd_ops = &gfs2_revoke_lops;
        sdp->sd_log_num_revoke++;
        atomic_inc(&gl->gl_revokes);
index 932415050540e2a1bdefc6d957e68ef7a0d82d01..52f177be3bf861309ed2439d33da7617bba8dba8 100644 (file)
@@ -258,6 +258,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
        struct address_space *mapping = bh->b_page->mapping;
        struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
        struct gfs2_bufdata *bd = bh->b_private;
+       int was_pinned = 0;
 
        if (test_clear_buffer_pinned(bh)) {
                trace_gfs2_pin(bd, 0);
@@ -273,12 +274,16 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
                        tr->tr_num_databuf_rm++;
                }
                tr->tr_touched = 1;
+               was_pinned = 1;
                brelse(bh);
        }
        if (bd) {
                spin_lock(&sdp->sd_ail_lock);
                if (bd->bd_tr) {
                        gfs2_trans_add_revoke(sdp, bd);
+               } else if (was_pinned) {
+                       bh->b_private = NULL;
+                       kmem_cache_free(gfs2_bufdata_cachep, bd);
                }
                spin_unlock(&sdp->sd_ail_lock);
        }
index 82303b4749582cd3c00d402a9f42b9972b1de677..52fa88314f5cdf8ef98ed95e44791a5065cbfccd 100644 (file)
@@ -1366,8 +1366,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        if (IS_ERR(s))
                goto error_bdev;
 
-       if (s->s_root)
+       if (s->s_root) {
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  blkdev_put() acquires
+                * bd_mutex and can't be called under s_umount.  Drop
+                * s_umount temporarily.  This is safe as we're
+                * holding an active reference.
+                */
+               up_write(&s->s_umount);
                blkdev_put(bdev, mode);
+               down_write(&s->s_umount);
+       }
 
        memset(&args, 0, sizeof(args));
        args.ar_quota = GFS2_QUOTA_DEFAULT;
index 739e0a52dedadea67eb595f4b03619ce3e3383a3..5549d69ddb45a2038ece8e24085e0f9ef6ce9984 100644 (file)
@@ -110,7 +110,7 @@ xfs_attr3_rmt_verify(
        if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
                return false;
        if (be32_to_cpu(rmt->rm_offset) +
-                               be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
+                               be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
                return false;
        if (rmt->rm_owner == 0)
                return false;
index 1394106ed22db9db61542f5183023f98ef1ca817..82e0dab46ee52cc991a7130d8f671e011eef10a3 100644 (file)
@@ -287,6 +287,7 @@ xfs_bmapi_allocate(
        INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
        queue_work(xfs_alloc_wq, &args->work);
        wait_for_completion(&done);
+       destroy_work_on_stack(&args->work);
        return args->result;
 }
 
index c602c7718421ded2f2bbe50f1e76edc39ac2b6f2..ddabed1f51c22227df9fdc1a7d050ca3b395b470 100644 (file)
@@ -169,7 +169,8 @@ struct acpi_device_flags {
        u32 ejectable:1;
        u32 power_manageable:1;
        u32 match_driver:1;
-       u32 reserved:27;
+       u32 no_hotplug:1;
+       u32 reserved:26;
 };
 
 /* File System */
@@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
 int acpi_bus_get_private_data(acpi_handle, void **);
+void acpi_bus_no_hotplug(acpi_handle handle);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
index 1d4a920ef7ff4ffea56470ef24c2e6cf8a7b0696..04086c5be930e2941f8be91cb0a47107da73ad08 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h>       /* For pte_wrprotect */
 #endif
@@ -136,7 +137,6 @@ int drm_err(const char *func, const char *format, ...);
 
 /* driver capabilities and requirements mask */
 #define DRIVER_USE_AGP     0x1
-#define DRIVER_REQUIRE_AGP 0x2
 #define DRIVER_PCI_DMA     0x8
 #define DRIVER_SG          0x10
 #define DRIVER_HAVE_DMA    0x20
@@ -180,6 +180,22 @@ int drm_err(const char *func, const char *format, ...);
 #define DRM_ERROR(fmt, ...)                            \
        drm_err(__func__, fmt, ##__VA_ARGS__)
 
+/**
+ * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_ERROR_RATELIMITED(fmt, ...)                                \
+({                                                                     \
+       static DEFINE_RATELIMIT_STATE(_rs,                              \
+                                     DEFAULT_RATELIMIT_INTERVAL,       \
+                                     DEFAULT_RATELIMIT_BURST);         \
+                                                                       \
+       if (__ratelimit(&_rs))                                          \
+               drm_err(__func__, fmt, ##__VA_ARGS__);                  \
+})
+
 #define DRM_INFO(fmt, ...)                             \
        printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
 
@@ -422,7 +438,6 @@ struct drm_file {
        struct pid *pid;
        kuid_t uid;
        drm_magic_t magic;
-       unsigned long ioctl_count;
        struct list_head lhead;
        struct drm_minor *minor;
        unsigned long lock_count;
@@ -511,7 +526,7 @@ struct drm_device_dma {
  */
 struct drm_agp_mem {
        unsigned long handle;           /**< handle */
-       DRM_AGP_MEM *memory;
+       struct agp_memory *memory;
        unsigned long bound;            /**< address */
        int pages;
        struct list_head head;
@@ -523,7 +538,7 @@ struct drm_agp_mem {
  * \sa drm_agp_init() and drm_device::agp.
  */
 struct drm_agp_head {
-       DRM_AGP_KERN agp_info;          /**< AGP device information */
+       struct agp_kern_info agp_info;          /**< AGP device information */
        struct list_head memory;
        unsigned long mode;             /**< AGP mode */
        struct agp_bridge_data *bridge;
@@ -606,13 +621,6 @@ struct drm_ati_pcigart_info {
        int table_size;
 };
 
-/**
- * GEM specific mm private for tracking GEM objects
- */
-struct drm_gem_mm {
-       struct drm_vma_offset_manager vma_manager;
-};
-
 /**
  * This structure defines the drm_mm memory object, which will be used by the
  * DRM for its buffer objects.
@@ -750,10 +758,6 @@ struct drm_bus {
        int (*set_unique)(struct drm_device *dev, struct drm_master *master,
                          struct drm_unique *unique);
        int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p);
-       /* hooks that are for PCI */
-       int (*agp_init)(struct drm_device *dev);
-       void (*agp_destroy)(struct drm_device *dev);
-
 };
 
 /**
@@ -841,6 +845,7 @@ struct drm_driver {
         *
         * \param dev  DRM device.
         * \param crtc Id of the crtc to query.
+        * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
         * \param *vpos Target location for current vertical scanout position.
         * \param *hpos Target location for current horizontal scanout position.
         * \param *stime Target location for timestamp taken immediately before
@@ -863,6 +868,7 @@ struct drm_driver {
         *
         */
        int (*get_scanout_position) (struct drm_device *dev, int crtc,
+                                    unsigned int flags,
                                     int *vpos, int *hpos, ktime_t *stime,
                                     ktime_t *etime);
 
@@ -903,7 +909,7 @@ struct drm_driver {
 
        /* these have to be filled in */
 
-       irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+       irqreturn_t(*irq_handler) (int irq, void *arg);
        void (*irq_preinstall) (struct drm_device *dev);
        int (*irq_postinstall) (struct drm_device *dev);
        void (*irq_uninstall) (struct drm_device *dev);
@@ -995,8 +1001,8 @@ struct drm_driver {
        } kdriver;
        struct drm_bus *bus;
 
-       /* List of devices hanging off this driver */
-       struct list_head device_list;
+       /* List of devices hanging off this driver with stealth attach. */
+       struct list_head legacy_dev_list;
 };
 
 #define DRM_MINOR_UNASSIGNED 0
@@ -1085,7 +1091,7 @@ struct drm_vblank_crtc {
  * may contain multiple heads.
  */
 struct drm_device {
-       struct list_head driver_item;   /**< list of devices per driver */
+       struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */
        char *devname;                  /**< For /proc/interrupts */
        int if_version;                 /**< Highest interface version set */
 
@@ -1098,8 +1104,6 @@ struct drm_device {
        /** \name Usage Counters */
        /*@{ */
        int open_count;                 /**< Outstanding files open */
-       atomic_t ioctl_count;           /**< Outstanding IOCTLs pending */
-       atomic_t vma_count;             /**< Outstanding vma areas open */
        int buf_use;                    /**< Buffers in use -- cannot alloc */
        atomic_t buf_alloc;             /**< Buffer allocation in progress */
        /*@} */
@@ -1176,7 +1180,6 @@ struct drm_device {
        struct drm_sg_mem *sg;  /**< Scatter gather memory */
        unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
        void *dev_private;              /**< device private data */
-       void *mm_private;
        struct address_space *dev_mapping;
        struct drm_sigdata sigdata;        /**< For block_all_signals */
        sigset_t sigmask;
@@ -1194,6 +1197,7 @@ struct drm_device {
        /*@{ */
        struct mutex object_name_lock;
        struct idr object_name_idr;
+       struct drm_vma_offset_manager *vma_offset_manager;
        /*@} */
        int switch_power_state;
 
@@ -1268,6 +1272,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
                                /* Memory management support (drm_memory.h) */
 #include <drm/drm_memory.h>
 
+
                                /* Misc. IOCTL support (drm_ioctl.h) */
 extern int drm_irq_by_busid(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
@@ -1398,8 +1403,10 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
                                                 int crtc, int *max_error,
                                                 struct timeval *vblank_time,
                                                 unsigned flags,
-                                                struct drm_crtc *refcrtc);
-extern void drm_calc_timestamping_constants(struct drm_crtc *crtc);
+                                                const struct drm_crtc *refcrtc,
+                                                const struct drm_display_mode *mode);
+extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
+                                           const struct drm_display_mode *mode);
 
 extern bool
 drm_mode_parse_command_line_for_connector(const char *mode_option,
@@ -1461,6 +1468,30 @@ extern int drm_debugfs_create_files(const struct drm_info_list *files,
 extern int drm_debugfs_remove_files(const struct drm_info_list *files,
                                    int count, struct drm_minor *minor);
 extern int drm_debugfs_cleanup(struct drm_minor *minor);
+#else
+static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id,
+                                  struct dentry *root)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_create_files(const struct drm_info_list *files,
+                                          int count, struct dentry *root,
+                                          struct drm_minor *minor)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
+                                          int count, struct drm_minor *minor)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_cleanup(struct drm_minor *minor)
+{
+       return 0;
+}
 #endif
 
                                /* Info file support */
@@ -1645,6 +1676,7 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
 
        return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
+void drm_pci_agp_destroy(struct drm_device *dev);
 
 extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
 extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
@@ -1660,7 +1692,6 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
 
 /* platform section */
 extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
-extern void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device);
 
 /* returns true if currently okay to sleep */
 static __inline__ bool drm_can_sleep(void)
index a184eeee9c96bfb4afc4a1bc8b173a0a71fa1225..86a02188074bcec037714fdb1ea293dfb4ae3ebe 100644 (file)
 
 #if __OS_HAS_AGP
 
-void drm_free_agp(DRM_AGP_MEM * handle, int pages);
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-int drm_unbind_agp(DRM_AGP_MEM * handle);
-DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+void drm_free_agp(struct agp_memory * handle, int pages);
+int drm_bind_agp(struct agp_memory * handle, unsigned int start);
+int drm_unbind_agp(struct agp_memory * handle);
+struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
                                struct page **pages,
                                unsigned long num_pages,
                                uint32_t gtt_offset,
                                uint32_t type);
 
 struct drm_agp_head *drm_agp_init(struct drm_device *dev);
-void drm_agp_destroy(struct drm_agp_head *agp);
 void drm_agp_clear(struct drm_device *dev);
 int drm_agp_acquire(struct drm_device *dev);
 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
@@ -46,29 +45,23 @@ int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
 int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
 int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
-
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-       return drm_core_check_feature(dev, DRIVER_USE_AGP);
-}
-
 #else /* __OS_HAS_AGP */
 
-static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+static inline void drm_free_agp(struct agp_memory * handle, int pages)
 {
 }
 
-static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+static inline int drm_bind_agp(struct agp_memory * handle, unsigned int start)
 {
        return -ENODEV;
 }
 
-static inline int drm_unbind_agp(DRM_AGP_MEM * handle)
+static inline int drm_unbind_agp(struct agp_memory * handle)
 {
        return -ENODEV;
 }
 
-static inline DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
                                              struct page **pages,
                                              unsigned long num_pages,
                                              uint32_t gtt_offset,
@@ -82,10 +75,6 @@ static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)
        return NULL;
 }
 
-static inline void drm_agp_destroy(struct drm_agp_head *agp)
-{
-}
-
 static inline void drm_agp_clear(struct drm_device *dev)
 {
 }
@@ -183,12 +172,6 @@ static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
 {
        return -ENODEV;
 }
-
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-       return 0;
-}
-
 #endif /* __OS_HAS_AGP */
 
 #endif /* _DRM_AGPSUPPORT_H_ */
index f32c5cd51f4125a455a81ff60cd190c1383d31e1..e963470efd3998126f56621752cd2ba326c2131c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/idr.h>
 #include <linux/fb.h>
+#include <linux/hdmi.h>
 #include <drm/drm_mode.h>
 
 #include <drm/drm_fourcc.h>
@@ -181,6 +182,7 @@ struct drm_display_mode {
 
        int vrefresh;           /* in Hz */
        int hsync;              /* in kHz */
+       enum hdmi_picture_aspect picture_aspect_ratio;
 };
 
 static inline bool drm_mode_is_stereo(const struct drm_display_mode *mode)
@@ -447,7 +449,7 @@ struct drm_crtc {
        uint16_t *gamma_store;
 
        /* Constants needed for precise vblank and swap timestamping. */
-       s64 framedur_ns, linedur_ns, pixeldur_ns;
+       int framedur_ns, linedur_ns, pixeldur_ns;
 
        /* if you are using the helper */
        void *helper_private;
index ef6ad3a8e58e517f31624767fb1751f7ada463c5..b1388b5fe7acd7d597f6345f273ce26de61d7535 100644 (file)
@@ -120,8 +120,8 @@ struct drm_encoder_helper_funcs {
  */
 struct drm_connector_helper_funcs {
        int (*get_modes)(struct drm_connector *connector);
-       int (*mode_valid)(struct drm_connector *connector,
-                         struct drm_display_mode *mode);
+       enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+                                          struct drm_display_mode *mode);
        struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
 };
 
index a92c3754e3bbffe56c286d85bd2212f753ebe2c3..1d09050a8c001749ba26087581b93cb2de1f9153 100644 (file)
  * 1.2 formally includes both eDP and DPI definitions.
  */
 
-#define AUX_NATIVE_WRITE       0x8
-#define AUX_NATIVE_READ                0x9
-#define AUX_I2C_WRITE          0x0
-#define AUX_I2C_READ           0x1
-#define AUX_I2C_STATUS         0x2
-#define AUX_I2C_MOT            0x4
-
-#define AUX_NATIVE_REPLY_ACK   (0x0 << 4)
-#define AUX_NATIVE_REPLY_NACK  (0x1 << 4)
-#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
-#define AUX_NATIVE_REPLY_MASK  (0x3 << 4)
-
-#define AUX_I2C_REPLY_ACK      (0x0 << 6)
-#define AUX_I2C_REPLY_NACK     (0x1 << 6)
-#define AUX_I2C_REPLY_DEFER    (0x2 << 6)
-#define AUX_I2C_REPLY_MASK     (0x3 << 6)
+#define DP_AUX_I2C_WRITE               0x0
+#define DP_AUX_I2C_READ                        0x1
+#define DP_AUX_I2C_STATUS              0x2
+#define DP_AUX_I2C_MOT                 0x4
+#define DP_AUX_NATIVE_WRITE            0x8
+#define DP_AUX_NATIVE_READ             0x9
+
+#define DP_AUX_NATIVE_REPLY_ACK                (0x0 << 0)
+#define DP_AUX_NATIVE_REPLY_NACK       (0x1 << 0)
+#define DP_AUX_NATIVE_REPLY_DEFER      (0x2 << 0)
+#define DP_AUX_NATIVE_REPLY_MASK       (0x3 << 0)
+
+#define DP_AUX_I2C_REPLY_ACK           (0x0 << 2)
+#define DP_AUX_I2C_REPLY_NACK          (0x1 << 2)
+#define DP_AUX_I2C_REPLY_DEFER         (0x2 << 2)
+#define DP_AUX_I2C_REPLY_MASK          (0x3 << 2)
 
 /* AUX CH addresses */
 /* DPCD */
 
 #define DP_TEST_REQUEST                            0x218
 # define DP_TEST_LINK_TRAINING             (1 << 0)
-# define DP_TEST_LINK_PATTERN              (1 << 1)
+# define DP_TEST_LINK_VIDEO_PATTERN        (1 << 1)
 # define DP_TEST_LINK_EDID_READ                    (1 << 2)
 # define DP_TEST_LINK_PHY_TEST_PATTERN     (1 << 3) /* DPCD >= 1.1 */
+# define DP_TEST_LINK_FAUX_PATTERN         (1 << 4) /* DPCD >= 1.2 */
 
 #define DP_TEST_LINK_RATE                  0x219
 # define DP_LINK_RATE_162                  (0x6)
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
new file mode 100644 (file)
index 0000000..d32628a
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * MIPI DSI Bus
+ *
+ * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DRM_MIPI_DSI_H__
+#define __DRM_MIPI_DSI_H__
+
+#include <linux/device.h>
+
+struct mipi_dsi_host;
+struct mipi_dsi_device;
+
+/**
+ * struct mipi_dsi_msg - read/write DSI buffer
+ * @channel: virtual channel id
+ * @type: payload data type
+ * @tx_len: length of @tx_buf
+ * @tx_buf: data to be written
+ * @rx_len: length of @rx_buf
+ * @rx_buf: data to be read, or NULL
+ */
+struct mipi_dsi_msg {
+       u8 channel;
+       u8 type;
+
+       size_t tx_len;
+       const void *tx_buf;
+
+       size_t rx_len;
+       void *rx_buf;
+};
+
+/**
+ * struct mipi_dsi_host_ops - DSI bus operations
+ * @attach: attach DSI device to DSI host
+ * @detach: detach DSI device from DSI host
+ * @transfer: send and/or receive DSI packet, return number of received bytes,
+ *           or error
+ */
+struct mipi_dsi_host_ops {
+       int (*attach)(struct mipi_dsi_host *host,
+                     struct mipi_dsi_device *dsi);
+       int (*detach)(struct mipi_dsi_host *host,
+                     struct mipi_dsi_device *dsi);
+       ssize_t (*transfer)(struct mipi_dsi_host *host,
+                           struct mipi_dsi_msg *msg);
+};
+
+/**
+ * struct mipi_dsi_host - DSI host device
+ * @dev: driver model device node for this DSI host
+ * @ops: DSI host operations
+ */
+struct mipi_dsi_host {
+       struct device *dev;
+       const struct mipi_dsi_host_ops *ops;
+};
+
+int mipi_dsi_host_register(struct mipi_dsi_host *host);
+void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+
+/* DSI mode flags */
+
+/* video mode */
+#define MIPI_DSI_MODE_VIDEO            BIT(0)
+/* video burst mode */
+#define MIPI_DSI_MODE_VIDEO_BURST      BIT(1)
+/* video pulse mode */
+#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2)
+/* enable auto vertical count mode */
+#define MIPI_DSI_MODE_VIDEO_AUTO_VERT  BIT(3)
+/* enable hsync-end packets in vsync-pulse and v-porch area */
+#define MIPI_DSI_MODE_VIDEO_HSE                BIT(4)
+/* disable hfront-porch area */
+#define MIPI_DSI_MODE_VIDEO_HFP                BIT(5)
+/* disable hback-porch area */
+#define MIPI_DSI_MODE_VIDEO_HBP                BIT(6)
+/* disable hsync-active area */
+#define MIPI_DSI_MODE_VIDEO_HSA                BIT(7)
+/* flush display FIFO on vsync pulse */
+#define MIPI_DSI_MODE_VSYNC_FLUSH      BIT(8)
+/* disable EoT packets in HS mode */
+#define MIPI_DSI_MODE_EOT_PACKET       BIT(9)
+
+enum mipi_dsi_pixel_format {
+       MIPI_DSI_FMT_RGB888,
+       MIPI_DSI_FMT_RGB666,
+       MIPI_DSI_FMT_RGB666_PACKED,
+       MIPI_DSI_FMT_RGB565,
+};
+
+/**
+ * struct mipi_dsi_device - DSI peripheral device
+ * @host: DSI host for this peripheral
+ * @dev: driver model device node for this peripheral
+ * @channel: virtual channel assigned to the peripheral
+ * @format: pixel format for video mode
+ * @lanes: number of active data lanes
+ * @mode_flags: DSI operation mode related flags
+ */
+struct mipi_dsi_device {
+       struct mipi_dsi_host *host;
+       struct device dev;
+
+       unsigned int channel;
+       unsigned int lanes;
+       enum mipi_dsi_pixel_format format;
+       unsigned long mode_flags;
+};
+
+#define to_mipi_dsi_device(d) container_of(d, struct mipi_dsi_device, dev)
+
+int mipi_dsi_attach(struct mipi_dsi_device *dsi);
+int mipi_dsi_detach(struct mipi_dsi_device *dsi);
+int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel,
+                      const void *data, size_t len);
+ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel,
+                         u8 cmd, void *data, size_t len);
+
+/**
+ * struct mipi_dsi_driver - DSI driver
+ * @driver: device driver model driver
+ * @probe: callback for device binding
+ * @remove: callback for device unbinding
+ */
+struct mipi_dsi_driver {
+       struct device_driver driver;
+       int(*probe)(struct mipi_dsi_device *dsi);
+       int(*remove)(struct mipi_dsi_device *dsi);
+};
+
+#define to_mipi_dsi_driver(d) container_of(d, struct mipi_dsi_driver, driver)
+
+static inline void *mipi_dsi_get_drvdata(const struct mipi_dsi_device *dsi)
+{
+       return dev_get_drvdata(&dsi->dev);
+}
+
+static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dsi, void *data)
+{
+       dev_set_drvdata(&dsi->dev, data);
+}
+
+int mipi_dsi_driver_register(struct mipi_dsi_driver *driver);
+void mipi_dsi_driver_unregister(struct mipi_dsi_driver *driver);
+
+#define module_mipi_dsi_driver(__mipi_dsi_driver) \
+       module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \
+                       mipi_dsi_driver_unregister)
+
+#endif /* __DRM_MIPI_DSI__ */
index 815fafc6b4adb2f0acc7f4474351b6e56d30cef5..86ab99bc0ac50e560b5f31c55fd3f91231607244 100644 (file)
@@ -21,7 +21,6 @@ static inline void writeq(u64 val, void __iomem *reg)
 
 /** Current process ID */
 #define DRM_CURRENTPID                 task_pid_nr(current)
-#define DRM_SUSER(p)                   capable(CAP_SYS_ADMIN)
 #define DRM_UDELAY(d)                  udelay(d)
 /** Read a byte from a MMIO region */
 #define DRM_READ8(map, offset)         readb(((void __iomem *)(map)->handle) + (offset))
@@ -35,45 +34,12 @@ static inline void writeq(u64 val, void __iomem *reg)
 #define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
 /** Write a dword into a MMIO region */
 #define DRM_WRITE32(map, offset, val)  writel(val, ((void __iomem *)(map)->handle) + (offset))
-/** Read memory barrier */
 
 /** Read a qword from a MMIO region - be careful using these unless you really understand them */
 #define DRM_READ64(map, offset)                readq(((void __iomem *)(map)->handle) + (offset))
 /** Write a qword into a MMIO region */
 #define DRM_WRITE64(map, offset, val)  writeq(val, ((void __iomem *)(map)->handle) + (offset))
 
-#define DRM_READMEMORYBARRIER()                rmb()
-/** Write memory barrier */
-#define DRM_WRITEMEMORYBARRIER()       wmb()
-/** Read/write memory barrier */
-#define DRM_MEMORYBARRIER()            mb()
-
-/** IRQ handler arguments and return type and values */
-#define DRM_IRQ_ARGS           int irq, void *arg
-
-/** AGP types */
-#if __OS_HAS_AGP
-#define DRM_AGP_MEM            struct agp_memory
-#define DRM_AGP_KERN           struct agp_kern_info
-#else
-/* define some dummy types for non AGP supporting kernels */
-struct no_agp_kern {
-       unsigned long aper_base;
-       unsigned long aper_size;
-};
-#define DRM_AGP_MEM             int
-#define DRM_AGP_KERN            struct no_agp_kern
-#endif
-
-/** Other copying of data to kernel space */
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3)           \
-       copy_from_user(arg1, arg2, arg3)
-/** Other copying of data from kernel space */
-#define DRM_COPY_TO_USER(arg1, arg2, arg3)             \
-       copy_to_user(arg1, arg2, arg3)
-
-#define DRM_HZ HZ
-
 #define DRM_WAIT_ON( ret, queue, timeout, condition )          \
 do {                                                           \
        DECLARE_WAITQUEUE(entry, current);                      \
@@ -97,6 +63,3 @@ do {                                                          \
        __set_current_state(TASK_RUNNING);                      \
        remove_wait_queue(&(queue), &entry);                    \
 } while (0)
-
-#define DRM_WAKEUP( queue ) wake_up( queue )
-#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
new file mode 100644 (file)
index 0000000..c2ab77a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013, NVIDIA 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, sub license,
+ * 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 NON-INFRINGEMENT. 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.
+ */
+
+#ifndef __DRM_PANEL_H__
+#define __DRM_PANEL_H__
+
+#include <linux/list.h>
+
+struct drm_connector;
+struct drm_device;
+struct drm_panel;
+
+struct drm_panel_funcs {
+       int (*disable)(struct drm_panel *panel);
+       int (*enable)(struct drm_panel *panel);
+       int (*get_modes)(struct drm_panel *panel);
+};
+
+struct drm_panel {
+       struct drm_device *drm;
+       struct drm_connector *connector;
+       struct device *dev;
+
+       const struct drm_panel_funcs *funcs;
+
+       struct list_head list;
+};
+
+static inline int drm_panel_disable(struct drm_panel *panel)
+{
+       if (panel && panel->funcs && panel->funcs->disable)
+               return panel->funcs->disable(panel);
+
+       return panel ? -ENOSYS : -EINVAL;
+}
+
+static inline int drm_panel_enable(struct drm_panel *panel)
+{
+       if (panel && panel->funcs && panel->funcs->enable)
+               return panel->funcs->enable(panel);
+
+       return panel ? -ENOSYS : -EINVAL;
+}
+
+void drm_panel_init(struct drm_panel *panel);
+
+int drm_panel_add(struct drm_panel *panel);
+void drm_panel_remove(struct drm_panel *panel);
+
+int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
+int drm_panel_detach(struct drm_panel *panel);
+
+#ifdef CONFIG_OF
+struct drm_panel *of_drm_find_panel(struct device_node *np);
+#else
+static inline struct drm_panel *of_drm_find_panel(struct device_node *np)
+{
+       return NULL;
+}
+#endif
+
+#endif
index 87578c109e4869bbecf5cce3a7530a0c2fb80637..49376aec2fbb8a9e054b9605fd9de36e4cd39c5f 100644 (file)
        {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index 8639c85d61c400f4694e99ca7e1282df23f5ef66..32d34ebf0706fa8f73e793b035816fd7cfaa36a3 100644 (file)
@@ -681,6 +681,15 @@ extern int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement);
 extern int ttm_tt_swapout(struct ttm_tt *ttm,
                          struct file *persistent_swap_storage);
 
+/**
+ * ttm_tt_unpopulate - free pages from a ttm
+ *
+ * @ttm: Pointer to the ttm_tt structure
+ *
+ * Calls the driver method to free all pages from a ttm
+ */
+extern void ttm_tt_unpopulate(struct ttm_tt *ttm);
+
 /*
  * ttm_bo.c
  */
index 58b029894eb33ea32dff2ba2977546c097f2b533..0097cc03034e18b10e5ad9cdc34b9019eb821314 100644 (file)
@@ -190,13 +190,25 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,
  * @key: Hash key
  *
  * Looks up a struct ttm_base_object with the key @key.
- * Also verifies that the object is visible to the application, by
- * comparing the @tfile argument and checking the object shareable flag.
  */
 
 extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
                                                      *tfile, uint32_t key);
 
+/**
+ * ttm_base_object_lookup_for_ref
+ *
+ * @tdev: Pointer to a struct ttm_object_device.
+ * @key: Hash key
+ *
+ * Looks up a struct ttm_base_object with the key @key.
+ * This function should only be used when the struct tfile associated with the
+ * caller doesn't yet have a reference to the base object.
+ */
+
+extern struct ttm_base_object *
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
+
 /**
  * ttm_base_object_unref
  *
@@ -218,6 +230,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
  * @existed: Upon completion, indicates that an identical reference object
  * already existed, and the refcount was upped on that object instead.
  *
+ * Checks that the base object is shareable and adds a ref object to it.
+ *
  * Adding a ref object to a base object is basically like referencing the
  * base object, but a user-space application holds the reference. When the
  * file corresponding to @tfile is closed, all its reference objects are
index 614aec4179029fbbcd62407483899590d15c6c49..6d0d8d8ef31ec9cb85b7bb9ec722a052a2eff019 100644 (file)
 #define TEGRA114_CLK_I2S2 18
 #define TEGRA114_CLK_EPP 19
 /* 20 (register bit affects vi and vi_sensor) */
-#define TEGRA114_CLK_GR_2D 21
+#define TEGRA114_CLK_GR2D 21
 #define TEGRA114_CLK_USBD 22
 #define TEGRA114_CLK_ISP 23
-#define TEGRA114_CLK_GR_3D 24
+#define TEGRA114_CLK_GR3D 24
 /* 25 */
 #define TEGRA114_CLK_DISP2 26
 #define TEGRA114_CLK_DISP1 27
 #define TEGRA114_CLK_PCLK 261
 #define TEGRA114_CLK_CCLK_G 262
 #define TEGRA114_CLK_CCLK_LP 263
-/* 264 */
-/* 265 */
+#define TEGRA114_CLK_DFLL_REF 264
+#define TEGRA114_CLK_DFLL_SOC 265
 /* 266 */
 /* 267 */
 /* 268 */
diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h
new file mode 100644 (file)
index 0000000..a1116a3
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * This header provides constants for binding nvidia,tegra124-car.
+ *
+ * The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 185 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 185 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+
+/* 0 */
+/* 1 */
+/* 2 */
+#define TEGRA124_CLK_ISPB 3
+#define TEGRA124_CLK_RTC 4
+#define TEGRA124_CLK_TIMER 5
+#define TEGRA124_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+/* 8 */
+#define TEGRA124_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA124_CLK_I2S1 11
+#define TEGRA124_CLK_I2C1 12
+#define TEGRA124_CLK_NDFLASH 13
+#define TEGRA124_CLK_SDMMC1 14
+#define TEGRA124_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA124_CLK_PWM 17
+#define TEGRA124_CLK_I2S2 18
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA124_CLK_GR_2D 21
+#define TEGRA124_CLK_USBD 22
+#define TEGRA124_CLK_ISP 23
+#define TEGRA124_CLK_GR_3D 24
+/* 25 */
+#define TEGRA124_CLK_DISP2 26
+#define TEGRA124_CLK_DISP1 27
+#define TEGRA124_CLK_HOST1X 28
+#define TEGRA124_CLK_VCP 29
+#define TEGRA124_CLK_I2S0 30
+/* 31 */
+
+/* 32 */
+/* 33 */
+#define TEGRA124_CLK_APBDMA 34
+/* 35 */
+#define TEGRA124_CLK_KBC 36
+/* 37 */
+/* 38 */
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA124_CLK_KFUSE 40
+#define TEGRA124_CLK_SBC1 41
+#define TEGRA124_CLK_NOR 42
+/* 43 */
+#define TEGRA124_CLK_SBC2 44
+/* 45 */
+#define TEGRA124_CLK_SBC3 46
+#define TEGRA124_CLK_I2C5 47
+#define TEGRA124_CLK_DSIA 48
+/* 49 */
+#define TEGRA124_CLK_MIPI 50
+#define TEGRA124_CLK_HDMI 51
+#define TEGRA124_CLK_CSI 52
+/* 53 */
+#define TEGRA124_CLK_I2C2 54
+#define TEGRA124_CLK_UARTC 55
+#define TEGRA124_CLK_MIPI_CAL 56
+#define TEGRA124_CLK_EMC 57
+#define TEGRA124_CLK_USB2 58
+#define TEGRA124_CLK_USB3 59
+/* 60 */
+#define TEGRA124_CLK_VDE 61
+#define TEGRA124_CLK_BSEA 62
+#define TEGRA124_CLK_BSEV 63
+
+/* 64 */
+#define TEGRA124_CLK_UARTD 65
+#define TEGRA124_CLK_UARTE 66
+#define TEGRA124_CLK_I2C3 67
+#define TEGRA124_CLK_SBC4 68
+#define TEGRA124_CLK_SDMMC3 69
+#define TEGRA124_CLK_PCIE 70
+#define TEGRA124_CLK_OWR 71
+#define TEGRA124_CLK_AFI 72
+#define TEGRA124_CLK_CSITE 73
+/* 74 */
+/* 75 */
+#define TEGRA124_CLK_LA 76
+#define TEGRA124_CLK_TRACE 77
+#define TEGRA124_CLK_SOC_THERM 78
+#define TEGRA124_CLK_DTV 79
+#define TEGRA124_CLK_NDSPEED 80
+#define TEGRA124_CLK_I2CSLOW 81
+#define TEGRA124_CLK_DSIB 82
+#define TEGRA124_CLK_TSEC 83
+/* 84 */
+/* 85 */
+/* 86 */
+/* 87 */
+/* 88 */
+#define TEGRA124_CLK_XUSB_HOST 89
+/* 90 */
+#define TEGRA124_CLK_MSENC 91
+#define TEGRA124_CLK_CSUS 92
+/* 93 */
+/* 94 */
+/* 95 (bit affects xusb_dev and xusb_dev_src) */
+
+/* 96 */
+/* 97 */
+/* 98 */
+#define TEGRA124_CLK_MSELECT 99
+#define TEGRA124_CLK_TSENSOR 100
+#define TEGRA124_CLK_I2S3 101
+#define TEGRA124_CLK_I2S4 102
+#define TEGRA124_CLK_I2C4 103
+#define TEGRA124_CLK_SBC5 104
+#define TEGRA124_CLK_SBC6 105
+#define TEGRA124_CLK_D_AUDIO 106
+#define TEGRA124_CLK_APBIF 107
+#define TEGRA124_CLK_DAM0 108
+#define TEGRA124_CLK_DAM1 109
+#define TEGRA124_CLK_DAM2 110
+#define TEGRA124_CLK_HDA2CODEC_2X 111
+/* 112 */
+#define TEGRA124_CLK_AUDIO0_2X 113
+#define TEGRA124_CLK_AUDIO1_2X 114
+#define TEGRA124_CLK_AUDIO2_2X 115
+#define TEGRA124_CLK_AUDIO3_2X 116
+#define TEGRA124_CLK_AUDIO4_2X 117
+#define TEGRA124_CLK_SPDIF_2X 118
+#define TEGRA124_CLK_ACTMON 119
+#define TEGRA124_CLK_EXTERN1 120
+#define TEGRA124_CLK_EXTERN2 121
+#define TEGRA124_CLK_EXTERN3 122
+#define TEGRA124_CLK_SATA_OOB 123
+#define TEGRA124_CLK_SATA 124
+#define TEGRA124_CLK_HDA 125
+/* 126 */
+#define TEGRA124_CLK_SE 127
+
+#define TEGRA124_CLK_HDA2HDMI 128
+#define TEGRA124_CLK_SATA_COLD 129
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */
+/*      xusb_host_src and xusb_ss_src) */
+#define TEGRA124_CLK_CILAB 144
+#define TEGRA124_CLK_CILCD 145
+#define TEGRA124_CLK_CILE 146
+#define TEGRA124_CLK_DSIALP 147
+#define TEGRA124_CLK_DSIBLP 148
+#define TEGRA124_CLK_ENTROPY 149
+#define TEGRA124_CLK_DDS 150
+/* 151 */
+#define TEGRA124_CLK_DP2 152
+#define TEGRA124_CLK_AMX 153
+#define TEGRA124_CLK_ADX 154
+/* 155 (bit affects dfll_ref and dfll_soc) */
+#define TEGRA124_CLK_XUSB_SS 156
+/* 157 */
+/* 158 */
+/* 159 */
+
+/* 160 */
+/* 161 */
+/* 162 */
+/* 163 */
+/* 164 */
+/* 165 */
+#define TEGRA124_CLK_I2C6 166
+/* 167 */
+/* 168 */
+/* 169 */
+/* 170 */
+#define TEGRA124_CLK_VIM2_CLK 171
+/* 172 */
+/* 173 */
+/* 174 */
+/* 175 */
+#define TEGRA124_CLK_HDMI_AUDIO 176
+#define TEGRA124_CLK_CLK72MHZ 177
+#define TEGRA124_CLK_VIC03 178
+/* 179 */
+#define TEGRA124_CLK_ADX1 180
+#define TEGRA124_CLK_DPAUX 181
+#define TEGRA124_CLK_SOR0 182
+/* 183 */
+#define TEGRA124_CLK_GPU 184
+#define TEGRA124_CLK_AMX1 185
+/* 186 */
+/* 187 */
+/* 188 */
+/* 189 */
+/* 190 */
+/* 191 */
+#define TEGRA124_CLK_UARTB 192
+#define TEGRA124_CLK_VFIR 193
+#define TEGRA124_CLK_SPDIF_IN 194
+#define TEGRA124_CLK_SPDIF_OUT 195
+#define TEGRA124_CLK_VI 196
+#define TEGRA124_CLK_VI_SENSOR 197
+#define TEGRA124_CLK_FUSE 198
+#define TEGRA124_CLK_FUSE_BURN 199
+#define TEGRA124_CLK_CLK_32K 200
+#define TEGRA124_CLK_CLK_M 201
+#define TEGRA124_CLK_CLK_M_DIV2 202
+#define TEGRA124_CLK_CLK_M_DIV4 203
+#define TEGRA124_CLK_PLL_REF 204
+#define TEGRA124_CLK_PLL_C 205
+#define TEGRA124_CLK_PLL_C_OUT1 206
+#define TEGRA124_CLK_PLL_C2 207
+#define TEGRA124_CLK_PLL_C3 208
+#define TEGRA124_CLK_PLL_M 209
+#define TEGRA124_CLK_PLL_M_OUT1 210
+#define TEGRA124_CLK_PLL_P 211
+#define TEGRA124_CLK_PLL_P_OUT1 212
+#define TEGRA124_CLK_PLL_P_OUT2 213
+#define TEGRA124_CLK_PLL_P_OUT3 214
+#define TEGRA124_CLK_PLL_P_OUT4 215
+#define TEGRA124_CLK_PLL_A 216
+#define TEGRA124_CLK_PLL_A_OUT0 217
+#define TEGRA124_CLK_PLL_D 218
+#define TEGRA124_CLK_PLL_D_OUT0 219
+#define TEGRA124_CLK_PLL_D2 220
+#define TEGRA124_CLK_PLL_D2_OUT0 221
+#define TEGRA124_CLK_PLL_U 222
+#define TEGRA124_CLK_PLL_U_480M 223
+
+#define TEGRA124_CLK_PLL_U_60M 224
+#define TEGRA124_CLK_PLL_U_48M 225
+#define TEGRA124_CLK_PLL_U_12M 226
+#define TEGRA124_CLK_PLL_X 227
+#define TEGRA124_CLK_PLL_X_OUT0 228
+#define TEGRA124_CLK_PLL_RE_VCO 229
+#define TEGRA124_CLK_PLL_RE_OUT 230
+#define TEGRA124_CLK_PLL_E 231
+#define TEGRA124_CLK_SPDIF_IN_SYNC 232
+#define TEGRA124_CLK_I2S0_SYNC 233
+#define TEGRA124_CLK_I2S1_SYNC 234
+#define TEGRA124_CLK_I2S2_SYNC 235
+#define TEGRA124_CLK_I2S3_SYNC 236
+#define TEGRA124_CLK_I2S4_SYNC 237
+#define TEGRA124_CLK_VIMCLK_SYNC 238
+#define TEGRA124_CLK_AUDIO0 239
+#define TEGRA124_CLK_AUDIO1 240
+#define TEGRA124_CLK_AUDIO2 241
+#define TEGRA124_CLK_AUDIO3 242
+#define TEGRA124_CLK_AUDIO4 243
+#define TEGRA124_CLK_SPDIF 244
+#define TEGRA124_CLK_CLK_OUT_1 245
+#define TEGRA124_CLK_CLK_OUT_2 246
+#define TEGRA124_CLK_CLK_OUT_3 247
+#define TEGRA124_CLK_BLINK 248
+/* 249 */
+/* 250 */
+/* 251 */
+#define TEGRA124_CLK_XUSB_HOST_SRC 252
+#define TEGRA124_CLK_XUSB_FALCON_SRC 253
+#define TEGRA124_CLK_XUSB_FS_SRC 254
+#define TEGRA124_CLK_XUSB_SS_SRC 255
+
+#define TEGRA124_CLK_XUSB_DEV_SRC 256
+#define TEGRA124_CLK_XUSB_DEV 257
+#define TEGRA124_CLK_XUSB_HS_SRC 258
+#define TEGRA124_CLK_SCLK 259
+#define TEGRA124_CLK_HCLK 260
+#define TEGRA124_CLK_PCLK 261
+#define TEGRA124_CLK_CCLK_G 262
+#define TEGRA124_CLK_CCLK_LP 263
+#define TEGRA124_CLK_DFLL_REF 264
+#define TEGRA124_CLK_DFLL_SOC 265
+#define TEGRA124_CLK_VI_SENSOR2 266
+#define TEGRA124_CLK_PLL_P_OUT5 267
+#define TEGRA124_CLK_CML0 268
+#define TEGRA124_CLK_CML1 269
+#define TEGRA124_CLK_PLL_C4 270
+#define TEGRA124_CLK_PLL_DP 271
+#define TEGRA124_CLK_PLL_E_MUX 272
+/* 273 */
+/* 274 */
+/* 275 */
+/* 276 */
+/* 277 */
+/* 278 */
+/* 279 */
+/* 280 */
+/* 281 */
+/* 282 */
+/* 283 */
+/* 284 */
+/* 285 */
+/* 286 */
+/* 287 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA124_CLK_AUDIO0_MUX 300
+#define TEGRA124_CLK_AUDIO1_MUX 301
+#define TEGRA124_CLK_AUDIO2_MUX 302
+#define TEGRA124_CLK_AUDIO3_MUX 303
+#define TEGRA124_CLK_AUDIO4_MUX 304
+#define TEGRA124_CLK_SPDIF_MUX 305
+#define TEGRA124_CLK_CLK_OUT_1_MUX 306
+#define TEGRA124_CLK_CLK_OUT_2_MUX 307
+#define TEGRA124_CLK_CLK_OUT_3_MUX 308
+#define TEGRA124_CLK_DSIA_MUX 309
+#define TEGRA124_CLK_DSIB_MUX 310
+#define TEGRA124_CLK_SOR0_LVDS 311
+#define TEGRA124_CLK_CLK_MAX 312
+
+#endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */
index a1ae9a8fdd6c5bbb5bd0472d65791b650b660a6c..9406207cfac8715b2545a8e77ae8bc7866e838fb 100644 (file)
@@ -92,7 +92,7 @@
 #define TEGRA20_CLK_OWR 71
 #define TEGRA20_CLK_AFI 72
 #define TEGRA20_CLK_CSITE 73
-#define TEGRA20_CLK_PCIE_XCLK 74
+/* 74 */
 #define TEGRA20_CLK_AVPUCQ 75
 #define TEGRA20_CLK_LA 76
 /* 77 */
index e40fae8f9a8d7f7634330d87918ede31a3a3c78d..889e49ba0aa3de3f3b83ad27b1d0f4b12521a05a 100644 (file)
@@ -92,7 +92,7 @@
 #define TEGRA30_CLK_OWR 71
 #define TEGRA30_CLK_AFI 72
 #define TEGRA30_CLK_CSITE 73
-#define TEGRA30_CLK_PCIEX 74
+/* 74 */
 #define TEGRA30_CLK_AVPUCQ 75
 #define TEGRA30_CLK_LA 76
 /* 77 */
 /* 298 */
 /* 299 */
 #define TEGRA30_CLK_CLK_OUT_1_MUX 300
-#define TEGRA30_CLK_CLK_MAX 301
+#define TEGRA30_CLK_CLK_OUT_2_MUX 301
+#define TEGRA30_CLK_CLK_OUT_3_MUX 302
+#define TEGRA30_CLK_AUDIO0_MUX 303
+#define TEGRA30_CLK_AUDIO1_MUX 304
+#define TEGRA30_CLK_AUDIO2_MUX 305
+#define TEGRA30_CLK_AUDIO3_MUX 306
+#define TEGRA30_CLK_AUDIO4_MUX 307
+#define TEGRA30_CLK_SPDIF_MUX 308
+#define TEGRA30_CLK_CLK_MAX 309
 
 #endif /* _DT_BINDINGS_CLOCK_TEGRA30_CAR_H */
index 23a0ceee831fc4ca2e5a93abfaa951ce3fff0048..3ca9fca827a2f1299ed7eea5ca9ec908e57f2fc8 100644 (file)
@@ -120,13 +120,6 @@ static inline void tegra_cpu_clock_resume(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_TEGRA
-void tegra_periph_reset_deassert(struct clk *c);
-void tegra_periph_reset_assert(struct clk *c);
-#else
-static inline void tegra_periph_reset_deassert(struct clk *c) {}
-static inline void tegra_periph_reset_assert(struct clk *c) {}
-#endif
 void tegra_clocks_apply_init_table(void);
 
 #endif /* __LINUX_CLK_TEGRA_H_ */
index 41cf0c399288e022edf32f7e65c6f151004829d9..bae1568416f81bb5037cd2c3d1ef88ed564a28e8 100644 (file)
@@ -22,6 +22,7 @@
 #define LINUX_DMAENGINE_H
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/uio.h>
 #include <linux/bug.h>
 #include <linux/scatterlist.h>
@@ -1040,6 +1041,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                        dma_filter_fn fn, void *fn_param);
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name);
 struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
 void dma_release_channel(struct dma_chan *chan);
 #else
@@ -1063,6 +1066,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
 {
        return NULL;
 }
+static inline struct dma_chan *dma_request_slave_channel_reason(
+                                       struct device *dev, const char *name)
+{
+       return ERR_PTR(-ENODEV);
+}
 static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
                                                         const char *name)
 {
@@ -1079,6 +1087,7 @@ int dma_async_device_register(struct dma_device *device);
 void dma_async_device_unregister(struct dma_device *device);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
+struct dma_chan *dma_get_any_slave_channel(struct dma_device *device);
 struct dma_chan *net_dma_find_channel(void);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
 #define dma_request_slave_channel_compat(mask, x, y, dev, name) \
index 70c4836e4a9f8fb16dd578bbbcfa25ecfec0b129..fe6ac956550e4e099a04889e9b33bf0f9a917c2e 100644 (file)
@@ -613,8 +613,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int unlink_framebuffer(struct fb_info *fb_info);
-extern void remove_conflicting_framebuffers(struct apertures_struct *a,
-                               const char *name, bool primary);
+extern int remove_conflicting_framebuffers(struct apertures_struct *a,
+                                          const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
 extern int fb_show_logo(struct fb_info *fb_info, int rotate);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
index f5b9b87ac9a9e807513686f2b97b96ad48432810..3af847273277785332e994aedc2559db74c1623a 100644 (file)
@@ -281,4 +281,10 @@ int host1x_device_exit(struct host1x_device *device);
 int host1x_client_register(struct host1x_client *client);
 int host1x_client_unregister(struct host1x_client *client);
 
+struct tegra_mipi_device;
+
+struct tegra_mipi_device *tegra_mipi_request(struct device *device);
+void tegra_mipi_free(struct tegra_mipi_device *device);
+int tegra_mipi_calibrate(struct tegra_mipi_device *device);
+
 #endif
index d9a550bf3e8e8a770c4198bf96bb2b81e34a3b6e..ce2a1f5f9a1e0226d933d28606823239e4467526 100644 (file)
@@ -769,7 +769,8 @@ struct netdev_phys_port_id {
  *        (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX)
  *     Required can not be NULL.
  *
- * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb);
+ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
+ *                         void *accel_priv);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -990,7 +991,8 @@ struct net_device_ops {
        netdev_tx_t             (*ndo_start_xmit) (struct sk_buff *skb,
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
-                                                   struct sk_buff *skb);
+                                                   struct sk_buff *skb,
+                                                   void *accel_priv);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1529,7 +1531,8 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 }
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb);
+                                   struct sk_buff *skb,
+                                   void *accel_priv);
 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
@@ -1819,6 +1822,7 @@ int dev_close(struct net_device *dev);
 void dev_disable_lro(struct net_device *dev);
 int dev_loopback_xmit(struct sk_buff *newskb);
 int dev_queue_xmit(struct sk_buff *skb);
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
 int register_netdevice(struct net_device *dev);
 void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
 void unregister_netdevice_many(struct list_head *head);
@@ -1912,6 +1916,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+       const struct net_device *dev = skb->dev;
+
+       if (!dev->header_ops || !dev->header_ops->rebuild)
+               return 0;
+       return dev->header_ops->rebuild(skb);
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
@@ -2417,7 +2430,7 @@ int dev_change_carrier(struct net_device *, bool new_carrier);
 int dev_get_phys_port_id(struct net_device *dev,
                         struct netdev_phys_port_id *ppid);
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv);
+                       struct netdev_queue *txq);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 
 extern int             netdev_budget;
@@ -3008,6 +3021,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
        dev->gso_max_size = size;
 }
 
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+                                       int pulled_hlen, u16 mac_offset,
+                                       int mac_len)
+{
+       skb->protocol = protocol;
+       skb->encapsulation = 1;
+       skb_push(skb, pulled_hlen);
+       skb_reset_transport_header(skb);
+       skb->mac_header = mac_offset;
+       skb->network_header = skb->mac_header + mac_len;
+       skb->mac_len = mac_len;
+}
+
 static inline bool netif_is_macvlan(struct net_device *dev)
 {
        return dev->priv_flags & IFF_MACVLAN;
index 939428ad25acb506297c1726faaee83d60d047c4..8e3e66ac0a5215d221042e15e631fb2fe2fb51d1 100644 (file)
@@ -24,6 +24,11 @@ extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
+#else
+static inline int lockdep_rtnl_is_held(void)
+{
+       return 1;
+}
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
 /**
index 215b5ea1cb302c43f0e8b9532fbe3ce59ff0f612..6f69b3f914fbf94c2d6d42beea62748a29a42d08 100644 (file)
@@ -1638,6 +1638,11 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
+static inline void skb_pop_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->network_header;
+}
+
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
@@ -2526,6 +2531,10 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * Ethernet MAC Drivers should call this function in their hard_xmit()
  * function immediately before giving the sk_buff to the MAC hardware.
  *
+ * Specifically, one should make absolutely sure that this function is
+ * called before TX completion of this packet can trigger.  Otherwise
+ * the packet could potentially already be freed.
+ *
  * @skb: A socket buffer.
  */
 static inline void skb_tx_timestamp(struct sk_buff *skb)
index fd4498329c7c509b3614ad820c7c717d976afa2f..e6f2ab3014a77f80236ccd78ed50249cf20a4d22 100644 (file)
@@ -19,6 +19,7 @@
 #define _MACH_TEGRA_POWERGATE_H_
 
 struct clk;
+struct reset_control;
 
 #define TEGRA_POWERGATE_CPU    0
 #define TEGRA_POWERGATE_3D     1
@@ -37,14 +38,49 @@ struct clk;
 #define TEGRA_POWERGATE_CPU0   14
 #define TEGRA_POWERGATE_C0NC   15
 #define TEGRA_POWERGATE_C1NC   16
+#define TEGRA_POWERGATE_SOR    17
 #define TEGRA_POWERGATE_DIS    18
 #define TEGRA_POWERGATE_DISB   19
 #define TEGRA_POWERGATE_XUSBA  20
 #define TEGRA_POWERGATE_XUSBB  21
 #define TEGRA_POWERGATE_XUSBC  22
+#define TEGRA_POWERGATE_VIC    23
+#define TEGRA_POWERGATE_IRAM   24
 
 #define TEGRA_POWERGATE_3D0    TEGRA_POWERGATE_3D
 
+#define TEGRA_IO_RAIL_CSIA     0
+#define TEGRA_IO_RAIL_CSIB     1
+#define TEGRA_IO_RAIL_DSI      2
+#define TEGRA_IO_RAIL_MIPI_BIAS        3
+#define TEGRA_IO_RAIL_PEX_BIAS 4
+#define TEGRA_IO_RAIL_PEX_CLK1 5
+#define TEGRA_IO_RAIL_PEX_CLK2 6
+#define TEGRA_IO_RAIL_USB0     9
+#define TEGRA_IO_RAIL_USB1     10
+#define TEGRA_IO_RAIL_USB2     11
+#define TEGRA_IO_RAIL_USB_BIAS 12
+#define TEGRA_IO_RAIL_NAND     13
+#define TEGRA_IO_RAIL_UART     14
+#define TEGRA_IO_RAIL_BB       15
+#define TEGRA_IO_RAIL_AUDIO    17
+#define TEGRA_IO_RAIL_HSIC     19
+#define TEGRA_IO_RAIL_COMP     22
+#define TEGRA_IO_RAIL_HDMI     28
+#define TEGRA_IO_RAIL_PEX_CNTRL        32
+#define TEGRA_IO_RAIL_SDMMC1   33
+#define TEGRA_IO_RAIL_SDMMC3   34
+#define TEGRA_IO_RAIL_SDMMC4   35
+#define TEGRA_IO_RAIL_CAM      36
+#define TEGRA_IO_RAIL_RES      37
+#define TEGRA_IO_RAIL_HV       38
+#define TEGRA_IO_RAIL_DSIB     39
+#define TEGRA_IO_RAIL_DSIC     40
+#define TEGRA_IO_RAIL_DSID     41
+#define TEGRA_IO_RAIL_CSIE     44
+#define TEGRA_IO_RAIL_LVDS     57
+#define TEGRA_IO_RAIL_SYS_DDC  58
+
 #ifdef CONFIG_ARCH_TEGRA
 int tegra_powergate_is_powered(int id);
 int tegra_powergate_power_on(int id);
@@ -52,7 +88,11 @@ int tegra_powergate_power_off(int id);
 int tegra_powergate_remove_clamping(int id);
 
 /* Must be called with clk disabled, and returns with clk enabled */
-int tegra_powergate_sequence_power_up(int id, struct clk *clk);
+int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+                                     struct reset_control *rst);
+
+int tegra_io_rail_power_on(int id);
+int tegra_io_rail_power_off(int id);
 #else
 static inline int tegra_powergate_is_powered(int id)
 {
@@ -74,7 +114,18 @@ static inline int tegra_powergate_remove_clamping(int id)
        return -ENOSYS;
 }
 
-static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk)
+static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+                                                   struct reset_control *rst);
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_io_rail_power_on(int id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_io_rail_power_off(int id)
 {
        return -ENOSYS;
 }
index 31e2de7d57c5d6c210e1b445b19551407fd31b6c..c0f0a13ed8183e58029aec1d12097aa1efb085f0 100644 (file)
 #define LLC_S_PF_IS_1(pdu)     ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
 
 #define PDU_SUPV_GET_Nr(pdu)   ((pdu->ctrl_2 & 0xFE) >> 1)
-#define PDU_GET_NEXT_Vr(sn)    (++sn & ~LLC_2_SEQ_NBR_MODULO)
+#define PDU_GET_NEXT_Vr(sn)    (((sn) + 1) & ~LLC_2_SEQ_NBR_MODULO)
 
 /* FRMR information field macros */
 
index 67b5d0068273e64ac94125861699e790a9d06e9d..0a248b323d875c08ca456d62ed46c028781e9432 100644 (file)
@@ -1046,9 +1046,6 @@ struct sctp_outq {
 
        /* Corked? */
        char cork;
-
-       /* Is this structure empty?  */
-       char empty;
 };
 
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
index 15017311f2e9f0c9c2dba9bf41c00f01763cee0f..eb73a3a39ec2fbb9a3b4aef39ff65e21af9d51b4 100644 (file)
@@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
+ * @dma_dev: If set, request DMA channel on this device rather than the DAI
+ *  device.
+ * @chan_names: If set, these custom DMA channel names will be requested at
+ *  registration time.
  * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
  * @prealloc_buffer_size: Size of the preallocated audio buffer.
  *
@@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
                        struct snd_soc_pcm_runtime *rtd,
                        struct snd_pcm_substream *substream);
        dma_filter_fn compat_filter_fn;
+       struct device *dma_dev;
+       const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
 
        const struct snd_pcm_hardware *pcm_hardware;
        unsigned int prealloc_buffer_size;
@@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
        unsigned int flags);
 void snd_dmaengine_pcm_unregister(struct device *dev);
 
+int devm_snd_dmaengine_pcm_register(struct device *dev,
+       const struct snd_dmaengine_pcm_config *config,
+       unsigned int flags);
+
 int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct dma_slave_config *slave_config);
index 9b24d65fed72b9d06843cba89ebeeabff07fb71f..3c9a833992e872f095a4373d6cb5e33602129acc 100644 (file)
@@ -181,7 +181,6 @@ enum drm_map_type {
        _DRM_AGP = 3,             /**< AGP/GART */
        _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
        _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
-       _DRM_GEM = 6,             /**< GEM object (obsolete) */
 };
 
 /**
index 3a4e97bd860771b6ad8e3b5d026a35200fcad4d3..52aed893710a126e979cec558239e55c76cb2c59 100644 (file)
@@ -222,6 +222,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_SET_CACHING       0x2f
 #define DRM_I915_GEM_GET_CACHING       0x30
 #define DRM_I915_REG_READ              0x31
+#define DRM_I915_GET_RESET_STATS       0x32
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -271,6 +272,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE      DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
 #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
 #define DRM_IOCTL_I915_REG_READ                        DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
+#define DRM_IOCTL_I915_GET_RESET_STATS         DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -1030,4 +1032,21 @@ struct drm_i915_reg_read {
        __u64 offset;
        __u64 val; /* Return value */
 };
+
+struct drm_i915_reset_stats {
+       __u32 ctx_id;
+       __u32 flags;
+
+       /* All resets since boot/module reload, for all contexts */
+       __u32 reset_count;
+
+       /* Number of batches lost when active in GPU, for this context */
+       __u32 batch_active;
+
+       /* Number of batches lost pending for execution, for this context */
+       __u32 batch_pending;
+
+       __u32 pad;
+};
+
 #endif /* _UAPI_I915_DRM_H_ */
index 2f3f7ea8c77b8a653b0972302ead53319f13e5fc..d9ea3a73afe2d2a4df80ebebd23316df5077c346 100644 (file)
@@ -983,6 +983,10 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_CP_DMA_COMPUTE  0x17
 /* CIK macrotile mode array */
 #define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY   0x18
+/* query the number of render backends */
+#define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
+/* max engine clock - needed for OpenCL */
+#define RADEON_INFO_MAX_SCLK           0x1a
 
 
 struct drm_radeon_info {
index f854ca4a1372812dda6f71c20c8a84b3bdcfc19a..9971c560ed9aa42dc841e76b9586f05e25225d96 100644 (file)
 #ifndef __VMWGFX_DRM_H__
 #define __VMWGFX_DRM_H__
 
+#ifndef __KERNEL__
+#include <drm.h>
+#endif
+
 #define DRM_VMW_MAX_SURFACE_FACES 6
 #define DRM_VMW_MAX_MIP_LEVELS 24
 
 #define DRM_VMW_PRESENT              18
 #define DRM_VMW_PRESENT_READBACK     19
 #define DRM_VMW_UPDATE_LAYOUT        20
+#define DRM_VMW_CREATE_SHADER        21
+#define DRM_VMW_UNREF_SHADER         22
+#define DRM_VMW_GB_SURFACE_CREATE    23
+#define DRM_VMW_GB_SURFACE_REF       24
+#define DRM_VMW_SYNCCPU              25
 
 /*************************************************************************/
 /**
@@ -76,6 +85,8 @@
 #define DRM_VMW_PARAM_MAX_FB_SIZE      5
 #define DRM_VMW_PARAM_FIFO_HW_VERSION  6
 #define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
+#define DRM_VMW_PARAM_3D_CAPS_SIZE     8
+#define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
 
 /**
  * struct drm_vmw_getparam_arg
@@ -788,4 +799,253 @@ struct drm_vmw_update_layout_arg {
        uint64_t rects;
 };
 
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_SHADER - Create shader
+ *
+ * Creates a shader and optionally binds it to a dma buffer containing
+ * the shader byte-code.
+ */
+
+/**
+ * enum drm_vmw_shader_type - Shader types
+ */
+enum drm_vmw_shader_type {
+       drm_vmw_shader_type_vs = 0,
+       drm_vmw_shader_type_ps,
+       drm_vmw_shader_type_gs
+};
+
+
+/**
+ * struct drm_vmw_shader_create_arg
+ *
+ * @shader_type: Shader type of the shader to create.
+ * @size: Size of the byte-code in bytes.
+ * where the shader byte-code starts
+ * @buffer_handle: Buffer handle identifying the buffer containing the
+ * shader byte-code
+ * @shader_handle: On successful completion contains a handle that
+ * can be used to subsequently identify the shader.
+ * @offset: Offset in bytes into the buffer given by @buffer_handle,
+ *
+ * Input / Output argument to the DRM_VMW_CREATE_SHADER Ioctl.
+ */
+struct drm_vmw_shader_create_arg {
+       enum drm_vmw_shader_type shader_type;
+       uint32_t size;
+       uint32_t buffer_handle;
+       uint32_t shader_handle;
+       uint64_t offset;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_SHADER - Unreferences a shader
+ *
+ * Destroys a user-space reference to a shader, optionally destroying
+ * it.
+ */
+
+/**
+ * struct drm_vmw_shader_arg
+ *
+ * @handle: Handle identifying the shader to destroy.
+ *
+ * Input argument to the DRM_VMW_UNREF_SHADER ioctl.
+ */
+struct drm_vmw_shader_arg {
+       uint32_t handle;
+       uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GB_SURFACE_CREATE - Create a host guest-backed surface.
+ *
+ * Allocates a surface handle and queues a create surface command
+ * for the host on the first use of the surface. The surface ID can
+ * be used as the surface ID in commands referencing the surface.
+ */
+
+/**
+ * enum drm_vmw_surface_flags
+ *
+ * @drm_vmw_surface_flag_shareable:     Whether the surface is shareable
+ * @drm_vmw_surface_flag_scanout:       Whether the surface is a scanout
+ *                                      surface.
+ * @drm_vmw_surface_flag_create_buffer: Create a backup buffer if none is
+ *                                      given.
+ */
+enum drm_vmw_surface_flags {
+       drm_vmw_surface_flag_shareable = (1 << 0),
+       drm_vmw_surface_flag_scanout = (1 << 1),
+       drm_vmw_surface_flag_create_buffer = (1 << 2)
+};
+
+/**
+ * struct drm_vmw_gb_surface_create_req
+ *
+ * @svga3d_flags:     SVGA3d surface flags for the device.
+ * @format:           SVGA3d format.
+ * @mip_level:        Number of mip levels for all faces.
+ * @drm_surface_flags Flags as described above.
+ * @multisample_count Future use. Set to 0.
+ * @autogen_filter    Future use. Set to 0.
+ * @buffer_handle     Buffer handle of backup buffer. SVGA3D_INVALID_ID
+ *                    if none.
+ * @base_size         Size of the base mip level for all faces.
+ *
+ * Input argument to the  DRM_VMW_GB_SURFACE_CREATE Ioctl.
+ * Part of output argument for the DRM_VMW_GB_SURFACE_REF Ioctl.
+ */
+struct drm_vmw_gb_surface_create_req {
+       uint32_t svga3d_flags;
+       uint32_t format;
+       uint32_t mip_levels;
+       enum drm_vmw_surface_flags drm_surface_flags;
+       uint32_t multisample_count;
+       uint32_t autogen_filter;
+       uint32_t buffer_handle;
+       uint32_t pad64;
+       struct drm_vmw_size base_size;
+};
+
+/**
+ * struct drm_vmw_gb_surface_create_rep
+ *
+ * @handle:            Surface handle.
+ * @backup_size:       Size of backup buffers for this surface.
+ * @buffer_handle:     Handle of backup buffer. SVGA3D_INVALID_ID if none.
+ * @buffer_size:       Actual size of the buffer identified by
+ *                     @buffer_handle
+ * @buffer_map_handle: Offset into device address space for the buffer
+ *                     identified by @buffer_handle.
+ *
+ * Part of output argument for the DRM_VMW_GB_SURFACE_REF ioctl.
+ * Output argument for the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+struct drm_vmw_gb_surface_create_rep {
+       uint32_t handle;
+       uint32_t backup_size;
+       uint32_t buffer_handle;
+       uint32_t buffer_size;
+       uint64_t buffer_map_handle;
+};
+
+/**
+ * union drm_vmw_gb_surface_create_arg
+ *
+ * @req: Input argument as described above.
+ * @rep: Output argument as described above.
+ *
+ * Argument to the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+union drm_vmw_gb_surface_create_arg {
+       struct drm_vmw_gb_surface_create_rep rep;
+       struct drm_vmw_gb_surface_create_req req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GB_SURFACE_REF - Reference a host surface.
+ *
+ * Puts a reference on a host surface with a given handle, as previously
+ * returned by the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ * A reference will make sure the surface isn't destroyed while we hold
+ * it and will allow the calling client to use the surface handle in
+ * the command stream.
+ *
+ * On successful return, the Ioctl returns the surface information given
+ * to and returned from the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+
+/**
+ * struct drm_vmw_gb_surface_reference_arg
+ *
+ * @creq: The data used as input when the surface was created, as described
+ *        above at "struct drm_vmw_gb_surface_create_req"
+ * @crep: Additional data output when the surface was created, as described
+ *        above at "struct drm_vmw_gb_surface_create_rep"
+ *
+ * Output Argument to the DRM_VMW_GB_SURFACE_REF ioctl.
+ */
+struct drm_vmw_gb_surface_ref_rep {
+       struct drm_vmw_gb_surface_create_req creq;
+       struct drm_vmw_gb_surface_create_rep crep;
+};
+
+/**
+ * union drm_vmw_gb_surface_reference_arg
+ *
+ * @req: Input data as described above at "struct drm_vmw_surface_arg"
+ * @rep: Output data as described above at "struct drm_vmw_gb_surface_ref_rep"
+ *
+ * Argument to the DRM_VMW_GB_SURFACE_REF Ioctl.
+ */
+union drm_vmw_gb_surface_reference_arg {
+       struct drm_vmw_gb_surface_ref_rep rep;
+       struct drm_vmw_surface_arg req;
+};
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_SYNCCPU - Sync a DMA buffer / MOB for CPU access.
+ *
+ * Idles any previously submitted GPU operations on the buffer and
+ * by default blocks command submissions that reference the buffer.
+ * If the file descriptor used to grab a blocking CPU sync is closed, the
+ * cpu sync is released.
+ * The flags argument indicates how the grab / release operation should be
+ * performed:
+ */
+
+/**
+ * enum drm_vmw_synccpu_flags - Synccpu flags:
+ *
+ * @drm_vmw_synccpu_read: Sync for read. If sync is done for read only, it's a
+ * hint to the kernel to allow command submissions that references the buffer
+ * for read-only.
+ * @drm_vmw_synccpu_write: Sync for write. Block all command submissions
+ * referencing this buffer.
+ * @drm_vmw_synccpu_dontblock: Dont wait for GPU idle, but rather return
+ * -EBUSY should the buffer be busy.
+ * @drm_vmw_synccpu_allow_cs: Allow command submission that touches the buffer
+ * while the buffer is synced for CPU. This is similar to the GEM bo idle
+ * behavior.
+ */
+enum drm_vmw_synccpu_flags {
+       drm_vmw_synccpu_read = (1 << 0),
+       drm_vmw_synccpu_write = (1 << 1),
+       drm_vmw_synccpu_dontblock = (1 << 2),
+       drm_vmw_synccpu_allow_cs = (1 << 3)
+};
+
+/**
+ * enum drm_vmw_synccpu_op - Synccpu operations:
+ *
+ * @drm_vmw_synccpu_grab:    Grab the buffer for CPU operations
+ * @drm_vmw_synccpu_release: Release a previous grab.
+ */
+enum drm_vmw_synccpu_op {
+       drm_vmw_synccpu_grab,
+       drm_vmw_synccpu_release
+};
+
+/**
+ * struct drm_vmw_synccpu_arg
+ *
+ * @op:                             The synccpu operation as described above.
+ * @handle:                 Handle identifying the buffer object.
+ * @flags:                  Flags as described above.
+ */
+struct drm_vmw_synccpu_arg {
+       enum drm_vmw_synccpu_op op;
+       enum drm_vmw_synccpu_flags flags;
+       uint32_t handle;
+       uint32_t pad64;
+};
+
 #endif
index ecc88592ecbe94acfbacd1eda9b5907a832470da..bd24470d24a2c7a3145af21094e03f67b7ce0761 100644 (file)
@@ -464,7 +464,8 @@ struct input_keymap_entry {
 #define KEY_BRIGHTNESS_ZERO    244     /* brightness off, use ambient */
 #define KEY_DISPLAY_OFF                245     /* display device to off state */
 
-#define KEY_WIMAX              246
+#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX              KEY_WWAN
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
 #define KEY_MICMUTE            248     /* Mute / unmute the microphone */
index 5bff0814776870e2974e6e436ad99f99f264e05a..bbc4d660221ac4e514e24d49ce140b25ad5364d2 100644 (file)
@@ -208,9 +208,10 @@ get_write_lock:
                if (mapping_cap_account_dirty(mapping)) {
                        unsigned long addr;
                        struct file *file = get_file(vma->vm_file);
+                       /* mmap_region may free vma; grab the info now */
+                       vm_flags = vma->vm_flags;
 
-                       addr = mmap_region(file, start, size,
-                                       vma->vm_flags, pgoff);
+                       addr = mmap_region(file, start, size, vm_flags, pgoff);
                        fput(file);
                        if (IS_ERR_VALUE(addr)) {
                                err = addr;
@@ -218,7 +219,7 @@ get_write_lock:
                                BUG_ON(addr != start);
                                err = 0;
                        }
-                       goto out;
+                       goto out_freed;
                }
                mutex_lock(&mapping->i_mmap_mutex);
                flush_dcache_mmap_lock(mapping);
@@ -253,6 +254,7 @@ get_write_lock:
 out:
        if (vma)
                vm_flags = vma->vm_flags;
+out_freed:
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index 7de1bf85f6833422e16161445b71e328fad2e1f6..95d1acb0f3d237f55f5f1d6405de5774f0f9fc6a 100644 (file)
@@ -883,9 +883,6 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                goto out_unlock;
        }
 
-       /* mmap_sem prevents this happening but warn if that changes */
-       WARN_ON(pmd_trans_migrating(pmd));
-
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1157,7 +1154,7 @@ alloc:
                new_page = NULL;
 
        if (unlikely(!new_page)) {
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
                                        address, pmd, orig_pmd, haddr);
                } else {
@@ -1184,7 +1181,7 @@ alloc:
 
        count_vm_event(THP_FAULT_ALLOC);
 
-       if (is_huge_zero_pmd(orig_pmd))
+       if (!page)
                clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
        else
                copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
@@ -1210,7 +1207,7 @@ alloc:
                page_add_new_anon_rmap(new_page, vma, haddr);
                set_pmd_at(mm, haddr, pmd, entry);
                update_mmu_cache_pmd(vma, address, pmd);
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
                        put_huge_zero_page();
                } else {
index bf5e8945714944f896e2dc79b33b75a491da4794..7f1a356153c013349ce520c7763002838c02fb76 100644 (file)
@@ -338,7 +338,7 @@ struct mem_cgroup {
 static size_t memcg_size(void)
 {
        return sizeof(struct mem_cgroup) +
-               nr_node_ids * sizeof(struct mem_cgroup_per_node);
+               nr_node_ids * sizeof(struct mem_cgroup_per_node *);
 }
 
 /* internal only representation about the status of kmem accounting. */
index db08af92c6fce92d9e0d61ca5752aa003c52c3f2..fabe55046c1d7b9638172aa8e26ecb4f3d6ed4b9 100644 (file)
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                                BUG_ON(!PageHWPoison(p));
                                return SWAP_FAIL;
                        }
+                       /*
+                        * We pinned the head page for hwpoison handling,
+                        * now we split the thp and we are interested in
+                        * the hwpoisoned raw page, so move the refcount
+                        * to it.
+                        */
+                       if (hpage != p) {
+                               put_page(hpage);
+                               get_page(p);
+                       }
                        /* THP is split, so ppage should be the real poisoned page. */
                        ppage = p;
                }
index d480cd6fc475854259bdd51021d5125dbdfbe479..192e6eebe4f240e4a8ece7cc0e10e902ff29f308 100644 (file)
@@ -133,7 +133,10 @@ static void __munlock_isolation_failed(struct page *page)
 
 /**
  * munlock_vma_page - munlock a vma page
- * @page - page to be unlocked
+ * @page - page to be unlocked, either a normal page or THP page head
+ *
+ * returns the size of the page as a page mask (0 for normal page,
+ *         HPAGE_PMD_NR - 1 for THP head page)
  *
  * called from munlock()/munmap() path with page supposedly on the LRU.
  * When we munlock a page, because the vma where we found the page is being
@@ -148,21 +151,30 @@ static void __munlock_isolation_failed(struct page *page)
  */
 unsigned int munlock_vma_page(struct page *page)
 {
-       unsigned int page_mask = 0;
+       unsigned int nr_pages;
 
        BUG_ON(!PageLocked(page));
 
        if (TestClearPageMlocked(page)) {
-               unsigned int nr_pages = hpage_nr_pages(page);
+               nr_pages = hpage_nr_pages(page);
                mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
-               page_mask = nr_pages - 1;
                if (!isolate_lru_page(page))
                        __munlock_isolated_page(page);
                else
                        __munlock_isolation_failed(page);
+       } else {
+               nr_pages = hpage_nr_pages(page);
        }
 
-       return page_mask;
+       /*
+        * Regardless of the original PageMlocked flag, we determine nr_pages
+        * after touching the flag. This leaves a possible race with a THP page
+        * split, such that a whole THP page was munlocked, but nr_pages == 1.
+        * Returning a smaller mask due to that is OK, the worst that can
+        * happen is subsequent useless scanning of the former tail pages.
+        * The NR_MLOCK accounting can however become broken.
+        */
+       return nr_pages - 1;
 }
 
 /**
@@ -286,10 +298,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
 {
        int i;
        int nr = pagevec_count(pvec);
-       int delta_munlocked = -nr;
+       int delta_munlocked;
        struct pagevec pvec_putback;
        int pgrescued = 0;
 
+       pagevec_init(&pvec_putback, 0);
+
        /* Phase 1: page isolation */
        spin_lock_irq(&zone->lru_lock);
        for (i = 0; i < nr; i++) {
@@ -318,18 +332,21 @@ skip_munlock:
                        /*
                         * We won't be munlocking this page in the next phase
                         * but we still need to release the follow_page_mask()
-                        * pin.
+                        * pin. We cannot do it under lru_lock however. If it's
+                        * the last pin, __page_cache_release would deadlock.
                         */
+                       pagevec_add(&pvec_putback, pvec->pages[i]);
                        pvec->pages[i] = NULL;
-                       put_page(page);
-                       delta_munlocked++;
                }
        }
+       delta_munlocked = -nr + pagevec_count(&pvec_putback);
        __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
        spin_unlock_irq(&zone->lru_lock);
 
+       /* Now we can release pins of pages that we are not munlocking */
+       pagevec_release(&pvec_putback);
+
        /* Phase 2: page munlock */
-       pagevec_init(&pvec_putback, 0);
        for (i = 0; i < nr; i++) {
                struct page *page = pvec->pages[i];
 
@@ -440,7 +457,8 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
 
        while (start < end) {
                struct page *page = NULL;
-               unsigned int page_mask, page_increm;
+               unsigned int page_mask;
+               unsigned long page_increm;
                struct pagevec pvec;
                struct zone *zone;
                int zoneid;
@@ -490,7 +508,9 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
                                goto next;
                        }
                }
-               page_increm = 1 + (~(start >> PAGE_SHIFT) & page_mask);
+               /* It's a bug to munlock in the middle of a THP page */
+               VM_BUG_ON((start >> PAGE_SHIFT) & page_mask);
+               page_increm = 1 + page_mask;
                start += page_increm * PAGE_SIZE;
 next:
                cond_resched();
index 762896ebfcf505348a659c83d8720b48e8b58c86..47c908f1f626a4d4a2de96b9f4a648ad386d4357 100644 (file)
@@ -530,6 +530,23 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
+                                    unsigned short type,
+                                    const void *daddr, const void *saddr,
+                                    unsigned int len)
+{
+       struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+}
+
+static const struct header_ops vlan_passthru_header_ops = {
+       .create  = vlan_passthru_hard_header,
+       .rebuild = dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static struct device_type vlan_type = {
        .name   = "vlan",
 };
@@ -573,7 +590,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->needed_headroom = real_dev->needed_headroom;
        if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
-               dev->header_ops      = real_dev->header_ops;
+               dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
                dev->header_ops      = &vlan_header_ops;
index a2b480a908723a37d47d14bd76e63628518e6561..b9c8a6eedf4537e4216f09e65f71ef72a55d4ed3 100644 (file)
@@ -307,9 +307,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
-       batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
-       batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
-       batadv_ogm_packet->header.ttl = 2;
+       batadv_ogm_packet->packet_type = BATADV_IV_OGM;
+       batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
+       batadv_ogm_packet->ttl = 2;
        batadv_ogm_packet->flags = BATADV_NO_FLAGS;
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +346,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
-       batadv_ogm_packet->header.ttl = BATADV_TTL;
+       batadv_ogm_packet->ttl = BATADV_TTL;
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -435,7 +435,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
                           fwd_str, (packet_num > 0 ? "aggregated " : ""),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
                           (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
                            "on" : "off"),
                           hard_iface->net_dev->name,
@@ -491,7 +491,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
        /* multihomed peer assumed
         * non-primary OGMs are only broadcasted on their interface
         */
-       if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
+       if ((directlink && (batadv_ogm_packet->ttl == 1)) ||
            (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
                /* FIXME: what about aggregated packets ? */
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -499,7 +499,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
                           (forw_packet->own ? "Sending own" : "Forwarding"),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->ttl,
                           forw_packet->if_incoming->net_dev->name,
                           forw_packet->if_incoming->net_dev->dev_addr);
 
@@ -572,7 +572,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 */
                if ((!directlink) &&
                    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
-                   (batadv_ogm_packet->header.ttl != 1) &&
+                   (batadv_ogm_packet->ttl != 1) &&
 
                    /* own packets originating non-primary
                     * interfaces leave only that interface
@@ -587,7 +587,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 * interface only - we still can aggregate
                 */
                if ((directlink) &&
-                   (new_bat_ogm_packet->header.ttl == 1) &&
+                   (new_bat_ogm_packet->ttl == 1) &&
                    (forw_packet->if_incoming == if_incoming) &&
 
                    /* packets from direct neighbors or
@@ -778,7 +778,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        uint16_t tvlv_len;
 
-       if (batadv_ogm_packet->header.ttl <= 1) {
+       if (batadv_ogm_packet->ttl <= 1) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
                return;
        }
@@ -798,7 +798,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
 
-       batadv_ogm_packet->header.ttl--;
+       batadv_ogm_packet->ttl--;
        memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
 
        /* apply hop penalty */
@@ -807,7 +807,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: tq: %i, ttl: %i\n",
-                  batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
+                  batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
 
        /* switch of primaries first hop flag when forwarding */
        batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -972,8 +972,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
 
        if (dup_status == BATADV_NO_DUP) {
-               orig_node->last_ttl = batadv_ogm_packet->header.ttl;
-               neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
+               orig_node->last_ttl = batadv_ogm_packet->ttl;
+               neigh_node->last_ttl = batadv_ogm_packet->ttl;
        }
 
        batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
@@ -1247,7 +1247,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * packet in an aggregation.  Here we expect that the padding
         * is always zero (or not 0x01)
         */
-       if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
+       if (batadv_ogm_packet->packet_type != BATADV_IV_OGM)
                return;
 
        /* could be changed by schedule_own_packet() */
@@ -1267,8 +1267,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                   if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
                   batadv_ogm_packet->prev_sender,
                   ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
-                  batadv_ogm_packet->header.ttl,
-                  batadv_ogm_packet->header.version, has_directlink_flag);
+                  batadv_ogm_packet->ttl,
+                  batadv_ogm_packet->version, has_directlink_flag);
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -1433,7 +1433,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * seqno and similar ttl as the non-duplicate
         */
        sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
-       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl;
        if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
                            (sameseq && similar_ttl)))
                batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
index 6c8c3934bd7b44bac8643683683c494e003f1ed2..b316a4cb6f147dbbafadb51cdccf687cef500373 100644 (file)
@@ -349,7 +349,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       switch (unicast_4addr_packet->u.header.packet_type) {
+       switch (unicast_4addr_packet->u.packet_type) {
        case BATADV_UNICAST:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within a UNICAST packet\n");
@@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                default:
                        batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
-                                  unicast_4addr_packet->u.header.packet_type);
+                                  unicast_4addr_packet->u.packet_type);
                }
                break;
        case BATADV_BCAST:
@@ -387,7 +387,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        default:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within an unknown packet type (0x%x)\n",
-                          unicast_4addr_packet->u.header.packet_type);
+                          unicast_4addr_packet->u.packet_type);
        }
 }
 
index 271d321b3a04063b4f9dfe476c7c07d9e2e50048..6ddb6145ffb564be9397728e83a4040f071c4a96 100644 (file)
@@ -355,7 +355,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
                                   skb->len + ETH_HLEN);
 
-               packet->header.ttl--;
+               packet->ttl--;
                batadv_send_skb_packet(skb, neigh_node->if_incoming,
                                       neigh_node->addr);
                ret = true;
@@ -444,9 +444,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                goto out_err;
 
        /* Create one header to be copied to all fragments */
-       frag_header.header.packet_type = BATADV_UNICAST_FRAG;
-       frag_header.header.version = BATADV_COMPAT_VERSION;
-       frag_header.header.ttl = BATADV_TTL;
+       frag_header.packet_type = BATADV_UNICAST_FRAG;
+       frag_header.version = BATADV_COMPAT_VERSION;
+       frag_header.ttl = BATADV_TTL;
        frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
        frag_header.reserved = 0;
        frag_header.no = 0;
index 29ae4efe3543e4bfc6ff013b9c97628b9e395209..130cc3217e2b0fb091dccfad6a4f41d4b0c9dbc9 100644 (file)
@@ -194,7 +194,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                goto free_skb;
        }
 
-       if (icmp_header->header.packet_type != BATADV_ICMP) {
+       if (icmp_header->packet_type != BATADV_ICMP) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
                len = -EINVAL;
@@ -243,9 +243,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 
        icmp_header->uid = socket_client->index;
 
-       if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
+       if (icmp_header->version != BATADV_COMPAT_VERSION) {
                icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-               icmp_header->header.version = BATADV_COMPAT_VERSION;
+               icmp_header->version = BATADV_COMPAT_VERSION;
                batadv_socket_add_packet(socket_client, icmp_header,
                                         packet_len);
                goto free_skb;
index c51a5e568f0a80c08beb4ded5b34b1aff8d5cfdf..1511f64a6ceaae34d26860cd4642cde71c5af9a0 100644 (file)
@@ -383,17 +383,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
+       if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
+                          batadv_ogm_packet->version);
                goto err_free;
        }
 
        /* all receive handlers return whether they received or reused
         * the supplied skb. if not, we have to free the skb.
         */
-       idx = batadv_ogm_packet->header.packet_type;
+       idx = batadv_ogm_packet->packet_type;
        ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
        if (ret == NET_RX_DROP)
@@ -426,8 +426,8 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
 
        /* broadcast packet */
        batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -1119,9 +1119,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
        skb_reserve(skb, ETH_HLEN);
        tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
        unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
-       unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
-       unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_tvlv_packet->header.ttl = BATADV_TTL;
+       unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
+       unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
+       unicast_tvlv_packet->ttl = BATADV_TTL;
        unicast_tvlv_packet->reserved = 0;
        unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
        unicast_tvlv_packet->align = 0;
index 351e199bc0afff37aa9c1a4b3f40201956dfde91..511d7e1eea38b6d6e13247df0f8d4399deea8382 100644 (file)
@@ -722,7 +722,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
 {
        if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
                return false;
-       if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+       if (orig_node->last_ttl != ogm_packet->ttl + 1)
                return false;
        if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
                return false;
@@ -1082,9 +1082,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        coded_packet = (struct batadv_coded_packet *)skb_dest->data;
        skb_reset_mac_header(skb_dest);
 
-       coded_packet->header.packet_type = BATADV_CODED;
-       coded_packet->header.version = BATADV_COMPAT_VERSION;
-       coded_packet->header.ttl = packet1->header.ttl;
+       coded_packet->packet_type = BATADV_CODED;
+       coded_packet->version = BATADV_COMPAT_VERSION;
+       coded_packet->ttl = packet1->ttl;
 
        /* Info about first unicast packet */
        memcpy(coded_packet->first_source, first_source, ETH_ALEN);
@@ -1097,7 +1097,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        memcpy(coded_packet->second_source, second_source, ETH_ALEN);
        memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
        coded_packet->second_crc = packet_id2;
-       coded_packet->second_ttl = packet2->header.ttl;
+       coded_packet->second_ttl = packet2->ttl;
        coded_packet->second_ttvn = packet2->ttvn;
        coded_packet->coded_len = htons(coding_len);
 
@@ -1452,7 +1452,7 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
        /* We only handle unicast packets */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Try to find a coding opportunity and send the skb if one is found */
@@ -1505,7 +1505,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
        /* Check for supported packet type */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Find existing nc_path or create a new */
@@ -1623,7 +1623,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                ttvn = coded_packet_tmp.second_ttvn;
        } else {
                orig_dest = coded_packet_tmp.first_orig_dest;
-               ttl = coded_packet_tmp.header.ttl;
+               ttl = coded_packet_tmp.ttl;
                ttvn = coded_packet_tmp.first_ttvn;
        }
 
@@ -1648,9 +1648,9 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_packet->header.ttl = ttl;
+       unicast_packet->packet_type = BATADV_UNICAST;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
+       unicast_packet->ttl = ttl;
        memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
        unicast_packet->ttvn = ttvn;
 
index 207459b62966d0975bca70894fcf5ce266a5da29..2dd8f2422550c3157112eb4ce5a27362e6caf8fb 100644 (file)
@@ -155,6 +155,7 @@ enum batadv_tvlv_type {
        BATADV_TVLV_ROAM        = 0x05,
 };
 
+#pragma pack(2)
 /* the destination hardware field in the ARP frame is used to
  * transport the claim type and the group id
  */
@@ -163,24 +164,20 @@ struct batadv_bla_claim_dst {
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
 };
-
-struct batadv_header {
-       uint8_t  packet_type;
-       uint8_t  version;  /* batman version field */
-       uint8_t  ttl;
-       /* the parent struct has to add a byte after the header to make
-        * everything 4 bytes aligned again
-        */
-};
+#pragma pack()
 
 /**
  * struct batadv_ogm_packet - ogm (routing protocol) packet
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @flags: contains routing relevant flags - see enum batadv_iv_flags
  * @tvlv_len: length of tvlv data following the ogm header
  */
 struct batadv_ogm_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  flags;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -196,29 +193,51 @@ struct batadv_ogm_packet {
 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
 
 /**
- * batadv_icmp_header - common ICMP header
- * @header: common batman header
+ * batadv_icmp_header - common members among all the ICMP packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @msg_type: ICMP packet type
  * @dst: address of the destination node
  * @orig: address of the source node
  * @uid: local ICMP socket identifier
+ * @align: not used - useful for alignment purposes only
+ *
+ * This structure is used for ICMP packets parsing only and it is never sent
+ * over the wire. The alignment field at the end is there to ensure that
+ * members are padded the same way as they are in real packets.
  */
 struct batadv_icmp_header {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  msg_type; /* see ICMP message types above */
        uint8_t  dst[ETH_ALEN];
        uint8_t  orig[ETH_ALEN];
        uint8_t  uid;
+       uint8_t  align[3];
 };
 
 /**
  * batadv_icmp_packet - ICMP packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @reserved: not used - useful for alignment
  * @seqno: ICMP sequence number
  */
 struct batadv_icmp_packet {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  reserved;
        __be16   seqno;
 };
@@ -227,13 +246,25 @@ struct batadv_icmp_packet {
 
 /**
  * batadv_icmp_packet_rr - ICMP RouteRecord packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @rr_cur: number of entries the rr array
  * @seqno: ICMP sequence number
  * @rr: route record array
  */
 struct batadv_icmp_packet_rr {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  rr_cur;
        __be16   seqno;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
@@ -253,8 +284,18 @@ struct batadv_icmp_packet_rr {
  */
 #pragma pack(2)
 
+/**
+ * struct batadv_unicast_packet - unicast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @ttvn: translation table version number
+ * @dest: originator destination of the unicast packet
+ */
 struct batadv_unicast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
@@ -280,7 +321,9 @@ struct batadv_unicast_4addr_packet {
 
 /**
  * struct batadv_frag_packet - fragmented packet
- * @header: common batman packet header with type, compatversion, and ttl
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @dest: final destination used when routing fragments
  * @orig: originator of the fragment used when merging the packet
  * @no: fragment number within this sequence
@@ -289,7 +332,9 @@ struct batadv_unicast_4addr_packet {
  * @total_size: size of the merged packet
  */
 struct batadv_frag_packet {
-       struct  batadv_header header;
+       uint8_t packet_type;
+       uint8_t version;  /* batman version field */
+       uint8_t ttl;
 #if defined(__BIG_ENDIAN_BITFIELD)
        uint8_t no:4;
        uint8_t reserved:4;
@@ -305,8 +350,19 @@ struct batadv_frag_packet {
        __be16  total_size;
 };
 
+/**
+ * struct batadv_bcast_packet - broadcast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @orig: originator of the broadcast packet
+ */
 struct batadv_bcast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -315,11 +371,11 @@ struct batadv_bcast_packet {
         */
 };
 
-#pragma pack()
-
 /**
  * struct batadv_coded_packet - network coded packet
- * @header: common batman packet header and ttl of first included packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: Align following fields to 2-byte boundaries
  * @first_source: original source of first included packet
  * @first_orig_dest: original destinal of first included packet
@@ -334,7 +390,9 @@ struct batadv_bcast_packet {
  * @coded_len: length of network coded part of the payload
  */
 struct batadv_coded_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  first_ttvn;
        /* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
        uint8_t  first_source[ETH_ALEN];
@@ -349,9 +407,13 @@ struct batadv_coded_packet {
        __be16   coded_len;
 };
 
+#pragma pack()
+
 /**
  * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: reserved field (for packet alignment)
  * @src: address of the source
  * @dst: address of the destination
@@ -359,7 +421,9 @@ struct batadv_coded_packet {
  * @align: 2 bytes to align the header to a 4 byte boundry
  */
 struct batadv_unicast_tvlv_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        uint8_t  dst[ETH_ALEN];
        uint8_t  src[ETH_ALEN];
@@ -420,13 +484,13 @@ struct batadv_tvlv_tt_vlan_data {
  * struct batadv_tvlv_tt_change - translation table diff data
  * @flags: status indicators concerning the non-mesh client (see
  *  batadv_tt_client_flags)
- * @reserved: reserved field
+ * @reserved: reserved field - useful for alignment purposes only
  * @addr: mac address of non-mesh client that triggered this tt change
  * @vid: VLAN identifier
  */
 struct batadv_tvlv_tt_change {
        uint8_t flags;
-       uint8_t reserved;
+       uint8_t reserved[3];
        uint8_t addr[ETH_ALEN];
        __be16 vid;
 };
index d4114d775ad61f659b59437c67aa7054d9a88f92..46278bfb8fdb9469e12f8fbdc8922e49f81f8014 100644 (file)
@@ -308,7 +308,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
                memcpy(icmph->dst, icmph->orig, ETH_ALEN);
                memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
                icmph->msg_type = BATADV_ECHO_REPLY;
-               icmph->header.ttl = BATADV_TTL;
+               icmph->ttl = BATADV_TTL;
 
                res = batadv_send_skb_to_orig(skb, orig_node, NULL);
                if (res != NET_XMIT_DROP)
@@ -338,9 +338,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
        /* send TTL exceeded if packet is an echo request (traceroute) */
-       if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
+       if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
                pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
-                        icmp_packet->icmph.orig, icmp_packet->icmph.dst);
+                        icmp_packet->orig, icmp_packet->dst);
                goto out;
        }
 
@@ -349,7 +349,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
                goto out;
 
        /* get routing information */
-       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
+       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
        if (!orig_node)
                goto out;
 
@@ -359,11 +359,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
-       memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
-       memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+       memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+       memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr,
               ETH_ALEN);
-       icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
-       icmp_packet->icmph.header.ttl = BATADV_TTL;
+       icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
+       icmp_packet->ttl = BATADV_TTL;
 
        if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
@@ -434,7 +434,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                return batadv_recv_my_icmp_packet(bat_priv, skb);
 
        /* TTL exceeded */
-       if (icmph->header.ttl < 2)
+       if (icmph->ttl < 2)
                return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
 
        /* get routing information */
@@ -449,7 +449,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmph = (struct batadv_icmp_header *)skb->data;
 
        /* decrement ttl */
-       icmph->header.ttl--;
+       icmph->ttl--;
 
        /* route it */
        if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -709,7 +709,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* TTL exceeded */
-       if (unicast_packet->header.ttl < 2) {
+       if (unicast_packet->ttl < 2) {
                pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
                         ethhdr->h_source, unicast_packet->dest);
                goto out;
@@ -727,9 +727,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
        /* decrement ttl */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.ttl--;
+       unicast_packet->ttl--;
 
-       switch (unicast_packet->header.packet_type) {
+       switch (unicast_packet->packet_type) {
        case BATADV_UNICAST_4ADDR:
                hdr_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
@@ -970,7 +970,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
        /* the caller function should have already pulled 2 bytes */
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
@@ -1160,7 +1160,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
-       if (bcast_packet->header.ttl < 2)
+       if (bcast_packet->ttl < 2)
                goto out;
 
        orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
index c83be5ebaa285dffe64d051850e87f2fca02624b..fba4dcfcfac21b6e9c6686c30fc6ca8a1a08f3fa 100644 (file)
@@ -161,11 +161,11 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
                return false;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
        /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
+       unicast_packet->packet_type = BATADV_UNICAST;
        /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
+       unicast_packet->ttl = BATADV_TTL;
        /* copy the destination for faster routing */
        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
        /* set the destination tt version number */
@@ -221,7 +221,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                goto out;
 
        uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
-       uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
        memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
        uc_4addr_packet->subtype = packet_subtype;
        uc_4addr_packet->reserved = 0;
@@ -436,7 +436,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 
        /* as we have a copy now, it is safe to decrease the TTL */
        bcast_packet = (struct batadv_bcast_packet *)newskb->data;
-       bcast_packet->header.ttl--;
+       bcast_packet->ttl--;
 
        skb_reset_mac_header(newskb);
 
index 36f050876f8260245a008de079cf0974fa97b76e..a8f99d1486c0441e9aa192e81d7522ad451f4bd7 100644 (file)
@@ -264,11 +264,11 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        goto dropped;
 
                bcast_packet = (struct batadv_bcast_packet *)skb->data;
-               bcast_packet->header.version = BATADV_COMPAT_VERSION;
-               bcast_packet->header.ttl = BATADV_TTL;
+               bcast_packet->version = BATADV_COMPAT_VERSION;
+               bcast_packet->ttl = BATADV_TTL;
 
                /* batman packet type: broadcast */
-               bcast_packet->header.packet_type = BATADV_BCAST;
+               bcast_packet->packet_type = BATADV_BCAST;
                bcast_packet->reserved = 0;
 
                /* hw address of first interface is the orig mac because only
@@ -328,7 +328,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                         struct sk_buff *skb, struct batadv_hard_iface *recv_if,
                         int hdr_size, struct batadv_orig_node *orig_node)
 {
-       struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
+       struct batadv_bcast_packet *batadv_bcast_packet;
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        __be16 ethertype = htons(ETH_P_BATMAN);
        struct vlan_ethhdr *vhdr;
@@ -336,7 +336,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
        unsigned short vid;
        bool is_bcast;
 
-       is_bcast = (batadv_header->packet_type == BATADV_BCAST);
+       batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -345,7 +346,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       vid = batadv_get_vid(skb, hdr_size);
+       /* clean the netfilter state now that the batman-adv header has been
+        * removed
+        */
+       nf_reset(skb);
+
+       vid = batadv_get_vid(skb, 0);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
index 4add57d4857f11e5ea9edfa13aae1f46dab3e4f9..ff625fedbc5eeb08a7569c01973f5eb1ddc71eb1 100644 (file)
@@ -333,7 +333,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       tt_change_node->change.reserved = 0;
+       memset(tt_change_node->change.reserved, 0,
+              sizeof(tt_change_node->change.reserved));
        memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
        tt_change_node->change.vid = htons(common->vid);
 
@@ -2221,7 +2222,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
                               ETH_ALEN);
                        tt_change->flags = tt_common_entry->flags;
                        tt_change->vid = htons(tt_common_entry->vid);
-                       tt_change->reserved = 0;
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
 
                        tt_num_entries++;
                        tt_change++;
index 6a6c8bb4fd72d4f2d4294b9f7fed772d81e57b93..7552f9e3089ce790040268f1ce0a067d6ef728cb 100644 (file)
@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
        skb_pull(skb, 1);
 
-       if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
-           bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+       if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+               /* No permission check is needed for user channel
+                * since that gets enforced when binding the socket.
+                *
+                * However check that the packet type is valid.
+                */
+               if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+                       err = -EINVAL;
+                       goto drop;
+               }
+
+               skb_queue_tail(&hdev->raw_q, skb);
+               queue_work(hdev->workqueue, &hdev->tx_work);
+       } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
                u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
-               if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
-                   bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
-                       err = -EINVAL;
-                       goto drop;
-               }
-
                skb_queue_tail(&hdev->raw_q, skb);
                queue_work(hdev->workqueue, &hdev->tx_work);
        }
index 4c214b2b88efa01d81be93a8b8d77e57229c1fa4..ef66365b7354da9f2fe2c4d87d2056d9a781f3c8 100644 (file)
@@ -1998,7 +1998,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -2030,7 +2030,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index ba3b7ea5ebb3139cca38e82ac6f5f5e346f4a4e0..0ce469e5ec8057c674901b404db13061fe8b7392 100644 (file)
@@ -2539,7 +2539,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv)
+                       struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc = NETDEV_TX_OK;
@@ -2605,13 +2605,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        dev_queue_xmit_nit(skb, dev);
 
                skb_len = skb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
-               else
                        rc = ops->ndo_start_xmit(skb, dev);
 
                trace_net_dev_xmit(skb, rc, dev, skb_len);
-               if (rc == NETDEV_TX_OK && txq)
+               if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
        }
@@ -2627,10 +2624,7 @@ gso:
                        dev_queue_xmit_nit(nskb, dev);
 
                skb_len = nskb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(nskb, dev);
+               rc = ops->ndo_start_xmit(nskb, dev);
                trace_net_dev_xmit(nskb, rc, dev, skb_len);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
@@ -2811,7 +2805,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-int dev_queue_xmit(struct sk_buff *skb)
+int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -2827,7 +2821,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        skb_update_prio(skb);
 
-       txq = netdev_pick_tx(dev, skb);
+       txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -2863,7 +2857,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                        if (!netif_xmit_stopped(txq)) {
                                __this_cpu_inc(xmit_recursion);
-                               rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+                               rc = dev_hard_start_xmit(skb, dev, txq);
                                __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
@@ -2892,8 +2886,19 @@ out:
        rcu_read_unlock_bh();
        return rc;
 }
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+       return __dev_queue_xmit(skb, NULL);
+}
 EXPORT_SYMBOL(dev_queue_xmit);
 
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
+{
+       return __dev_queue_xmit(skb, accel_priv);
+}
+EXPORT_SYMBOL(dev_queue_xmit_accel);
+
 
 /*=======================================================================
                        Receiver routines
@@ -4500,7 +4505,7 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *upper;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
index d6ef173225008ec1946ed232f781cc63754b9575..2fc5beaf578349cd543621a460bf2bb4eaa9d221 100644 (file)
@@ -395,17 +395,21 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb)
+                                   struct sk_buff *skb,
+                                   void *accel_priv)
 {
        int queue_index = 0;
 
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
                if (ops->ndo_select_queue)
-                       queue_index = ops->ndo_select_queue(dev, skb);
+                       queue_index = ops->ndo_select_queue(dev, skb,
+                                                           accel_priv);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
-               queue_index = dev_cap_txqueue(dev, queue_index);
+
+               if (!accel_priv)
+                       queue_index = dev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index 36b1443f9ae4b38cdd7b15f645f08032acac06d0..932c6d7cf6668e073a90432281037b51cf7dfecc 100644 (file)
@@ -1275,7 +1275,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 
        if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
                            skb->len) < 0 &&
-           dev->header_ops->rebuild(skb))
+           dev_rebuild_header(skb))
                return 0;
 
        return dev_queue_xmit(skb);
index 8f971990677cd48026f651b2dba01d01190bfff6..19fe9c717cedb56051ff6cb5effca0274fd946d8 100644 (file)
@@ -375,7 +375,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
        if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
                struct netdev_queue *txq;
 
-               txq = netdev_pick_tx(dev, skb);
+               txq = netdev_pick_tx(dev, skb, NULL);
 
                /* try until next clock tick */
                for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)
index 4c6bdf97a6577d190332b85654769a92ce553111..595ddf0459db79c724b8eab2c8b0f6a0a7d1df97 100644 (file)
@@ -152,17 +152,6 @@ static const struct file_operations dccpprobe_fops = {
        .llseek  = noop_llseek,
 };
 
-static __init int setup_jprobe(void)
-{
-       int ret = register_jprobe(&dccp_send_probe);
-
-       if (ret) {
-               request_module("dccp");
-               ret = register_jprobe(&dccp_send_probe);
-       }
-       return ret;
-}
-
 static __init int dccpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -174,7 +163,13 @@ static __init int dccpprobe_init(void)
        if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
                goto err0;
 
-       ret = setup_jprobe();
+       ret = register_jprobe(&dccp_send_probe);
+       if (ret) {
+               ret = request_module("dccp");
+               if (!ret)
+                       ret = register_jprobe(&dccp_send_probe);
+       }
+
        if (ret)
                goto err1;
 
index 459e200c08a40e4e737798582524cd973064b143..a2d2456a557a7621059a5b0bbe033168492f8fe7 100644 (file)
@@ -547,7 +547,7 @@ static int lowpan_header_create(struct sk_buff *skb,
                        hc06_ptr += 3;
                } else {
                        /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
+                       memcpy(hc06_ptr, hdr, 4);
                        /* replace the top byte with new ECN | DSCP format */
                        *hc06_ptr = tmp;
                        hc06_ptr += 4;
index e5d436188464eba55eca773f4fb88fd0f0634e97..2cd02f32f99f568c8275389aefd754700a77efa6 100644 (file)
@@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        netdev_features_t enc_features;
        int ghl = GRE_HEADER_SECTION;
        struct gre_base_hdr *greh;
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        __be16 protocol = skb->protocol;
        int tnl_hlen;
@@ -58,13 +59,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        } else
                csum = false;
 
+       if (unlikely(!pskb_may_pull(skb, ghl)))
+               goto out;
+
        /* setup inner skb. */
        skb->protocol = greh->protocol;
        skb->encapsulation = 0;
 
-       if (unlikely(!pskb_may_pull(skb, ghl)))
-               goto out;
-
        __skb_pull(skb, ghl);
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, skb_inner_network_offset(skb));
@@ -73,8 +74,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
                goto out;
+       }
 
        skb = segs;
        tnl_hlen = skb_tnl_header_len(skb);
index 56a964a553d2c739a03b880acd7158a4c9714b66..a0f52dac8940de45ffaa53291c82950b2e6c4c99 100644 (file)
@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = inet->inet_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 
        r->idiag_family       = tw->tw_family;
        r->idiag_retrans      = 0;
+
        r->id.idiag_if        = tw->tw_bound_dev_if;
        sock_diag_save_cookie(tw, r->id.idiag_cookie);
+
        r->id.idiag_sport     = tw->tw_sport;
        r->id.idiag_dport     = tw->tw_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
        r->id.idiag_dst[0]    = tw->tw_daddr;
+
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
        r->idiag_expires      = jiffies_to_msecs(tmo);
@@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = ireq->ir_rmt_port;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = ireq->ir_loc_addr;
        r->id.idiag_dst[0] = ireq->ir_rmt_addr;
+
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
index d7aea4c5b9400efec37d15db3c5a896769d0da68..e560ef34cf4bd2efe9f1f7a64424441117a4502a 100644 (file)
@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
                                  iph->saddr, iph->daddr, tpi->key);
 
        if (tunnel) {
+               skb_pop_mac_header(skb);
                ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error);
                return PACKET_RCVD;
        }
index 912402752f2ffce701d697de1bb7a32b05c3b482..df184616493f707ea8a0ea353a33d3a5aa981fc7 100644 (file)
@@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk,
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
-                              mtu-exthdrlen);
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
@@ -1151,7 +1151,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                         mtu : 0xFFFF;
 
        if (cork->length + size > maxnonfragsize - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu);
+               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
index f140048334ce21f38d86ac4a2fdf770df5330d78..a7e4729e974b3206f57e3b3da4026a77432768e1 100644 (file)
@@ -2478,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        __be16 protocol = skb->protocol;
@@ -2497,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
+                                    mac_len);
                goto out;
+       }
 
        outer_hlen = skb_tnl_header_len(skb);
        skb = segs;
index 83206de2bc7679dc20e4fdcf34f8b1f5cd7831ef..79c62bdcd3c549b7dc07c74449d30b77296134eb 100644 (file)
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
+       int offset;
+       __wsum csum;
+
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
+               segs = skb_udp_tunnel_segment(skb, features);
+               goto out;
+       }
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       /* Do software UFO. Complete and fill in the UDP checksum as
+        * HW cannot do checksum of UDP packets sent as multiple
+        * IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
-       if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
-               segs = skb_udp_tunnel_segment(skb, features);
-       else {
-               int offset;
-               __wsum csum;
-
-               /* Do software UFO. Complete and fill in the UDP checksum as
-                * HW cannot do checksum of UDP packets sent as multiple
-                * IP fragments.
-                */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
-
-               segs = skb_segment(skb, features);
-       }
+       segs = skb_segment(skb, features);
 out:
        return segs;
 }
index d5fa5b8c443ecbbcb0ed09a10db19b06730b7d8b..abe46a4228ce96655d1aacec77052a89e70cfdd4 100644 (file)
@@ -1671,7 +1671,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1682,7 +1682,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -2509,7 +2509,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        struct inet6_ifaddr *ifp;
 
        ifp = ipv6_add_addr(idev, addr, NULL, plen,
-                           scope, IFA_F_PERMANENT, 0, 0);
+                           scope, IFA_F_PERMANENT,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                spin_lock_bh(&ifp->lock);
                ifp->flags &= ~IFA_F_TENTATIVE;
@@ -2637,7 +2638,8 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr
 #endif
 
 
-       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, 0, 0);
+       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
                addrconf_dad_start(ifp);
@@ -3456,7 +3458,12 @@ restart:
                                         &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
-                       if (ifp->flags & IFA_F_PERMANENT)
+                       /* When setting preferred_lft to a value not zero or
+                        * infinity, while valid_lft is infinity
+                        * IFA_F_PERMANENT has a non-infinity life time.
+                        */
+                       if ((ifp->flags & IFA_F_PERMANENT) &&
+                           (ifp->prefered_lft == INFINITY_LIFE_TIME))
                                continue;
 
                        spin_lock(&ifp->lock);
@@ -3481,7 +3488,8 @@ restart:
                                        ifp->flags |= IFA_F_DEPRECATED;
                                }
 
-                               if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+                               if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
+                                   (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
                                        next = ifp->tstamp + ifp->valid_lft * HZ;
 
                                spin_unlock(&ifp->lock);
@@ -3761,7 +3769,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
 
-       if (!(ifa->flags&IFA_F_PERMANENT)) {
+       if (!((ifa->flags&IFA_F_PERMANENT) &&
+             (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
                preferred = ifa->prefered_lft;
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
index 4acdb63495dbe2484de9d278b810401e6d26fc6a..e6f931997996ef46efa1272b16e261bf8f6609a7 100644 (file)
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
                        (opt ? opt->opt_nflen : 0);
-       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
+       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
+                    sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
-               if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-                       ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
+               unsigned int maxnonfragsize, headersize;
+
+               headersize = sizeof(struct ipv6hdr) +
+                            (opt ? opt->tot_len : 0) +
+                            (dst_allfrag(&rt->dst) ?
+                             sizeof(struct frag_hdr) : 0) +
+                            rt->rt6i_nfheader_len;
+
+               maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ?
+                                mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
+
+               /* dontfrag active */
+               if ((cork->length + length > mtu - headersize) && dontfrag &&
+                   (sk->sk_protocol == IPPROTO_UDP ||
+                    sk->sk_protocol == IPPROTO_RAW)) {
+                       ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
+                                                  sizeof(struct ipv6hdr));
+                       goto emsgsize;
+               }
+
+               if (cork->length + length > maxnonfragsize - headersize) {
+emsgsize:
+                       ipv6_local_error(sk, EMSGSIZE, fl6,
+                                        mtu - headersize +
+                                        sizeof(struct ipv6hdr));
                        return -EMSGSIZE;
                }
        }
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
-                                          sk->sk_protocol == IPPROTO_RAW)) {
-               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-               return -EMSGSIZE;
-       }
-
        skb = skb_peek_tail(&sk->sk_write_queue);
        cork->length += length;
        if (((length > mtu) ||
index d6062325db08411207fd63b435ec1e5e4e0f2001..7881965a824840a763a7e1183efcf21153f87b47 100644 (file)
@@ -103,16 +103,25 @@ struct ip6_tnl_net {
 
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
-       struct pcpu_tstats sum = { 0 };
+       struct pcpu_tstats tmp, sum = { 0 };
        int i;
 
        for_each_possible_cpu(i) {
+               unsigned int start;
                const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
 
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       tmp.rx_packets = tstats->rx_packets;
+                       tmp.rx_bytes = tstats->rx_bytes;
+                       tmp.tx_packets = tstats->tx_packets;
+                       tmp.tx_bytes =  tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               sum.rx_packets += tmp.rx_packets;
+               sum.rx_bytes   += tmp.rx_bytes;
+               sum.tx_packets += tmp.tx_packets;
+               sum.tx_bytes   += tmp.tx_bytes;
        }
        dev->stats.rx_packets = sum.rx_packets;
        dev->stats.rx_bytes   = sum.rx_bytes;
@@ -824,8 +833,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
index ed94ba61dda0ec1c3e2b170fe74eb2334b752700..7b42d5ef868deaa193094a85a00b502aeaba0bdd 100644 (file)
@@ -75,26 +75,6 @@ struct vti6_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-static struct net_device_stats *vti6_get_stats(struct net_device *dev)
-{
-       struct pcpu_tstats sum = { 0 };
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
-       }
-       dev->stats.rx_packets = sum.rx_packets;
-       dev->stats.rx_bytes   = sum.rx_bytes;
-       dev->stats.tx_packets = sum.tx_packets;
-       dev->stats.tx_bytes   = sum.tx_bytes;
-       return &dev->stats;
-}
-
 #define for_each_vti6_tunnel_rcu(start) \
        for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
@@ -331,8 +311,10 @@ static int vti6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                skb->mark = 0;
                secpath_reset(skb);
@@ -716,7 +698,7 @@ static const struct net_device_ops vti6_netdev_ops = {
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
        .ndo_change_mtu = vti6_change_mtu,
-       .ndo_get_stats  = vti6_get_stats,
+       .ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 /**
@@ -750,12 +732,18 @@ static void vti6_dev_setup(struct net_device *dev)
 static inline int vti6_dev_init_gen(struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
+       int i;
 
        t->dev = dev;
        t->net = dev_net(dev);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
+       for_each_possible_cpu(i) {
+               struct pcpu_tstats *stats;
+               stats = per_cpu_ptr(dev->tstats, i);
+               u64_stats_init(&stats->syncp);
+       }
        return 0;
 }
 
index a0a48ac3403f3a9284786aa5b8f00dc03696e2e0..4b4944c3e4c4473c8b1ca4fbce8700a8af988604 100644 (file)
@@ -1905,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
index 366fbba3359ab790e1b22917931acdbdb1daebf3..d3005b34476a82f8172cfe8807507d561d307938 100644 (file)
@@ -702,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -924,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (tunnel->parms.iph.daddr && skb_dst(skb))
                        skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
-               if (skb->len > mtu) {
+               if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
@@ -966,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
        skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
-       if (IS_ERR(skb))
+       if (IS_ERR(skb)) {
+               ip_rt_put(rt);
                goto out;
+       }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
                            ttl, df, !net_eq(tunnel->net, dev_net(dev)));
index 7b01b9f5846c845bcf4f04b21cfbcb5786c19421..c71b699eb555165e124ec21109e37212587c7741 100644 (file)
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
-       u32 *seq;
+       u32 *seq, skb_len;
        unsigned long used;
        int target;     /* Read at least this many bytes */
        long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
                continue;
        found_ok_skb:
+               skb_len = skb->len;
                /* Ok so how much can we use? */
                used = skb->len - offset;
                if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                /* Partial read */
-               if (used + offset < skb->len)
+               if (used + offset < skb_len)
                        continue;
        } while (len > 0);
 
index 36c3a4cbcabf66b2a0864414b3c23ea2896b7c4e..a0757913046eab8eee0c99104d8900db4e338c3e 100644 (file)
@@ -1061,7 +1061,8 @@ static void ieee80211_uninit(struct net_device *dev)
 }
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        void *accel_priv)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1078,7 +1079,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
-                                         struct sk_buff *skb)
+                                         struct sk_buff *skb,
+                                         void *accel_priv)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index c558b246ef0036c38e6c8a00b338b43c46913f78..ca7fa7f0613dba22cdc0e82d8a96e1de9ff011dc 100644 (file)
@@ -463,7 +463,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
        if (unlikely(!sta))
@@ -474,15 +473,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
-               /* only deauth, disassoc and action are bufferable MMPDUs */
-               if (ieee80211_is_mgmt(hdr->frame_control) &&
-                   !ieee80211_is_deauth(hdr->frame_control) &&
-                   !ieee80211_is_disassoc(hdr->frame_control) &&
-                   !ieee80211_is_action(hdr->frame_control)) {
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-                       return TX_CONTINUE;
-               }
-
                ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -525,9 +515,22 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
        if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
                return TX_CONTINUE;
 
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_deauth(hdr->frame_control) &&
+           !ieee80211_is_disassoc(hdr->frame_control) &&
+           !ieee80211_is_action(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+       }
+
        if (tx->flags & IEEE80211_TX_UNICAST)
                return ieee80211_tx_h_unicast_ps_buf(tx);
        else
index c8beafd401aa283f0befa0494e02649359bab83f..5a355a46d1dc4a70e82fadcd509ddd4fae34c3e1 100644 (file)
@@ -63,6 +63,7 @@
 #include <net/ip_vs.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -97,6 +98,11 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                return;
 
+       /* Applications may adjust TCP seqs */
+       if (cp->app && nf_ct_protonum(ct) == IPPROTO_TCP &&
+           !nfct_seqadj(ct) && !nfct_seqadj_ext_add(ct))
+               return;
+
        /*
         * The connection is not yet in the hashtable, so we update it.
         * CIP->VIP will remain the same, so leave the tuple in
index 17c1bcb182c6b58a782744e23bfe671de160bf92..f6e2ae91a80badd697a1f77e299dc332bc34a8d1 100644 (file)
@@ -36,6 +36,11 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
        spin_lock_bh(&ct->lock);
index 902fb0a6b38ad9baac15c3fc3f17a3e695510db8..7a394df0deb7686fa7fe4da162ff77d3c03435c5 100644 (file)
@@ -97,7 +97,6 @@ int nf_conntrack_tstamp_pernet_init(struct net *net)
 void nf_conntrack_tstamp_pernet_fini(struct net *net)
 {
        nf_conntrack_tstamp_fini_sysctl(net);
-       nf_ct_extend_unregister(&tstamp_extend);
 }
 
 int nf_conntrack_tstamp_init(void)
index f02b3605823e5616bc70f128a896e76d8f984ff2..1fb2258c35357c8c6f5072ae6593de2d53ab9f03 100644 (file)
@@ -34,10 +34,14 @@ static unsigned int help(struct sk_buff *skb,
                         struct nf_conntrack_expect *exp)
 {
        char buffer[sizeof("4294967296 65635")];
+       struct nf_conn *ct = exp->master;
+       union nf_inet_addr newaddr;
        u_int16_t port;
        unsigned int ret;
 
        /* Reply comes from server. */
+       newaddr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
+
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
@@ -57,17 +61,35 @@ static unsigned int help(struct sk_buff *skb,
        }
 
        if (port == 0) {
-               nf_ct_helper_log(skb, exp->master, "all ports in use");
+               nf_ct_helper_log(skb, ct, "all ports in use");
                return NF_DROP;
        }
 
-       ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
-                                      protoff, matchoff, matchlen, buffer,
-                                      strlen(buffer));
+       /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+        * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+        * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
+        *
+        * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
+        *                        255.255.255.255==4294967296, 10 digits)
+        * P:         bound port (min 1 d, max 5d (65635))
+        * F:         filename   (min 1 d )
+        * S:         size       (min 1 d )
+        * 0x01, \n:  terminators
+        */
+       /* AAA = "us", ie. where server normally talks to. */
+       snprintf(buffer, sizeof(buffer), "%u %u", ntohl(newaddr.ip), port);
+       pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n",
+                buffer, &newaddr.ip, port);
+
+       ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff,
+                                      matchlen, buffer, strlen(buffer));
        if (ret != NF_ACCEPT) {
-               nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
+               nf_ct_helper_log(skb, ct, "cannot mangle packet");
                nf_ct_unexpect_related(exp);
        }
+
        return ret;
 }
 
index f93b7d06f4be9525ad4ab4314a106b01e85749ba..71a9f49a768b887dec1b361b78147016cb2b9307 100644 (file)
@@ -312,6 +312,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        int err, i = 0;
 
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                err = nf_register_hook(&nft_base_chain(chain)->ops);
                if (err < 0)
                        goto err;
@@ -321,6 +324,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        return 0;
 err:
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                if (i-- <= 0)
                        break;
 
@@ -333,8 +339,10 @@ static int nf_tables_table_disable(struct nft_table *table)
 {
        struct nft_chain *chain;
 
-       list_for_each_entry(chain, &table->chains, list)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+       list_for_each_entry(chain, &table->chains, list) {
+               if (chain->flags & NFT_BASE_CHAIN)
+                       nf_unregister_hook(&nft_base_chain(chain)->ops);
+       }
 
        return 0;
 }
@@ -2098,17 +2106,21 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
        const struct nft_set *set;
-       unsigned int idx = 0, s_idx = cb->args[0];
+       unsigned int idx, s_idx = cb->args[0];
        struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
 
        if (cb->args[1])
                return skb->len;
 
        list_for_each_entry(table, &ctx->afi->tables, list) {
-               if (cur_table && cur_table != table)
-                       continue;
+               if (cur_table) {
+                       if (cur_table != table)
+                               continue;
 
+                       cur_table = NULL;
+               }
                ctx->table = table;
+               idx = 0;
                list_for_each_entry(set, &ctx->table->sets, list) {
                        if (idx < s_idx)
                                goto cont;
@@ -2370,7 +2382,9 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
        enum nft_registers dreg;
 
        dreg = nft_type_to_reg(set->dtype);
-       return nft_validate_data_load(ctx, dreg, &elem->data, set->dtype);
+       return nft_validate_data_load(ctx, dreg, &elem->data,
+                                     set->dtype == NFT_DATA_VERDICT ?
+                                     NFT_DATA_VERDICT : NFT_DATA_VALUE);
 }
 
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
index 3c4b69e5fe17348b422f390bf79ab4269043fe5d..a155d19a225edcfb4b1a550ebc898f40d51c564d 100644 (file)
@@ -1053,6 +1053,7 @@ static void __net_exit nfnl_log_net_exit(struct net *net)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
+       nf_log_unset(net, &nfulnl_logger);
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 8e0bb75e7c51e61092fb904dc1d93befe1e7320d..55c939f5371fabf35ad996efb51ea52a29630703 100644 (file)
@@ -31,7 +31,7 @@ static void nft_exthdr_eval(const struct nft_expr *expr,
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
-       unsigned int offset;
+       unsigned int offset = 0;
        int err;
 
        err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
index 872529105abc7c3a2e41b9d579e934e019e8e5ff..83b9927e7d19f3b14c8db4b199385122843d6764 100644 (file)
@@ -384,7 +384,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 {
        dev->dep_link_up = true;
 
-       if (!dev->active_target) {
+       if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
                struct nfc_target *target;
 
                target = nfc_find_target(dev, target_idx);
index b4c8b0022feeebea1aec424542e37a8391d87297..ba2dffeff60876ca669993d1863dcbb6cb76a740 100644 (file)
@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support iWARP devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_IB_CA)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
index 33af77246bfeb90c6b31bfe6163dc2c9cfbda787..62ced6516c586f5c7b5cb779e079ad57b72b7518 100644 (file)
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (msg->msg_name) {
                struct sockaddr_rose *srose;
+               struct full_sockaddr_rose *full_srose = msg->msg_name;
 
                memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
                srose = msg->msg_name;
@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
                srose->srose_ndigis = rose->dest_ndigis;
-               if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) {
-                       struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name;
-                       for (n = 0 ; n < rose->dest_ndigis ; n++)
-                               full_srose->srose_digis[n] = rose->dest_digis[n];
-                       msg->msg_namelen = sizeof(struct full_sockaddr_rose);
-               } else {
-                       if (rose->dest_ndigis >= 1) {
-                               srose->srose_ndigis = 1;
-                               srose->srose_digi = rose->dest_digis[0];
-                       }
-                       msg->msg_namelen = sizeof(struct sockaddr_rose);
-               }
+               for (n = 0 ; n < rose->dest_ndigis ; n++)
+                       full_srose->srose_digis[n] = rose->dest_digis[n];
+               msg->msg_namelen = sizeof(struct full_sockaddr_rose);
        }
 
        skb_free_datagram(sk, skb);
index 5c5edf56adbd4fc9a4d64a509a9103511f995db4..11fe1a416433f1fe2ea46c86ee753826e523b716 100644 (file)
@@ -77,16 +77,16 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
                                     &csum_idx_gen, &csum_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_csum(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_csum(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &csum_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &csum_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
+       p = to_tcf_csum(pc);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
index 5645a4d32abdd187f59d9f6301842e35d08762df..eb9ba60ebab4394527d10f25511b36b5aff84a32 100644 (file)
@@ -102,10 +102,11 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &gact_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &gact_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        gact = to_gact(pc);
index 882a89762f77c2edb8b6d10d0c8ef69cf3e39aac..dcbfe8ce04a6a30ee9ce273f8e82196a5ba4a319 100644 (file)
@@ -141,10 +141,12 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_ipt_release(to_ipt(pc), bind);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_ipt_release(to_ipt(pc), bind);
+
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        ipt = to_ipt(pc);
 
index 6a15ace002411a8c11efeed6156d72324b9eb2ff..76869538d0287148e48bf43660d3e243912a6e30 100644 (file)
@@ -70,15 +70,15 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                                     &nat_idx_gen, &nat_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_nat(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_nat(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &nat_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &nat_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
+       p = to_tcf_nat(pc);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
index 03b67674169c5db79eb546d93d0b4833324786d3..7aa2dcd989f842976c57d449452d2e0458a7b32c 100644 (file)
@@ -84,10 +84,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                p = to_pedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &pedit_hash_info);
+               tcf_hash_release(pc, bind, &pedit_hash_info);
+               if (bind)
+                       return 0;
+               if (!ovr)
                        return -EEXIST;
-               }
+
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
index 16a62c36928a78110923d36d5b87808936d8f90a..ef246d87e68bbdf628bc00eebb05e9cb88a3cb87 100644 (file)
@@ -177,10 +177,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
+                               return 0;
                        }
                        if (ovr)
                                goto override;
-                       return ret;
+                       /* not replacing */
+                       return -EEXIST;
                }
        }
 
index 31157d3e729c8c29e8bb89ce03fa68c5ad8e7f39..f7b45ab85388748e9f730939b7f214952f8df84e 100644 (file)
@@ -142,10 +142,13 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
-               if (!ovr) {
-                       tcf_simp_release(d, bind);
+
+               if (bind)
+                       return 0;
+               tcf_simp_release(d, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
+
                reset_policy(d, defdata, parm);
        }
 
index 35ea643b4325562d74c4c05d9950a4f8a8a7ad32..8fe9d25c3008ece001d4da815cdf4f50c893fdab 100644 (file)
@@ -120,10 +120,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_skbedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        spin_lock_bh(&d->tcf_lock);
index 922a09406ba70573499877ac3e561c9ee7b61a5c..7fc899a943a8fa8368415bc0c6c8a939bd042963 100644 (file)
@@ -126,7 +126,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
 
        HARD_TX_LOCK(dev, txq, smp_processor_id());
        if (!netif_xmit_frozen_or_stopped(txq))
-               ret = dev_hard_start_xmit(skb, dev, txq, NULL);
+               ret = dev_hard_start_xmit(skb, dev, txq);
 
        HARD_TX_UNLOCK(dev, txq);
 
index f51ba985a36eaaf0b021adba700cf16d42394e6f..59268f6e2c36a0b32ac6b768dea15b7b6be0021d 100644 (file)
@@ -208,8 +208,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
-
-       q->empty = 1;
 }
 
 /* Free the outqueue structure and any related pending chunks.
@@ -332,7 +330,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
                        else
                                SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
-                       q->empty = 0;
                        break;
                }
        } else {
@@ -654,7 +651,6 @@ redo:
                        if (chunk->fast_retransmit == SCTP_NEED_FRTX)
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
-                       q->empty = 0;
                        q->asoc->stats.rtxchunks++;
                        break;
                }
@@ -1065,8 +1061,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                        sctp_transport_reset_timers(transport);
 
-                       q->empty = 0;
-
                        /* Only let one DATA chunk get bundled with a
                         * COOKIE-ECHO chunk.
                         */
@@ -1275,29 +1269,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,
                 asoc->adv_peer_ack_point);
 
-       /* See if all chunks are acked.
-        * Make sure the empty queue handler will get run later.
-        */
-       q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->retransmit));
-       if (!q->empty)
-               goto finish;
-
-       list_for_each_entry(transport, transport_list, transports) {
-               q->empty = q->empty && list_empty(&transport->transmitted);
-               if (!q->empty)
-                       goto finish;
-       }
-
-       pr_debug("%s: sack queue is empty\n", __func__);
-finish:
-       return q->empty;
+       return sctp_outq_is_empty(q);
 }
 
-/* Is the outqueue empty?  */
+/* Is the outqueue empty?
+ * The queue is empty when we have not pending data, no in-flight data
+ * and nothing pending retransmissions.
+ */
 int sctp_outq_is_empty(const struct sctp_outq *q)
 {
-       return q->empty;
+       return q->out_qlen == 0 && q->outstanding_bytes == 0 &&
+              list_empty(&q->retransmit);
 }
 
 /********************************************************************
index 69cd9bf3f561d64d377ddb65091b98e1017e15cf..13b9877458201fa4d5bb14a36892825272229050 100644 (file)
@@ -1498,6 +1498,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
                int type;
 
                head = head->next;
+               buf->next = NULL;
 
                /* Ensure bearer is still enabled */
                if (unlikely(!b_ptr->active))
index c081a7632302ca0798c193b039214466c3180184..d43f3182b1d4cc1628817d882c9d006006e27e1e 100644 (file)
@@ -251,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk,
        return p_ptr;
 }
 
-int tipc_deleteport(u32 ref)
+int tipc_deleteport(struct tipc_port *p_ptr)
 {
-       struct tipc_port *p_ptr;
        struct sk_buff *buf = NULL;
 
-       tipc_withdraw(ref, 0, NULL);
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
+       tipc_withdraw(p_ptr, 0, NULL);
 
-       tipc_ref_discard(ref);
-       tipc_port_unlock(p_ptr);
+       spin_lock_bh(p_ptr->lock);
+       tipc_ref_discard(p_ptr->ref);
+       spin_unlock_bh(p_ptr->lock);
 
        k_cancel_timer(&p_ptr->timer);
        if (p_ptr->connected) {
@@ -704,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 }
 
 
-int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
+                struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        u32 key;
-       int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
+       if (p_ptr->connected)
                return -EINVAL;
+       key = p_ptr->ref + p_ptr->pub_count + 1;
+       if (key == p_ptr->ref)
+               return -EADDRINUSE;
 
-       if (p_ptr->connected)
-               goto exit;
-       key = ref + p_ptr->pub_count + 1;
-       if (key == ref) {
-               res = -EADDRINUSE;
-               goto exit;
-       }
        publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
                                    scope, p_ptr->ref, key);
        if (publ) {
                list_add(&publ->pport_list, &p_ptr->publications);
                p_ptr->pub_count++;
                p_ptr->published = 1;
-               res = 0;
+               return 0;
        }
-exit:
-       tipc_port_unlock(p_ptr);
-       return res;
+       return -EINVAL;
 }
 
-int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
+                 struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        struct publication *tpubl;
        int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
        if (!seq) {
                list_for_each_entry_safe(publ, tpubl,
                                         &p_ptr->publications, pport_list) {
@@ -771,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        }
        if (list_empty(&p_ptr->publications))
                p_ptr->published = 0;
-       tipc_port_unlock(p_ptr);
        return res;
 }
 
index 9122535973430edff99e8ee6070a091975dea457..34f12bd4074e49ff8b4c7809bfe0bc706941ec7c 100644 (file)
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err);
 
 void tipc_acknowledge(u32 port_ref, u32 ack);
 
-int tipc_deleteport(u32 portref);
+int tipc_deleteport(struct tipc_port *p_ptr);
 
 int tipc_portimportance(u32 portref, unsigned int *importance);
 int tipc_set_portimportance(u32 portref, unsigned int importance);
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
 int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
 int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
 
-int tipc_publish(u32 portref, unsigned int scope,
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
                 struct tipc_name_seq const *name_seq);
-int tipc_withdraw(u32 portref, unsigned int scope,
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
                  struct tipc_name_seq const *name_seq);
 
 int tipc_connect(u32 portref, struct tipc_portid const *port);
index 3b61851bb9276ec733f7ab8c9d2179a5dd7fef4d..e741416d1d24d4655cd4096b07f84cd978c90cc7 100644 (file)
@@ -354,7 +354,7 @@ static int release(struct socket *sock)
         * Delete TIPC port; this ensures no more messages are queued
         * (also disconnects an active connection & sends a 'FIN-' to peer)
         */
-       res = tipc_deleteport(tport->ref);
+       res = tipc_deleteport(tport);
 
        /* Discard any remaining (connection-based) messages in receive queue */
        __skb_queue_purge(&sk->sk_receive_queue);
@@ -386,30 +386,46 @@ static int release(struct socket *sock)
  */
 static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
 {
+       struct sock *sk = sock->sk;
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
+       struct tipc_port *tport = tipc_sk_port(sock->sk);
+       int res = -EINVAL;
 
-       if (unlikely(!uaddr_len))
-               return tipc_withdraw(portref, 0, NULL);
+       lock_sock(sk);
+       if (unlikely(!uaddr_len)) {
+               res = tipc_withdraw(tport, 0, NULL);
+               goto exit;
+       }
 
-       if (uaddr_len < sizeof(struct sockaddr_tipc))
-               return -EINVAL;
-       if (addr->family != AF_TIPC)
-               return -EAFNOSUPPORT;
+       if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+               res = -EINVAL;
+               goto exit;
+       }
+       if (addr->family != AF_TIPC) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if (addr->addrtype == TIPC_ADDR_NAME)
                addr->addr.nameseq.upper = addr->addr.nameseq.lower;
-       else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
-               return -EAFNOSUPPORT;
+       else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
            (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
-           (addr->addr.nameseq.type != TIPC_CFG_SRV))
-               return -EACCES;
+           (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
+               res = -EACCES;
+               goto exit;
+       }
 
-       return (addr->scope > 0) ?
-               tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+       res = (addr->scope > 0) ?
+               tipc_publish(tport, addr->scope, &addr->addr.nameseq) :
+               tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq);
+exit:
+       release_sock(sk);
+       return res;
 }
 
 /**
index a271c27fac774ce987c0db6f1330ffbfca6dc7f7..722da616438cd1e933fb4d5e60a2c4846f44d186 100644 (file)
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
        /* find payload start allowing for extended bitmap(s) */
 
        if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+               if ((unsigned long)iterator->_arg -
+                   (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+                   (unsigned long)iterator->_max_length)
+                       return -EINVAL;
                while (get_unaligned_le32(iterator->_arg) &
                                        (1 << IEEE80211_RADIOTAP_EXT)) {
                        iterator->_arg += sizeof(uint32_t);
index 65f800890d70d857c9b42d379caad887f5a98c74..d3c5bd7c6b513cd376a2e37857cb8f19919b5a43 100644 (file)
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 #endif
 
+       if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+                                      wdev->ssid, wdev->ssid_len,
+                                      WLAN_CAPABILITY_ESS,
+                                      WLAN_CAPABILITY_ESS);
+               if (bss)
+                       cfg80211_hold_bss(bss_from_pub(bss));
+       }
+
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                return;
        }
 
-       if (!bss) {
-               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-                                      wdev->ssid, wdev->ssid_len,
-                                      WLAN_CAPABILITY_ESS,
-                                      WLAN_CAPABILITY_ESS);
-               if (WARN_ON(!bss))
-                       return;
-               cfg80211_hold_bss(bss_from_pub(bss));
-       }
+       if (WARN_ON(!bss))
+               return;
 
        wdev->current_bss = bss_from_pub(bss);
 
index 6625699f497c7f3889f7b82b325a315c9e51774a..57b0b49f4e6e23a9c6dd974e3f9dd78664f1f59a 100644 (file)
@@ -234,6 +234,14 @@ static int inode_alloc_security(struct inode *inode)
        return 0;
 }
 
+static void inode_free_rcu(struct rcu_head *head)
+{
+       struct inode_security_struct *isec;
+
+       isec = container_of(head, struct inode_security_struct, rcu);
+       kmem_cache_free(sel_inode_cache, isec);
+}
+
 static void inode_free_security(struct inode *inode)
 {
        struct inode_security_struct *isec = inode->i_security;
@@ -244,8 +252,16 @@ static void inode_free_security(struct inode *inode)
                list_del_init(&isec->list);
        spin_unlock(&sbsec->isec_lock);
 
-       inode->i_security = NULL;
-       kmem_cache_free(sel_inode_cache, isec);
+       /*
+        * The inode may still be referenced in a path walk and
+        * a call to selinux_inode_permission() can be made
+        * after inode_free_security() is called. Ideally, the VFS
+        * wouldn't do this, but fixing that is a much harder
+        * job. For now, simply free the i_security via RCU, and
+        * leave the current inode->i_security pointer intact.
+        * The inode will be freed after the RCU grace period too.
+        */
+       call_rcu(&isec->rcu, inode_free_rcu);
 }
 
 static int file_alloc_security(struct file *file)
index b1dfe104945078ead53647c247c46aa6134fac2e..078e553f52f27a03ab83490f20bb2353782d2ef2 100644 (file)
@@ -38,7 +38,10 @@ struct task_security_struct {
 
 struct inode_security_struct {
        struct inode *inode;    /* back pointer to inode object */
-       struct list_head list;  /* list of inode_security_struct */
+       union {
+               struct list_head list;  /* list of inode_security_struct */
+               struct rcu_head rcu;    /* for freeing the inode_security_struct */
+       };
        u32 task_sid;           /* SID of creating task */
        u32 sid;                /* SID of this object */
        u16 sclass;             /* security class of this object */
index 3449c1e909ae10c71a695f6dc2eedecba9e8c163..7ac745df1412689c6adf0bf246399870b79e44e7 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 static void devm_component_release(struct device *dev, void *res)
 {
@@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
        return ret;
 }
 EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
+
+#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
+
+static void devm_dmaengine_pcm_release(struct device *dev, void *res)
+{
+       snd_dmaengine_pcm_unregister(*(struct device **)res);
+}
+
+/**
+ * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
+ * @dev: The parent device for the PCM device
+ * @config: Platform specific PCM configuration
+ * @flags: Platform specific quirks
+ *
+ * Register a dmaengine based PCM device with automatic unregistration when the
+ * device is unregistered.
+ */
+int devm_snd_dmaengine_pcm_register(struct device *dev,
+       const struct snd_dmaengine_pcm_config *config, unsigned int flags)
+{
+       struct device **ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = snd_dmaengine_pcm_register(dev, config, flags);
+       if (ret == 0) {
+               *ptr = dev;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register);
+
+#endif
index 41949af3baaed2580dae2df585222339ade75208..7483922f6ee3f4f8a523b05a00f8ce1f1e2a94e2 100644 (file)
@@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
        hw.buffer_bytes_max = SIZE_MAX;
        hw.fifo_size = dma_data->fifo_size;
 
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
+               hw.info |= SNDRV_PCM_INFO_BATCH;
+
        ret = dma_get_slave_caps(chan, &dma_caps);
        if (ret == 0) {
                if (dma_caps.cmd_pause)
@@ -284,25 +287,54 @@ static const char * const dmaengine_pcm_dma_channel_names[] = {
        [SNDRV_PCM_STREAM_CAPTURE] = "rx",
 };
 
-static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
-       struct device *dev)
+static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
+       struct device *dev, const struct snd_dmaengine_pcm_config *config)
 {
        unsigned int i;
+       const char *name;
+       struct dma_chan *chan;
 
        if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
                           SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
            !dev->of_node)
-               return;
+               return 0;
+
+       if (config->dma_dev) {
+               /*
+                * If this warning is seen, it probably means that your Linux
+                * device structure does not match your HW device structure.
+                * It would be best to refactor the Linux device structure to
+                * correctly match the HW structure.
+                */
+               dev_warn(dev, "DMA channels sourced from device %s",
+                        dev_name(config->dma_dev));
+               dev = config->dma_dev;
+       }
 
-       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
-               pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
-               pcm->chan[1] = pcm->chan[0];
-       } else {
-               for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-                       pcm->chan[i] = dma_request_slave_channel(dev,
-                                       dmaengine_pcm_dma_channel_names[i]);
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       name = "rx-tx";
+               else
+                       name = dmaengine_pcm_dma_channel_names[i];
+               if (config->chan_names[i])
+                       name = config->chan_names[i];
+               chan = dma_request_slave_channel_reason(dev, name);
+               if (IS_ERR(chan)) {
+                       if (PTR_ERR(chan) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       pcm->chan[i] = NULL;
+               } else {
+                       pcm->chan[i] = chan;
                }
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
        }
+
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+               pcm->chan[1] = pcm->chan[0];
+
+       return 0;
 }
 
 static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
@@ -338,7 +370,9 @@ int snd_dmaengine_pcm_register(struct device *dev,
        pcm->config = config;
        pcm->flags = flags;
 
-       dmaengine_pcm_request_chan_of(pcm, dev);
+       ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
+       if (ret)
+               goto err_free_dma;
 
        if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
                ret = snd_soc_add_platform(dev, &pcm->platform,
index 8fc653ca3ab40b3ef04d1a58723a2466086ab8ff..896292bb853f9565d2083adb491d6929f1225db4 100644 (file)
@@ -1,6 +1,8 @@
 config SND_SOC_TEGRA
        tristate "SoC Audio for the Tegra System-on-Chip"
        depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
+       depends on COMMON_CLK
+       depends on RESET_CONTROLLER
        select REGMAP_MMIO
        select SND_SOC_GENERIC_DMAENGINE_PCM
        help
index ae27bcd586d25428458c305c16448395b9f74d88..d8b98d70ff41b8ef7362428c7ff7534bb2034186 100644 (file)
@@ -313,7 +313,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
 {
        struct tegra20_ac97 *ac97;
        struct resource *mem;
-       u32 of_dma[2];
        void __iomem *regs;
        int ret = 0;
 
@@ -348,14 +347,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
                goto err_clk_put;
        }
 
-       if (of_property_read_u32_array(pdev->dev.of_node,
-                                      "nvidia,dma-request-selector",
-                                      of_dma, 2) < 0) {
-               dev_err(&pdev->dev, "No DMA resource\n");
-               ret = -ENODEV;
-               goto err_clk_put;
-       }
-
        ac97->reset_gpio = of_get_named_gpio(pdev->dev.of_node,
                                             "nvidia,codec-reset-gpio", 0);
        if (gpio_is_valid(ac97->reset_gpio)) {
@@ -380,12 +371,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
        ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1;
        ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        ac97->capture_dma_data.maxburst = 4;
-       ac97->capture_dma_data.slave_id = of_dma[1];
 
        ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
        ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        ac97->playback_dma_data.maxburst = 4;
-       ac97->playback_dma_data.slave_id = of_dma[1];
 
        ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev);
        if (ret)
index 8c819f8114708f7a94e33929a04ebecbdf3e2ffc..42c1f6bfaf2e5bb2a4f2df89269be672b26e377c 100644 (file)
@@ -339,9 +339,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = {
 static int tegra20_i2s_platform_probe(struct platform_device *pdev)
 {
        struct tegra20_i2s *i2s;
-       struct resource *mem, *memregion, *dmareq;
-       u32 of_dma[2];
-       u32 dma_ch;
+       struct resource *mem, *memregion;
        void __iomem *regs;
        int ret;
 
@@ -370,20 +368,6 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
                goto err_clk_put;
        }
 
-       dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!dmareq) {
-               if (of_property_read_u32_array(pdev->dev.of_node,
-                                       "nvidia,dma-request-selector",
-                                       of_dma, 2) < 0) {
-                       dev_err(&pdev->dev, "No DMA resource\n");
-                       ret = -ENODEV;
-                       goto err_clk_put;
-               }
-               dma_ch = of_dma[1];
-       } else {
-               dma_ch = dmareq->start;
-       }
-
        memregion = devm_request_mem_region(&pdev->dev, mem->start,
                                            resource_size(mem), DRV_NAME);
        if (!memregion) {
@@ -410,12 +394,10 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
        i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
        i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        i2s->capture_dma_data.maxburst = 4;
-       i2s->capture_dma_data.slave_id = dma_ch;
 
        i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
        i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        i2s->playback_dma_data.maxburst = 4;
-       i2s->playback_dma_data.slave_id = dma_ch;
 
        pm_runtime_enable(&pdev->dev);
        if (!pm_runtime_enabled(&pdev->dev)) {
index 31154338c1eb742da6a1342310d81fddb1f9ecd4..d6f4c9940e0c64fee63b1e447ba11b40a5cfc2d1 100644 (file)
@@ -24,8 +24,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
-#include <linux/clk/tegra.h>
 #include <sound/soc.h>
 #include "tegra30_ahub.h"
 
@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
 }
 
 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
-                                 dma_addr_t *fiforeg,
-                                 unsigned int *reqsel)
+                                 char *dmachan, int dmachan_len,
+                                 dma_addr_t *fiforeg)
 {
        int channel;
        u32 reg, val;
@@ -110,9 +110,11 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
        __set_bit(channel, ahub->rx_usage);
 
        *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel;
+       snprintf(dmachan, dmachan_len, "rx%d", channel);
        *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO +
                   (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE);
-       *reqsel = ahub->dma_sel + channel;
+
+       pm_runtime_get_sync(ahub->dev);
 
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
@@ -140,6 +142,8 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
              (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
        ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_rx_fifo);
@@ -149,12 +153,16 @@ int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
        int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
        int reg, val;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
        val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
        tegra30_apbif_write(reg, val);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_rx_fifo);
@@ -164,12 +172,16 @@ int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
        int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
        int reg, val;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
        val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
        tegra30_apbif_write(reg, val);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_rx_fifo);
@@ -185,8 +197,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
 EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
 
 int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
-                                 dma_addr_t *fiforeg,
-                                 unsigned int *reqsel)
+                                 char *dmachan, int dmachan_len,
+                                 dma_addr_t *fiforeg)
 {
        int channel;
        u32 reg, val;
@@ -200,9 +212,11 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
        __set_bit(channel, ahub->tx_usage);
 
        *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel;
+       snprintf(dmachan, dmachan_len, "tx%d", channel);
        *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO +
                   (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE);
-       *reqsel = ahub->dma_sel + channel;
+
+       pm_runtime_get_sync(ahub->dev);
 
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
@@ -230,6 +244,8 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
              (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
        ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_allocate_tx_fifo);
@@ -239,12 +255,16 @@ int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif)
        int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
        int reg, val;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
        val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
        tegra30_apbif_write(reg, val);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_enable_tx_fifo);
@@ -254,12 +274,16 @@ int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif)
        int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
        int reg, val;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_CHANNEL_CTRL +
              (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
        val = tegra30_apbif_read(reg);
        val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
        tegra30_apbif_write(reg, val);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_disable_tx_fifo);
@@ -280,10 +304,14 @@ int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
        int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
        int reg;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_AUDIO_RX +
              (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
        tegra30_audio_write(reg, 1 << txcif);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_set_rx_cif_source);
@@ -293,35 +321,51 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
        int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
        int reg;
 
+       pm_runtime_get_sync(ahub->dev);
+
        reg = TEGRA30_AHUB_AUDIO_RX +
              (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
        tegra30_audio_write(reg, 0);
 
+       pm_runtime_put(ahub->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
 
-#define CLK_LIST_MASK_TEGRA30  BIT(0)
-#define CLK_LIST_MASK_TEGRA114 BIT(1)
+#define MOD_LIST_MASK_TEGRA30  BIT(0)
+#define MOD_LIST_MASK_TEGRA114 BIT(1)
+#define MOD_LIST_MASK_TEGRA124 BIT(2)
 
-#define CLK_LIST_MASK_TEGRA30_OR_LATER \
-               (CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114)
+#define MOD_LIST_MASK_TEGRA30_OR_LATER \
+               (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \
+                       MOD_LIST_MASK_TEGRA124)
+#define MOD_LIST_MASK_TEGRA114_OR_LATER \
+               (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124)
 
 static const struct {
-       const char *clk_name;
-       u32 clk_list_mask;
-} configlink_clocks[] = {
-       { "i2s0", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "i2s1", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "i2s2", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "i2s3", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "i2s4", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "dam0", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "dam1", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "dam2", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "spdif_in", CLK_LIST_MASK_TEGRA30_OR_LATER },
-       { "amx", CLK_LIST_MASK_TEGRA114 },
-       { "adx", CLK_LIST_MASK_TEGRA114 },
+       const char *rst_name;
+       u32 mod_list_mask;
+} configlink_mods[] = {
+       { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER },
+       { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER },
+       { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER },
+       { "amx1", MOD_LIST_MASK_TEGRA124 },
+       { "adx1", MOD_LIST_MASK_TEGRA124 },
+       { "afc0", MOD_LIST_MASK_TEGRA124 },
+       { "afc1", MOD_LIST_MASK_TEGRA124 },
+       { "afc2", MOD_LIST_MASK_TEGRA124 },
+       { "afc3", MOD_LIST_MASK_TEGRA124 },
+       { "afc4", MOD_LIST_MASK_TEGRA124 },
+       { "afc5", MOD_LIST_MASK_TEGRA124 },
 };
 
 #define LAST_REG(name) \
@@ -450,17 +494,17 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
 };
 
 static struct tegra30_ahub_soc_data soc_data_tegra30 = {
-       .clk_list_mask = CLK_LIST_MASK_TEGRA30,
+       .mod_list_mask = MOD_LIST_MASK_TEGRA30,
        .set_audio_cif = tegra30_ahub_set_cif,
 };
 
 static struct tegra30_ahub_soc_data soc_data_tegra114 = {
-       .clk_list_mask = CLK_LIST_MASK_TEGRA114,
+       .mod_list_mask = MOD_LIST_MASK_TEGRA114,
        .set_audio_cif = tegra30_ahub_set_cif,
 };
 
 static struct tegra30_ahub_soc_data soc_data_tegra124 = {
-       .clk_list_mask = CLK_LIST_MASK_TEGRA114,
+       .mod_list_mask = MOD_LIST_MASK_TEGRA124,
        .set_audio_cif = tegra124_ahub_set_cif,
 };
 
@@ -475,10 +519,9 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match;
        const struct tegra30_ahub_soc_data *soc_data;
-       struct clk *clk;
+       struct reset_control *rst;
        int i;
        struct resource *res0, *res1, *region;
-       u32 of_dma[2];
        void __iomem *regs_apbif, *regs_ahub;
        int ret = 0;
 
@@ -495,19 +538,24 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
         * operate correctly, all devices on this bus must be out of reset.
         * Ensure that here.
         */
-       for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
-               if (!(configlink_clocks[i].clk_list_mask &
-                                       soc_data->clk_list_mask))
+       for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) {
+               if (!(configlink_mods[i].mod_list_mask &
+                                       soc_data->mod_list_mask))
                        continue;
-               clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name);
-               if (IS_ERR(clk)) {
-                       dev_err(&pdev->dev, "Can't get clock %s\n",
-                               configlink_clocks[i].clk_name);
-                       ret = PTR_ERR(clk);
+
+               rst = reset_control_get(&pdev->dev,
+                                       configlink_mods[i].rst_name);
+               if (IS_ERR(rst)) {
+                       dev_err(&pdev->dev, "Can't get reset %s\n",
+                               configlink_mods[i].rst_name);
+                       ret = PTR_ERR(rst);
                        goto err;
                }
-               tegra_periph_reset_deassert(clk);
-               clk_put(clk);
+
+               ret = reset_control_deassert(rst);
+               reset_control_put(rst);
+               if (ret)
+                       goto err;
        }
 
        ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
@@ -536,16 +584,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
                goto err_clk_put_d_audio;
        }
 
-       if (of_property_read_u32_array(pdev->dev.of_node,
-                               "nvidia,dma-request-selector",
-                               of_dma, 2) < 0) {
-               dev_err(&pdev->dev,
-                       "Missing property nvidia,dma-request-selector\n");
-               ret = -ENODEV;
-               goto err_clk_put_d_audio;
-       }
-       ahub->dma_sel = of_dma[1];
-
        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res0) {
                dev_err(&pdev->dev, "No apbif memory resource\n");
index d67321d90faa1f5e828e0bca0a5ccc331539f47b..fd7ba75ed814733ccfcb7e1e837b9132b0329ffd 100644 (file)
@@ -465,15 +465,15 @@ enum tegra30_ahub_rxcif {
 };
 
 extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
-                                        dma_addr_t *fiforeg,
-                                        unsigned int *reqsel);
+                                        char *dmachan, int dmachan_len,
+                                        dma_addr_t *fiforeg);
 extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 
 extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
-                                        dma_addr_t *fiforeg,
-                                        unsigned int *reqsel);
+                                        char *dmachan, int dmachan_len,
+                                        dma_addr_t *fiforeg);
 extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
@@ -502,7 +502,7 @@ void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
                           struct tegra30_ahub_cif_conf *conf);
 
 struct tegra30_ahub_soc_data {
-       u32 clk_list_mask;
+       u32 mod_list_mask;
        void (*set_audio_cif)(struct regmap *regmap,
                              unsigned int reg,
                              struct tegra30_ahub_cif_conf *conf);
@@ -524,7 +524,6 @@ struct tegra30_ahub {
        struct device *dev;
        struct clk *clk_d_audio;
        struct clk *clk_apbif;
-       int dma_sel;
        resource_size_t apbif_addr;
        struct regmap *regmap_apbif;
        struct regmap *regmap_ahub;
index 02247fee1cf7e1450fb4bbcdf2e58cf5ee76c7e8..49ad9366add86b008823f6091315d74d78f13aeb 100644 (file)
@@ -73,47 +73,6 @@ static int tegra30_i2s_runtime_resume(struct device *dev)
        return 0;
 }
 
-static int tegra30_i2s_startup(struct snd_pcm_substream *substream,
-                       struct snd_soc_dai *dai)
-{
-       struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       int ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
-                                       &i2s->playback_dma_data.addr,
-                                       &i2s->playback_dma_data.slave_id);
-               i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-               i2s->playback_dma_data.maxburst = 4;
-               tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
-                                              i2s->playback_fifo_cif);
-       } else {
-               ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
-                                       &i2s->capture_dma_data.addr,
-                                       &i2s->capture_dma_data.slave_id);
-               i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-               i2s->capture_dma_data.maxburst = 4;
-               tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
-                                              i2s->capture_i2s_cif);
-       }
-
-       return ret;
-}
-
-static void tegra30_i2s_shutdown(struct snd_pcm_substream *substream,
-                       struct snd_soc_dai *dai)
-{
-       struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
-               tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
-       } else {
-               tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
-               tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
-       }
-}
-
 static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
@@ -317,8 +276,6 @@ static int tegra30_i2s_probe(struct snd_soc_dai *dai)
 }
 
 static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
-       .startup        = tegra30_i2s_startup,
-       .shutdown       = tegra30_i2s_shutdown,
        .set_fmt        = tegra30_i2s_set_fmt,
        .hw_params      = tegra30_i2s_hw_params,
        .trigger        = tegra30_i2s_trigger,
@@ -499,15 +456,51 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
                        goto err_pm_disable;
        }
 
+       i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       i2s->playback_dma_data.maxburst = 4;
+       ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
+                                           i2s->playback_dma_chan,
+                                           sizeof(i2s->playback_dma_chan),
+                                           &i2s->playback_dma_data.addr);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not alloc TX FIFO: %d\n", ret);
+               goto err_suspend;
+       }
+       ret = tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
+                                            i2s->playback_fifo_cif);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not route TX FIFO: %d\n", ret);
+               goto err_free_tx_fifo;
+       }
+
+       i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       i2s->capture_dma_data.maxburst = 4;
+       ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
+                                           i2s->capture_dma_chan,
+                                           sizeof(i2s->capture_dma_chan),
+                                           &i2s->capture_dma_data.addr);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not alloc RX FIFO: %d\n", ret);
+               goto err_unroute_tx_fifo;
+       }
+       ret = tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
+                                            i2s->capture_i2s_cif);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not route TX FIFO: %d\n", ret);
+               goto err_free_rx_fifo;
+       }
+
        ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
                                   &i2s->dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
-               goto err_suspend;
+               goto err_unroute_rx_fifo;
        }
 
-       ret = tegra_pcm_platform_register(&pdev->dev);
+       ret = tegra_pcm_platform_register_with_chan_names(&pdev->dev,
+                               &i2s->dma_config, i2s->playback_dma_chan,
+                               i2s->capture_dma_chan);
        if (ret) {
                dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
                goto err_unregister_component;
@@ -517,6 +510,14 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 
 err_unregister_component:
        snd_soc_unregister_component(&pdev->dev);
+err_unroute_rx_fifo:
+       tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
+err_free_rx_fifo:
+       tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
+err_unroute_tx_fifo:
+       tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
+err_free_tx_fifo:
+       tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
 err_suspend:
        if (!pm_runtime_status_suspended(&pdev->dev))
                tegra30_i2s_runtime_suspend(&pdev->dev);
@@ -539,6 +540,12 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
        tegra_pcm_platform_unregister(&pdev->dev);
        snd_soc_unregister_component(&pdev->dev);
 
+       tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
+       tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
+
+       tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
+       tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
+
        clk_put(i2s->clk_i2s);
 
        return 0;
index 4d0b0a30dbfb341c8a2a93b00485f2d3fb826f18..774fc6ad202697efaa7d3417d1fc48612934b59f 100644 (file)
@@ -238,11 +238,14 @@ struct tegra30_i2s {
        struct clk *clk_i2s;
        enum tegra30_ahub_txcif capture_i2s_cif;
        enum tegra30_ahub_rxcif capture_fifo_cif;
+       char capture_dma_chan[8];
        struct snd_dmaengine_dai_dma_data capture_dma_data;
        enum tegra30_ahub_rxcif playback_i2s_cif;
        enum tegra30_ahub_txcif playback_fifo_cif;
+       char playback_dma_chan[8];
        struct snd_dmaengine_dai_dma_data playback_dma_data;
        struct regmap *regmap;
+       struct snd_dmaengine_pcm_config dma_config;
 };
 
 #endif
index 7b2d23ba69b3bf397ba3fb963feb2d3d2b5948af..7ce5c334a660ed043f8a8f1700cf1d5aa928a93a 100644 (file)
@@ -61,12 +61,23 @@ static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = {
 
 int tegra_pcm_platform_register(struct device *dev)
 {
-       return snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config,
-                       SND_DMAENGINE_PCM_FLAG_NO_DT |
-                       SND_DMAENGINE_PCM_FLAG_COMPAT);
+       return snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config, 0);
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
 
+int tegra_pcm_platform_register_with_chan_names(struct device *dev,
+                               struct snd_dmaengine_pcm_config *config,
+                               char *txdmachan, char *rxdmachan)
+{
+       *config = tegra_dmaengine_pcm_config;
+       config->dma_dev = dev->parent;
+       config->chan_names[0] = txdmachan;
+       config->chan_names[1] = rxdmachan;
+
+       return snd_dmaengine_pcm_register(dev, config, 0);
+}
+EXPORT_SYMBOL_GPL(tegra_pcm_platform_register_with_chan_names);
+
 void tegra_pcm_platform_unregister(struct device *dev)
 {
        return snd_dmaengine_pcm_unregister(dev);
index 68ad901714a9d5ca6a95f71a8227ecbdf763ff09..7883dec748a316cfc445c87832323c185d70bcd2 100644 (file)
 #ifndef __TEGRA_PCM_H__
 #define __TEGRA_PCM_H__
 
+struct snd_dmaengine_pcm_config;
+
 int tegra_pcm_platform_register(struct device *dev);
+int tegra_pcm_platform_register_with_chan_names(struct device *dev,
+                               struct snd_dmaengine_pcm_config *config,
+                               char *txdmachan, char *rxdmachan);
 void tegra_pcm_platform_unregister(struct device *dev);
 
 #endif